Is there a way to update a unique field in update view?
I have a model that has a name and age field but when I try to update the age without even changing the value of the name, it returns an error that the name already exists in the database
models.py
class MyModel(models.Model)
name = models.CharField(max_length=200, unique=True)
age = models.IntegerField()
views.py
class MyModelUpdateView(UpdateView):
def get(self):
self.object = self.get_object()
my_model = self.object
form = MyModelForm(instance=my_model)
return self.render_to_response(
self.get_context_data(pk=my_model.pk, form=form)
)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
my_model = self.object
form = MyModelForm(data=request.POST, instance=my_model)
if form.is_valid():
form.save()
return some_url
return self.render_to_response(
self.get_context_data(pk=my_model.pk, form=form)
)
forms.py
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
fields = (
'name',
'age',
)
def clean(self):
cleaned_data = super().clean()
if MyModel.objects.filter(
active=True, name=cleaned_data.get('name')
).exists():
raise forms.ValidationError('MyModel already exists.')
return cleaned_data
What am I missing here? Thank you.
Since you update a model, and you do not change the name, of course a record with that name already exists: that specific record. You thus should alter the checking code, to:
class MyModelForm(forms.ModelForm):
def clean(self, *args, **kwargs):
cleaned_data = super().clean(*args, **kwargs)
if MyModel.objects.exclude(pk=self.instance.pk).filter(
active=True, name=cleaned_data.get('name')
).exists():
raise forms.ValidationError('MyModel already exists.')
return cleaned_data
class Meta:
model = MyModel
fields = ('name', 'age')
Please do not alter the boilerplate logic of the UpdateView, you can easily implement this with:
class MyModelUpdateView(UpdateView):
form_class = MyModelForm
success_url = 'some url'
That being said, since if you already have set the field to unique=True, then there is no need to implement the check yourself. It seems here, that you already have a unique=True constraint:
class MyModel(models.Model)
name = models.CharField(max_length=200, unique=True)
age = models.IntegerField()
In that case, you can simply let the ModelForm do the work, so then your form looks like:
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
fields = ('name', 'age')
It is only if you want a more sophisticated uniqness (like with active=True?), and you can not represent it (easily) you should do your own validation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With