Django模型关系(外键)(manytomany)

时间:2012-07-24 11:02:05

标签: django django-models

我是django的新手,来自PHP的观点。我想写一个真正的基本应用程序,有四个类:书,电子书,流派和价格。每本书和电子书应该有一种类型和许多奖品。在SQL-DB中,我将Book和Ebook中的一个字段引用到一个类型表的类型和一个名为Book_prices的新表,它将Books和Ebooks链接到价格。

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(),它只能引用Book或Ebook。

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 个答案:

答案 0 :(得分: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()

答案 1 :(得分: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作为价格。