Django duplicate key value violates unique constraint error model form - django

I have a legacy DB on PostgreSQL with a simple products table with 2 columns (productid, productname) with 70 products. I am trying to start using Django as a frontend and I have the model as below and a model form. The save process is failing with the error below.
duplicate key value violates unique constraint "productidentifier"
DETAIL: Key (productid)=(4) already exists.
Could anyone help correct the error. I have confirmed on the Postgres table that the index get sequence is set right, expected value should be 72. See below the model, form and view.
#models.py
class Products(models.Model):
productid = models.AutoField(primary_key=True)
productname = models.TextField(verbose_name='Product Name')
class Meta:
managed = False
#Views.py
def new_product(request):
if request.method == 'POST':
form= forms.EditProductForm(request.POST)
if form.is_valid():
product = form.save()
return redirect('views.full_product_list')
else:
form = forms.EditProductForm()
return render(request, 'edit_product.html', {'form': form})
#forms.py
class EditProductForm(forms.ModelForm):
productname = forms.CharField(widget=forms.TextInput(attrs={'class':'form-control'}))
class Meta:
model = models.Products
fields = ('productname')

There is propably some issue with your auto field sequence. You can use ./manage.py sqlsequencereset to fix that. It will generate SQL queries to fix sequence on your tables.

Related

Fill Foreign Key Field in Form Field with Related Record in Django

I have 2 models Office & Meeting.
class Office(models.Model):
name = models.CharField(verbose_name=u"name",max_length=255)
class Meeting(models.Model):
meeting_office = models.ForeignKey(Registration,verbose_name=u"Office", on_delete=models.DO_NOTHING, related_name='meeting_office')
date = models.DateField(verbose_name=u"Date", null=False, blank=False)
I have a form that creates the blank meeting successfully
class MeetingForm(ModelForm):
class Meta:
model = Meeting
fields = (
'date',
'meeting_office'
)
widgets = {
'date' :forms.DateInput(attrs={'type': 'date'}),
'meeting_office' :forms.Select(attrs={'class': 'form-control'}),
When I want to have a prefilled form, i have a view that is below
def office_add_meeting(request, office_id):
print("office_id"+ office_id) # produces correct foreign key
office = Office.objects.get(pk=office_id)
form = MeetingForm(request.POST or None)
if form.is_valid():
form.instance.meeting_office = office
form.save()
messages.success(request, "Insert Successfull")
return HttpResponseRedirect('/office_main')
return render(request,
'Office/meeting-form.html',
{"form": form,
"office_id": office_id})
But the form does not prefill the foreign key field. Confirmed the office_id has been passed to the view successfully. Idon't see why the form is not using the defined instance. Any ideas what could be causing this? Or is there a better way?
To set the initial fields on a form, you can use a dictionary matching to the attribute names of the fields.
Try the following:
form = MeetingForm(initial={"meeting_office":your_office})
For editing existing forms, you can also use:
my_meeting = Meeting.objects.all().first() # Example of model
MeetingForm(instance=my_meeting) # Also use instance where you're accepting the form.

Django 1054 Unknown Field error

I'm attempting to add a new foreign key to an existing model of mine, but I'm having issues getting it to save the values from the UI. When I get to the relevant page, the data populates correctly, but when I attempt to save a change of the foreign key I get a 1054 "Unknown column 'schedule_id' in 'field list'" error. Strangely, if I refresh the page, the changes were saved regardless of the error.
Relevant models:
class Group(BaseModel):
code = CharField()
name = CharField()
calendar = models.ForeignKey(Calendar)
schedule = models.ForeignKey(Schedule, null=True, blank=True, default=None) # this is the new FK
class Schedule(BaseModel):
code = CharField()
name = CharField()
description = CharField()
#various integer fields
I'm using South for my database migrations:
def forwards(self, orm):
db.add_column('group', 'schedule',
self.gf('django.db.models.fields.related.ForeignKey')\
(to=orm['app.Schedule'], blank=True, null=True)\
)
The view is pretty simple:
def api_group(jsonDict, request):
if request.method == "POST":
#other handlers
elif operation == "edit":
_update_group(request)
def _update_group(request):
group = Group.objects.get(id=request.POST.get('id'))
formData = request.POST.copy()
form = GroupForm(formData, instance=group)
if form.is_valid():
form.save()
class GroupForm(renderutils.BaseModelForm):
id = forms.CharField(widget=forms.HiddenInput())
class Meta(renderutils.BaseModelForm.Meta):
model = Group
When I look at the 'group' table, I can see the field named 'schedule_id' and correct values are getting assigned on save, I just don't understand why the error is being raised if nothing is going wrong? I've tried doing a backward and forward south migration multiple times to make sure it wasn't something wrong with it.

Changing primary key in a form creates two entries in DB, one with old primary key and other with new primary key

Code:
Model:
class Machines(models.Model):
name = models.CharField(max_length=100, verbose_name="hostname", help_text="Host name of the machine")
ip_addr = models.CharField(max_length=50, primary_key=True, help_text="IP address of the machine")
.... have many other fields.
Form:
Using forms.ModelForm to create a form
View:
def save(request):
if request.method == "POST":
ip = request.POST.get("ip")
machine = get_object_or_404(Machines, ip_addr=ip)
form = MachineForm(instance=machine, data=request.POST)
if form.is_valid():
if form.has_changed():
form.save()
context = {"message": "Updated successfully"}
else:
context = {"message": "No data to update"}
return render_to_response("edit.html", context, context_instance=RequestContext(request))
If I change "name" field, form.save() updates the current object properly. But, if I change "ip_addr" field which is primary key, form.save() creates two entries one with old primary key other with new primary key.
If we do same in MySQL(BTW, I am using MySQL as DB)
update machines_table set ip_addr="10.1.1.1" where ip_addr="10.1.1.2";
It works fine, there will not be any duplicate entry.
Can you please help me out.
What you're doing is updating private key. Django creates new instance in this case. It is is actually Django's way to copy a record. The INSERT not UPDATE query is performed by ORM.
If you change your code to:
class Machines(models.Model):
…
ip_addr = models.CharField(max_length=50, unique=True, …
…
Django will interprete your edit action correctly as the primary key won't change.
Next time use django-debug-toolbar to see what query is performed by Django ORM.

Getting an error while using Django Model Form in views.py

In my models.py
class Alert(models.Model):
user = models.CharField(max_length=30, blank=True)
a = models.IntegerField(blank=True)
def __unicode__(self):
return "'%s' at %s" % (self.user)
In My forms.py:
class AlertForm(forms.ModelForm):
class Meta:
model=Alert
fields = ('a','user')
widgets = {
'user': forms.HiddenInput()
}
AlertCountFormset = modelformset_factory(Alert,
form = AlertForm)
In my views.py:
def profile_setting(request, slug):
if request.method == 'GET':
form = AlertForm(request.POST)
if form.is_valid():
alert_form = form.save(commit=False)
alert_form.user = request.user.username
alert_form.save() # Here i am getting the error
return HttpResponseRedirect('/user/list')
extra_context = {
'form': AlertForm()
}
return direct_to_template(request,'users/profile_setting.html',
extra_context)
I am trying to fill the Django model Form but i am getting following error where i had put the comment:
events_alertcount.a may not be NULL
What is this? Even after putting thenull=True in the field of a it shows an same error. Is that something wrong with my forms.py or models.py?
This is enforced on database level, too. Set your "a" column in your db to allow the field to be NULL. This should fix it. HTH.
try this:
a = models.IntegerField(blank=True, null=True)
and you should call syncdb once again
When defining a model field, the blank option is validation related, meaning that if you set blank to true, validation will not fail if that field is not filled in.
blank is validation-related. If a field has blank=True, validation on Django’s admin site will allow entry of an empty value. If a field has blank=False, the field will be required.
However, if validation doesn't fail and you save the model, the field will be persisted to the database. Now, a field cannot be null in the database unless you set the null option to true.
null is purely database-related, whereas blank is validation-related.
Having said that, you can fix you error by adding the null option to Alert.a:
a = models.IntegerField(blank=True, null=True)
Now, if you've already ran the syncdb command, you need to drop your tables and then rerun syncdb in order for this change to be picked up. If this database is a production database and you cannot do this, look into django-south on how you can migrate your schemas and data.

django forms give: Select a valid choice. That choice is not one of the available choices

I am unable to catch the values from the unit_id after the selection is done by the user and data is posted. Can someone help me to solve this.
The values of the unit_id drop down list is obtained from another database table (LiveDataFeed). And once a value is selected and form posted, it gives the error:
Select a valid choice. That choice is not one of the available choices.
Here is the implementation:
in models.py:
class CommandData(models.Model):
unit_id = models.CharField(max_length=50)
command = models.CharField(max_length=50)
communication_via = models.CharField(max_length=50)
datetime = models.DateTimeField()
status = models.CharField(max_length=50, choices=COMMAND_STATUS)
In views.py:
class CommandSubmitForm(ModelForm):
iquery = LiveDataFeed.objects.values_list('unit_id', flat=True).distinct()
unit_id = forms.ModelChoiceField(queryset=iquery, empty_label='None',
required=False, widget=forms.Select())
class Meta:
model = CommandData
fields = ('unit_id', 'command', 'communication_via')
def CommandSubmit(request):
if request.method == 'POST':
form = CommandSubmitForm(request.POST)
if form.is_valid():
form.save()
return HttpResponsRedirect('/')
else:
form = CommandSubmitForm()
return render_to_response('command_send.html', {'form': form},
context_instance=RequestContext(request))
You're getting a flat value_list back which will just be a list of the ids, but when you do that, you're probably better off using a plain ChoiceField instead of a ModelChoiceField and providing it with a list of tuples, not just ids. For example:
class CommandSubmitForm(ModelForm):
iquery = LiveDataFeed.objects.values_list('unit_id', flat=True).distinct()
iquery_choices = [('', 'None')] + [(id, id) for id in iquery]
unit_id = forms.ChoiceField(iquery_choices,
required=False, widget=forms.Select())
You could also leave it as a ModelChoiceField, and use LiveDataFeed.objects.all() as the queryset, but in order to display the id in the box as well as have it populate for the option values, you'd have to subclass ModelChoiceField to override the label_from_instance method. You can see an example in the docs here.
Before you call form.is_valid(), do the following:
unit_id = request.POST.get('unit_id')
form.fields['unit_id'].choices = [(unit_id, unit_id)]
Now you can call form.is_valid() and your form will validate correctly.