views:

601

answers:

1

heya,

I have a Django project, that has a "Address" model. This is used in several places - by a "User Profile" model, by a "Hospital" model, by an "Insitution" model etc.

I'm using Django's generic relations to allow each of these objects to create a foreign-key to Address.

However, this seems to cause some weirdness in the Django Admin (or perhaps I'm not understanding correctly how it's meant to be used). In the Django Admin, if I try to create an address, I'm seeing fields for "Content type" and "Object id". The model won't validate/save if these aren't filled. Not sure what to put in these.

The thing is, I wanted to be able to create standalone Address objects. Then, when I create a User Profile, or a Hospital, I could link these to the Address objects, including the possibility of multiple ones linking to the same Address object.

How should I use the Django admin with generic relations?

Also, I'm also intending to use django-reversion for version control of the models, not sure if this will cause any issues with generic relations and the admin?

Cheers, Victor

Edit: I should just add, here's an earlier question I posted Addresses and Inlines:

http://stackoverflow.com/questions/1918637/django-designing-model-relationships-admin-interface-and-inline

Based on the answers given there, that's why the Address model is the one with a foreign key. And since a normal FK field can only point to one type of object, that's why we're using generic relations.

Each User/Department/Hospital etc. may (and in most cases will) have multiple addresses.

The same address can be used by multiple entities, but this is rarer, and duplication is fine here, I'm guessing, right?

So it'd be a one-to-many from User/Department/Hospital to Addresses.

In that original question, they also suggested using abstract classes, and a different Address model for each entity that needed an Address. I'm still not sure if that's the better approach, or if there's a way to make GenericRelations work with what I'm trying to do here.

+3  A: 

Using generic relations in django is exactly that. A ForeignKey to ContentType (content_type) and an IntegerField to denote the instance id (object_id). These are useful if you don't know which type of content the ForeignKey is pointing to. Since you know you're targeting the Address model you want to use regular ForeignKey(Address) instead of generic relations.

In response to your comment

Actually its much easier to use ForeignKey since you don't need to go through ContentType.

class Address(models.Model):
  street=models.CharField(max_length=100)
  city=models.CharField(max_length=100)


class Hospital(models.Model):
  name=models.CharField(max_length=100)
  created=models.DateTimeField()
  address=models.ForeignKey(Address, related_name="hospitals")

class Institution(models.Model):
  name=models.CharField(max_length=100)
  address=models.ForeignKey(Address, related_name="institutions")


>>> instance=Institution.objects.get(id=1)
>>> instance.address.city
>>> address=Address.objects.get(id=1)
>>> address.institutions.all() 
>>> address.hospitals.all()

Are your models going to share addresses? i.e. Can a Hospital and an Institution and perhaps a UserProfile all point to the same address instance? Or is it more likely that each will have it's own address? I am trying to understand why you've created a separate class Address. If it's to avoid retyping the same fields into each class you could use an abstract model class and subclass it. Or you might be needing a OneToOneField which is a two way pointer between the two instances.

czarchaic
heya,Hmm, I thought that from a design perspective, you'd put the FK field on the Address object, and have that link to each of the things that needed an address (User, Hospital, Institution etc.). However, since you need to specify a type for that, that's why I used Generic Relations.However, if I put the FK field on the other object, doesn't that break design, or weird up the ORM?Cheers,Victor
victorhooi
@victorhool i think @czarchaic is right, for your description the best approach to the situation is a `models.ForeignKey(Address), doesn't break design neither weird up the ORM, anyway if you persist in use a generic relation, read the doc in http://docs.djangoproject.com/en/1.1/ref/contrib/contenttypes/#generic-relations-in-forms-and-admin
diegueus9
Where you put the FK depends on which side is the "many". Can a user/hospital/institution have many addresses? Then the FK should be on Address, pointing to the user/hospital/institution. But if a single Address can belong to multiple other things, then you want the FK on the "other thing" pointing to Address.
Carl Meyer
@Carl Meyer Yeah, one of the requirements was to have multiple addresses per generic object (UserProfile, Hospital, Institution etc.) Also, those addresses may be shared.
victorhooi
@victorhooi if you need multiple addresses per object, and multiple objects per address (shared addresses) without duplicating addresses, then you don't need FKs either way, you need a ManyToMany. And there's no GenericManyToMany, though you could fake one by creating your intermediary model manually.
Carl Meyer
@Carl Meyer I thought I could just use a FK, since it's a one-to-many for addresses (we can forgo the multiple objects per address requirement, or just duplicate - it's a rarer case than the opposite, multiple addresses per object, which is nearly always true.)Should the FK field still be on addresses?And I'm still not sure how the admin interface works with generics - is it meant to autofill the content_type and object_it fields?Cheers,Victor
victorhooi