2011-06-03 34 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