On Thu, 2009-01-29 at 19:54 -0800, CALdan wrote:
> hi!
> 
> I'm putting together a simple model in Django as an example for a
> large project.  I'm attempting to set up the models in an efficient
> manner with as little redundancy as possible (none).
> 
> What I'm attempting to do is use unique_together across 2 classes
> which are linked through their primary key fields, with the
> unique_together referencing a field from each table which are not the
> primary keys.
> 
> Is it possible to use unique_together across classes like this?  If
> not, what alternative could I use that's clean and efficient?

You can't add the lines -> survey unique constraint through Django's
ORM. The Meta.unique_together attribute is only for adding a constraint
to fields on the table for that model. You're needing a more complex
check constraint at the database level and this isn't supported. You
could add it as a table modification using raw SQL (via, say, the
post-syncdb hook, or just manually), but it won't be handled by things
like form validation, so will be a little tricky to work with.

One workaround is to wait a little bit until model-aware validation
lands and add model-level validation as well, to the Lines model, to do
this checking. That wouldn't completely remove the possibility of an
IntegrityError when you save to the databse, but no uniqueness checks at
the Python level can do that (it can be unique when we validate and
something else can have written to the database before we save), but
it's a way of making it work more smoothly. By "smoothly" here, I'm
meaning having some way of detecting a potential clash before calling
save() and seeing an IntegrityError returned from the database.

> The rules that need to be adherred to within the model are as follows:
> 
> 1.Survey's have many Lots.
> 
> 2.Within a Survey, Lot numbers must be unique.
> 
> 3.Lot's have many Lines.
> 
> 4.Within a Survey, Line numbers must be unique.

> 
> The models are posted below with the fields in question in bold.
> 
> class Survey(models.Model):
>     survey = models.IntegerField(primary_key=True,  unique = True)
> 
>     class Meta:
>         ordering = ["survey"]
>         db_table='survey'
> 
> class Lot(models.Model):
>     lot_id = models.AutoField(primary_key=True,  unique = True)
>     lot_number = models.IntegerField()
>     survey = models.ForeignKey(Survey, db_column ='survey')
> 
>     class Meta:
>         ordering = ["lot_number"]
>         db_table='lot'
>         unique_together = ("lot_number",  "survey")
> 
> class Line(models.Model):
>     line_id = models.AutoField(primary_key=True,  unique = True)
>     lot_id = models.ForeignKey(Lot, db_column='lot_id')

You should consider renaming the attribute here to just "lot" (or
something similarly descriptive; "lot" would require you to add a
related_name attribute).

The thing is, from a Python perspective, that attribute does *not* hold
the lot_id. It actually contains a Lot instance whenever you're using.
It's a Lot, not an id. There will be a "hidden" attribute generated on
the model called (in your case) lot_id_id, which will be the actual
lot_id, but you never interact with that. Code that uses "lot_id", when
it really means "lot instance" tends to be confusing to read in six
months time (it's a common first stab at naming and I've seen it enough
in client code to want to warn people away from it).

Regards,
Malcolm


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to