2012-07-24 228 views
0

我對django完全陌生,來自PHP的角度。我想寫一個真正的基本應用程序與四個類:書籍,電子書,流派和價格。每本書和電子書應該有一個類型和許多獎品。在SQL-DB中,我將一個字段放在Book和Ebook中,通過id引用一個流派表和一個名爲Book_prices的新表,它將Books和Ebooks鏈接到價格。Django模型關係(foreignkey)(manytomany)

table book_prices 
id | type | price 
---+--------+------ 
1 | book | 3 
2 | book | 3 
3 | ebook | 1 

table book/ebook 
id | ... | genre_id 
---+-----+--------- 
1 |  | 5 
2 |  | 7 
3 |  | 9 

基本上我想爲每個電子書和書添加一個價格和一種流派的列表。我如何使用django模型來做到這一點?我知道model.ForeignKey()可以應用於每個書籍/電子書引用一個流派。但是我的價格呢?如果我在價格上添加ForeignKey(),則只能參考書籍或電子書。

class Book: 
    name = models.CharField(max_length=100) 
    pages = models.IntegerField() 

class Ebook: 
    name = models.CharField(max_length=100) 
    filesize = models.FloatField() 

class Genre: 
    name = models.CharField(max_length=100) 
    info = models.TextField() 

class Price: 
    currency = models.CharField(max_length=4) 
    amount = models.FloatField() 

回答

2

這是一種方法。它使用繼承來減少類之間的重複。 它使用contenttypes框架。 還你的類需要繼承django.db.models

from django.db import models 
from django.contrib.contenttypes.models import ContentType 
from django.contrib.contenttypes import generic 

class Genre(models.Model): 
    name = models.CharField(max_length=100) 
    info = models.TextField() 

class Price(models.Model): 
    currency = models.CharField(max_length=4) 
    amount = models.FloatField() 
    content_type = models.ForeignKey(ContentType) 
    object_id = models.PositiveIntegerField() 
    book = generic.GenericForeignKey('content_type', 'object_id') 

class BookBase(models.Model): 
    name = models.CharField(max_length=100) 
    genre = models.ForeignKey(Genre) 

    class Meta: 
     abstract = True 

class Book(BookBase): 
    pages = models.IntegerField() 

class Ebook(models.Model): 
    filesize = models.FloatField() 
+0

如果您將使用south進行遷移,您可能會遇到一些問題。 http://stackoverflow.com/questions/1600129/using-south-to-refactor-a-django-model-with-inheritence – nk9 2012-07-24 11:58:03

+1

@ b1-這是一個非常優秀的SO職位。謝謝。 – scytale 2012-07-24 12:00:46

+0

@scytale我喜歡子類化的想法,但是如何在我的管理界面中顯示價格字段?將PriceInline類添加到我的BookAdmin/EbookAdmin會導致「..沒有ForeignKey to ..」異常。 – Joey 2012-07-24 21:53:43

0
class Genre: 
    name = models.CharField(max_length=100) 
    info = models.TextField() 

class Price: 
    currency = models.CharField(max_length=4) 
    amount = models.FloatField() 

class Book: 
    genre = models.ForeignKey(Genre) 
    name = models.CharField(max_length=100) 
    pages = models.IntegerField() 
    prices = models.ManyToManyField(Price) 

class Ebook: 
    genre = models.ForeignKey(Genre) 
    name = models.CharField(max_length=100) 
    filesize = models.FloatField() 
    prices = models.ManyToManyField(Price) 

獲取所有的價格爲一本書實例。

b1 = Book.objects.get(id=1) 
prices = b1.prices.all() 

ManyToManyField創建幕後中間表,酷似你 會做,如果你手工做的。您甚至可以明確定義此表, 以防您想向其中添加更多字段,through參數

另請考慮使用價格爲DecimalField

+1

這種方法的問題是,隨着價格的關係是不完全正確。你想讓一本書有很多價格。你*不希望一個價格有很多書(當你想改變一本書的價格時會發生什麼?)。您可以通過添加自定義驗證來確保價格只與一本書有關。我認爲更好的解決方案是使用contenttypes實現一對多的Price-> Book/Ebook關係。 – scytale 2012-07-24 11:27:38

+0

@scytale我不會以這種方式建模我的數據庫。但這是OP所要求的,而這正是我向他展示的內容。還要避免在大型數據集中使用多態關係(使用ContentTypes),因爲它至少在我的經驗中代價非常高。 – rantanplan 2012-07-24 11:30:14

+0

@rantanplan你是如何建模這個數據庫的? – Joey 2012-07-24 14:52:45