你基本上根據你想用你的「引用」模型是什麼樣的關係兩個選項:
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