Take the 2-minute tour ×

So I'm new to Django...

First some background on how we do things now. We have a custom php system but I am constructing an improved inventory management system in django using only the admin interface. We store part numbers, and it is essential that we do not store duplicates. Part numbers can sometimes be entered with hypens, periods, spaces, etc. We need to be sure that duplicate parts are not added no matter what kind of formatting is entered. With our existing non-django system, we use a regex to strip anything from the string that is not a-zA-Z0-9. The actual entered part number is persisted, and the cleaned number is persisted to the db as well. Then when someone is adding a new part or even searching for a part, this cleaned version of the part number helps to avoid this ambiguity. We do the same for the manufacturer name.

My way of emulating this in django was to add the part_number_clean field along with the part_number field to the model. Then I overrode the save method to calculate the clean part number like so (manufacturer as well):

    self.manufacturer_clean = re.sub(r'[^a-zA-Z0-9]', '', self.manufacturer).lower()
    self.part_number_clean = re.sub(r'[^a-zA-Z0-9]', '', self.part_number).lower()
    super(CatalogProduct, self).save(*args, **kwargs) 

The problem is, I need to unique on a combination of part number and manufacturer:

class Meta:
    unique_together     = ('part_number_clean ', 'manufacturer_clean ')

When I try to save a duplicate record, I get a database integrity violation. So it seems like django is evaluating the unique fields before the save function is called (which makes sense). I just need to know how or which method I should override to calculate these fields BEFORE any validation.

Additionally, I am interested in adding a third field to the unique_together mix that may or may not be filled out. If it is not filled it will just have an empty default value. I hope this will not cause any issues.

It would also be great if when the user tabbed-out of the manufacturer and part number fields, and both were not empty, some js would see if that product exists already, and offer the user the option to click a button and be whisked away to that record, before they waste their time filling out the rest of the data only to find that it already exists. I'm guessing this lies way outside the realm of the admin interface without serious hacking. Is there any way to somehow integrate this with the admin interface? Its working great for me up till now...

share|improve this question

2 Answers 2

up vote 2 down vote accepted

I figured it out. I'm posting the answer for anyone else that is curious. This was actually very simple in the end to implement in the model. All one needs to do is implement (override?) the clean() method of the model. In the method, I calculate and set my special fields, then be sure to call self.validate_unique() after. Works like a charm! No need to raise any exceptions, the form will display the error on top perfectly. Doing this in the save method will not work, as the exception cannot be thrown by your code or django at that point. Here is the code:

class CatalogProduct(models.Model):
    manufacturer        = models.CharField(max_length=100)
    manufacturer_clean  = models.CharField('Manufacturer',max_length=100,blank=True,editable=False)
    part_number         = models.CharField(max_length=100)
    part_number_clean   = models.CharField('Part number',max_length=100,blank=True,editable=False)

    def clean(self):
        # Calculate manufacturer_clean and part_number_clean
share|improve this answer
You can select your own answer –  Enrico Dec 1 '12 at 0:55

The model is only responsible for describing data and how that data should be represented between your Python and database environment. It's because of this atomic role that models don't care about validation and what you've just went in there and introduced it.

You need a model form. It can clean the manufacturer and part number and also ensure that uniqueness constraints are satisfied as part of the validation process.

share|improve this answer
seems that kind of thing is used in regular pages... i'm trying to accomplish this in the admin interface. is there a way to do it? –  Brett Nov 30 '12 at 16:35
Yes. Your admin class can specify a custom form that does the validation you need. –  Brandon Nov 30 '12 at 18:02
now im trying to figure out what i need to override. a modelform? or just a form? is there any way to override the form but just to override the validation routine and not have to re-create all the fields and whatever else gets automatically created by django for an admin form? forgive my noobness. seems like modelform is what builds the form based on the model, but i didnt see any way to raise a validation error on that. can anybody provide a more descriptive explanation of what i need to do and what goes where? i don't need you to write code for me. just let me know what i need to do please. –  Brett Nov 30 '12 at 18:33
I've realized that putting this functionality into a model form doesn't really make sense to me. It seems that the model is still responsible for keeping track of unique fields no? The 'unique=True' parameter is used when creating model fields. Also, unique_together is setup in the Meta class of the model. So it seems logical to me that the behavior i need should be implemented in the model. I need the exact same functionality as unique_together - my issue is that it won't work when using fields that I calculate myself before save. –  Brett Nov 30 '12 at 22:24

Your Answer


