你基本上根据你想用你的“引用”模型是什么样的关系两个选项:
models.ForeignKey
(如果与ForeignKey的模型应该有一个链接到一个特定的只有一个模型键入另一个Django模型)或models.ManyToManyField
(如果它是一个多对多的关系)。
- 使用contenttypes框架,它允许你基本上有一个通用的foreignkey; https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/
这有点抽象,所以我将给出每个选项的具体示例。
假设您有一个商店模型,其中每个商店最多包含一个评论,但同一评论可指向多个商店。然后,它可能是有意义的有这样一个模型:
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)
正如上面写的,你可以有商店A,B,C,其中商店A和商店B两个链接查看1,和器C的链接查看这似乎有点愚蠢。对商店的评论应该只指向一家商店(你应该被允许拥有没有评论或多次评论的商店;但是不应该能够进行不指向商店的评论)。所以它构建起来更有意义:
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')
这样每个评论指向一个商店;但商店不一定有审查。如果变量store_obj
与特定商店的实例一起使用,则可以使用查询集store_obj.review_set.all()
遍历所有评论。
现在让我们说你有两个模型,说Store
和Hotel
是根本不同,但只希望一个评论类链接到两个。这是contenttypes
/GenericRelation
来的地方。它比简单的ForeignKey稍微复杂一些(因为你必须跟踪类型和object_id然后构造GenericForeignKey),但是可以如下实现。 (显然这只有在酒店和商店真的需要不同的字段/方法时才有意义,不像这个例子。)
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')
其实在重新阅读你的答案我想你想要的仅仅是这样的:
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')
所以每次审查被链接到一个商店,你可以给一个列表选择要存储在数据库'yelp'中,'ypag'用较长的文本字符串表示,以及超链接。
如果它们根本不同,您也可以为每种评论类型创建单独的类;例如,如果你正在做电影评论,烂番茄评论将存储根本不同的信息比metacritic评论。但只要每个型号都有一个FK指向Store,这并不重要。
如果您需要管理员编辑审阅类型的列表,其执行方式是作为外键。喜欢的东西:
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"))
当你知道你有一些初步ReviewType对象,我用get_or_create基于ID(在ID来创建它们,因此,如果管理员编辑名称“黄页”说“黄页“一个新的对象永远不会被创建)。
为了使这样你就可以从商店的管理页面中添加评论,您需要使用内联模式: https://docs.djangoproject.com/en/1.3/ref/contrib/admin/#django.contrib.admin.InlineModelAdmin
所以你admin.py页面上,这样做
class ReviewInline(admin.TabularInline):
model = review
extra = 1
class StoreAdmin(admin.ModelAdmin):
inlines = [ReviewInline,]
admin.site.register(Store, StoreAdmin)
我认为contenttypes更接近我试图实现的目标。这更接近标签的概念,因为从某种意义上讲,我将用一个特定标签“标注”一个模型,但它也会有一个与标签和模型相关联的独特链接。 – xtine 2011-06-03 00:42:17
@xtine:好的,所以我终于完成了我的答案。 (我没有提交代码就提交了它,因为它有答案的要点,我不想被其他人殴打,但认为代码使它非常具体。) – 2011-06-03 00:58:30
“选择”选择是我需要。不过,我正在考虑让选择可以管理,因此管理员可以添加另一种链接类型,而无需将其添加到模型中。 – xtine 2011-06-03 05:37:55