You basically have two options based on what kind of relationship you want to model with your 'references':
models.ForeignKey (if the model with the ForeignKey should have a link to exactly one model of a specific type in another django model) or models.ManyToManyField (if its a many to many relationship).
- Use the contenttypes framework, which allows you to essentially have a generic foreignkey; https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/
This is a bit abstract, so I'll give a concrete example of each option.
Say you have a Store model, where each store contains at most one review, but the same review can point to multiple stores. Then it may make sense to have a model like this:
class Store(models.Model):
name = models.CharField(max_length=50)
review = models.ForeignKey('Review')
class Review(models.Model):
user_comment = models.TextField(max_length=1024)
As written above you could have Stores A, B, C, where store A and store B both link to review 1, and store C links to review 2. This seems a bit silly; a review of a store should only point to one store (and you should be allowed to have stores with no reviews or multiple reviews; but shouldn't be able to have a review that doesn't point to a store). So it makes much more sense to construct it like:
class Store(models.Model):
name = models.CharField(max_length=50)
class Review(models.Model):
user_comment = models.TextField(max_length=1024)
store = models.ForeignKey('Store')
This way each review points to exactly one store; but a store doesn't necessarily have a review. If you have a variable store_obj with an instance of a specific store you can iterate through all the reviews with by the queryset store_obj.review_set.all().
Now lets say you have two models say Store and Hotel that are fundamentally different, but want only one review class to link to both. This is where contenttypes / GenericRelation come in. Its a bit more complicated than simple ForeignKey (as you have to keep track of the type and object_id and then construct the GenericForeignKey), but could be implemented as follows. (Obviously this would only make sense if you really need different fields/methods in Hotel and Store, unlike this example.)
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
class Store(models.Model):
name = models.CharField(max_length=50)
reviews = generic.GenericRelation("GenericReview")
class Hotel(models.Model):
name = models.CharField(max_length=50)
reviews = generic.GenericRelation("GenericReview")
class GenericReview(models.Model):
text = models.TextField(max_length=1024)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
Actually upon re-reading your answer I think what you want is just something like:
class Store(models.Model):
name = models.CharField(max_length=50)
class Review(models.Model):
user_comment = models.TextField(max_length=1024)
review_type = models.CharField(max_length=4, choices=(('yelp', 'Yelp'), ('ypag', 'Yellow Pages'),))
hyperlink = models.URLField()
store = models.ForeignKey('Store')
So each review is linked to one store, you can give a list of choices to be stored in the database 'yelp', 'ypag' represented by longer text strings, as well as the hyperlink.
You could also create separate classes for each type of review if they are fundamentally different; e.g., if you were doing movie reviews a rotten tomatoes review would store fundamentally different information than a metacritic review. But it doesn't matter as long as each model has a FK pointing back to Store.
If you need the admin to edit the list of review-types, the way to do it is as a foreignkey. Something like:
class Store(models.Model):
name = models.CharField(max_length=50)
class ReviewType(models.Model):
def __unicode__(self):
return u'%s' % (self.description)
description = models.CharField(max_length=50)
class Review(models.Model):
user_comment = models.TextField(max_length=1024)
review_type = models.ForeignKey("ReviewType")
hyperlink = models.URLField()
store = models.ForeignKey('Store')
ReviewType.objects.get_or_create(id=1, defaults=dict(description="Yelp"))
ReviewType.objects.get_or_create(id=2, defaults=dict(description="Yellow Pages"))
As you knew you'd have some initial ReviewType objects, I used get_or_create to create them based on id (on id, so if an admin edits the name "Yellow Pages" to say "Yellowpages" a new object is never created).
To make it so you can add a review from the admin page of the Store, you need to use inline models:
https://docs.djangoproject.com/en/1.3/ref/contrib/admin/#django.contrib.admin.InlineModelAdmin
So on your admin.py page, do something like
class ReviewInline(admin.TabularInline):
model = review
extra = 1
class StoreAdmin(admin.ModelAdmin):
inlines = [ReviewInline,]
admin.site.register(Store, StoreAdmin)