2012-07-24 183 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