2011-06-03 30 views
1

我不确定如何正确地说出这一点。但我有一个模型,列出了一堆商店(完整的名称,地址,电话等)。我也想列出和存储链接归因于商店,所以就像说一个Yelp评论,黄页链接等。如何在Django模型中添加/引用属性?

而不是不断增加列,我有点想着有一个不同的模型,列出了一堆类型像Yelp,Yellowpages等链接源,然后另一个实际上交叉引用它们,所以一行将有像商店ID 3,在链接类型yelp链接。

任何想法,我会做到这一点,以便管理员可以动态地添加另一种链接类型,如说谷歌地方,然后将能够添加一个商店的谷歌地点页面链接到商店?

回答

3

你基本上根据你想用你的“引用”模型是什么样的关系两个选项:

  1. models.ForeignKey(如果与ForeignKey的模型应该有一个链接到一个特定的只有一个模型键入另一个Django模型)或models.ManyToManyField(如果它是一个多对多的关系)。
  2. 使用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()遍历所有评论。

现在让我们说你有两个模型,说StoreHotel是根本不同,但只希望一个评论类链接到两个。这是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) 
+0

我认为contenttypes更接近我试图实现的目标。这更接近标签的概念,因为从某种意义上讲,我将用一个特定标签“标注”一个模型,但它也会有一个与标签和模型相关联的独特链接。 – xtine 2011-06-03 00:42:17

+0

@xtine:好的,所以我终于完成了我的答案。 (我没有提交代码就提交了它,因为它有答案的要点,我不想被其他人殴打,但认为代码使它非常具体。) – 2011-06-03 00:58:30

+0

“选择”选择是我需要。不过,我正在考虑让选择可以管理,因此管理员可以添加另一种链接类型,而无需将其添加到模型中。 – xtine 2011-06-03 05:37:55

0

所以你想要的是一个Store模型,并且你希望每个商店都有一个或多个指向商店某些信息的链接。您可以使用ForeignKeyManyToManyField

如果每个商店都有唯一的一组链接,请使用ForeignKey。但是,如果商店在它们之间共享链接,请使用ManyToManyField。很可能你最终会使用ForeignKey这意味着你应该有类似于下面的代码。

class Store(models.Model): 
    name = models.CharField() 
    address = models.CharField() 
    phone = models.CharField() 

class LinkType(models.Model) 
    name = models.charField() 

class Link(models.Model): 
    name = models.CharField() 
    url  = models.CharField() 
    type = models.ForeignKey(LinkType) # Assumed links have only one type 
    store = models.ForeignKey(Store) # Assumed link each link belongs to only one store