8👍
There are two options:
a) Have a try block where you save your model and capture the IntegrityError and deal with it. Something like:
try:
new_accountadmin_form.save()
except IntegrityError:
new_accountadmin_form._errors["account"] = ["some message"]
new_accountadmin_form._errors["is_master"] = ["some message"]
del new_accountadmin_form.cleaned_data["account"]
del new_accountadmin_form.cleaned_data["is_master"]
b) In the clean() method of your form, check if the a row exists and raise a forms.ValidationError
with an appropriate message. Example here.
So, b) it is… That is why I referenced the documentation; all you need is there.
But it would be something like:
class YouForm(forms.Form):
# Everything as before.
...
def clean(self):
""" This is the form's clean method, not a particular field's clean method """
cleaned_data = self.cleaned_data
account = cleaned_data.get("account")
is_master = cleaned_data.get("is_master")
username = cleaned_data.get("username")
if AccountAdmin.objects.filter(account=account, is_master=is_master).count() > 0:
del cleaned_data["account"]
del cleaned_data["is_master"]
raise forms.ValidationError("Account and is_master combination already exists.")
if AccountAdmin.objects.filter(account=account, username=username).count() > 0:
del cleaned_data["account"]
del cleaned_data["username"]
raise forms.ValidationError("Account and username combination already exists.")
# Always return the full collection of cleaned data.
return cleaned_data
For what it is worth – I just realized that your unique_together above is referencing a field called username that is not represented in the model.
The clean method above is called after all clean methods for the individual fields are called.
2👍
And for a completely generic way. In the model have the following two helper fns:
def getField(self,fieldName):
# return the actual field (not the db representation of the field)
try:
return self._meta.get_field_by_name(fieldName)[0]
except models.fields.FieldDoesNotExist:
return None
and
def getUniqueTogether(self):
# returns the set of fields (their names) that must be unique_together
# otherwise returns None
unique_together = self._meta.unique_together
for field_set in unique_together:
return field_set
return None
And in the form have the following fn:
def clean(self):
cleaned_data = self.cleaned_data
instance = self.instance
# work out which fields are unique_together
unique_filter = {}
unique_fields = instance.getUniqueTogether()
if unique_fields:
for unique_field in unique_fields:
field = instance.getField(unique_field)
if field.editable:
# this field shows up in the form,
# so get the value from the form
unique_filter[unique_field] = cleaned_data[unique_field]
else:
# this field is excluded from the form,
# so get the value from the model
unique_filter[unique_field] = getattr(instance,unique_field)
# try to find if any models already exist in the db;
# I find all models and then exlude those matching the current model.
existing_instances = type(instance).objects.filter(**unique_filter).exclude(pk=instance.pk)
if existing_instances:
# if we've gotten to this point,
# then there is a pre-existing model matching the unique filter
# so record the relevant errors
for unique_field in unique_fields:
self.errors[unique_field] = "This value must be unique."
- [Django]-Increase displaying time of django messages
- [Django]-Django-uploadify-s3 and HTTP 403 Error
- [Django]-What is the settings for django rest framework swagger open api security object definition for oauth2 flow being password?
- [Django]-How to make a geography field unique?
- [Django]-Django Haystack + Elasticsearch strange intermittent bug
1👍
Model.Meta.unique_together creates a constraint limited to the database, while ModelForm.is_valid() is primarily based on correct types. Event if it did check constraints you would have a race condition that could still cause an IntegrityError in the save() call.
You probably want to be catching IntegrityError:
if new_accountadmin_form.is_valid():
try:
newaccountadmin_form.save()
except IntegrityError, error:
# here's your error handling code
- [Django]-Where to put Django comments moderation code?
- [Django]-How to stream a file in a request?
- [Django]-Executing tasks with celery at periodic schedule
- [Django]-Python & Django on a Mac: Illegal hardware instruction