Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error using a base class field in subclass unique_together meta option

Using the following code:

class Organization(models.Model):
    name = models.CharField(max_length="100",)
    alias = models.SlugField()
    ...

class Division(Organization):
    parent_org = models.ForeignKey(Organization)

    class Meta:
        unique_together=['parent_org', 'alias']
        ...

Trying to syncdb give me this error:

Error: One or more models did not validate:
organizations.division: "unique_together" refers to alias. This is not in the 
same model as the unique_together statement.

Any help is appreciated,

Thanks,

Eric

like image 726
Eric Acevedo Avatar asked Oct 05 '10 18:10

Eric Acevedo


2 Answers

This is by design. Reading the documentation for the unique_together option, it states that:

It's used in the Django admin and is enforced at the database level.

If you look at the table that a subclass creates, you'll see that it doesn't actually have the fields that its parent has. Instead, it gets a soft Foreign Key to the parent table with a field name called [field]_ptr_id, where [field] is the name of the table you're inheriting from excluding the app name. So your division table has a Primary Foreign Key called organization_ptr_id.

Now because unique_together is enforced at the database level using the UNIQUE constraint, there's no way that I know of for the database to actually apply that to a field not in the table.

Your best bet is probably through using Validators at your business-logic level, or re-thinking your database schema to support the constraint.

Edit: As Manoj pointed out, you could also try using Model Validators such as validate_unique.

like image 129
Pewpewarrows Avatar answered Oct 16 '22 15:10

Pewpewarrows


[Model] Validators would work for you. Perhaps simplest, though, would be to use:

class BaseOrganization(models.Model):
    name = models.CharField(max_length="100",)
    alias = models.SlugField()
    class Meta:
        abstract = True

class Organization(BaseOrganization):
    pass

class Division(BaseOrganization):
    parent_org = models.ForeignKey(Organization)

    class Meta:
        unique_together=['parent_org', 'alias']

Note: as with your current code, you could not have subdivisions of divisions.

like image 45
Jameson Quinn Avatar answered Oct 16 '22 16:10

Jameson Quinn