Django -如何在字段中添加同一模型的多个示例

omhiaaxx  于 2023-05-23  发布在  Go
关注(0)|答案(2)|浏览(215)

我有一个类看起来像这样。在packitems中,我希望有那个Item示例的编号,以及其中有多少个作为编号。

class Item(models.Model):
    title = models.CharField(max_length=100)
    price = models.DecimalField(decimal_places=2, max_digits=10)
    is_pack = models.BooleanField(default=False)
    pack_items = models.ManyToManyField(PackItem, blank=True)
class PackItem(models.Model):
    packitem = models.ForeignKey('Item', on_delete=models.CASCADE)
    quantity = models.IntegerField(default=1)

这似乎工作,但每次我在管理中创建一个新的包,我必须首先创建,一个接一个,每个PackItem,然后把它们放在项目的packitems字段。目标是:我有几瓶饮料作为物品,我想有这些饮料的预制包。我这样做以后会不会有问题?有没有更好的做法?还是这已经错了?

oyjwcjzk

oyjwcjzk1#

如果我理解正确的话,你需要的是一个**through=…**模型的多对多字段[Django-doc]。所以我们可以实现一个

class Item(models.Model):
    title = models.CharField(max_length=100)
    price = models.DecimalField(decimal_places=2, max_digits=10)

class Pack(models.Model):
    items = models.ManyToManyField(Item, through='PackItem')

class PackItem(models.Model):
    item = models.ForeignKey(Item, on_delete=models.CASCADE)
    pack = models.ForeignKey(Pack, on_delete=models.CASCADE)
    quantity = models.IntegerField(default=1)

因此,我们在这里指定Pack由一个项目集合组成,但junction table [wiki]将包含一个名为quantity的额外参数,该参数指定我们将Item添加到Pack对象的次数。

vom3gejh

vom3gejh2#

这个例子很好地回答了什么是直通模型。
为了进一步明确的事情,因为我需要一个额外的一个小时左右的教程来理解这一点:
1-Item模型应该很容易理解

class Item(models.Model):
    name = models.CharField(max_length=100)
    price = models.DecimalField(decimal_places=2, max_digits=10)
    # Display below in admin 
    def __str__(self): 
       return f"{self.name}"

2-Pack模型是在其中创建示例的模型。

class Pack(models.Model):
    pack = models.ForeignKey(Item, on_delete=models.CASCADE, related_name="packname")
    items = models.ManyToManyField(Item, through='PackItem')
    # Display below in admin 
    def __str__(self): 
       return f"{self.id}"

3-“PackInfo”模型是中介模型。在这里,您不会手动创建任何示例,因为它会自动创建。重要的是你添加了2个外键字段;一个用于您希望连接的每个模型,然后是您需要的任何其他字段(如“数量”)。本例的目的是添加“quantity”字段。

class PackInfo(models.Model):
    item = models.ForeignKey(Item, on_delete=models.CASCADE)
    pack = models.ForeignKey(Pack, on_delete=models.CASCADE)
    quantity = models.IntegerField(default=1)
    # Display below in admin 
    def __str__(self):
        return f"{self.id}"

管理中的Pack模型现在应该看起来像下面这样(我只是在Pack模型中添加了一个额外的foreignkey字段,允许您选择一个项目):

请注意,尽管Pack模型只有2个字段(“pack”和“items”),但还有一个名为“quantity”的附加字段。在我看来,这是使用直通模型的主要优点。
最后,我能够使用“admin.TabularInline”显示如图所示的管理员。您将中间模型(PackInfo)设置为TabularInline管理视图。然后,可以在模型中使用M2M字段(Pack)显示它。extra = 0是这样的,在按下“添加另一个包信息”之前,不会在管理中添加额外的空示例。

@admin.register(Item)
class ItemAdmin(admin.ModelAdmin):
    list_display = ('id', 'name', 'price')

class PackInfoInline(admin.TabularInline):
    model = PackInfo
    extra = 0       # Default extra instances to add is 3

@admin.register(Pack)
class PackAdmin(admin.ModelAdmin):
    inlines = [PackInfoInline]
    class Meta:
        model = Pack

相关问题