Django 多外键导航
Posted
技术标签:
【中文标题】Django 多外键导航【英文标题】:Django Multiple ForeignKey Navigation 【发布时间】:2015-02-17 02:03:34 【问题描述】:我正在构建一个购物车。在我的购物车中,一个项目可以由其他项目组成。我需要在单个模板中显示一组项目及其对应的相关部分。我知道如何在模板中显示单个项目及其对应部分,但我似乎无法弄清楚如何显示多个项目,每个项目都有自己的包含部分列表。
我已经摆弄了模板文件中标签的每一个排列:
# checkout.html
% for item in cart_items %
<tr>
<td class="left">
item.name
<ul>
% for part in item.product.buildpart.part_set.all %
<li> part.name
% endfor %
</ul>
</td>
<td>$ item.price </td>
<td> item.quantity </td>
<td class="right">$ item.lineItemTotal </td>
</tr>
% endfor %
这是生成模板的 vew:
# views.py
def checkout(request):
cart_items = get_cart_items(request)
<snip>
return render(request, 'checkout.html', locals())
下面是 get_cart_items() 函数,它返回用户购物车中的所有商品:
# cart.py
def get_cart_items(request):
""" return all items from the current user's cart """
return CartItem.objects.filter(cart_id=get_cart_id(request))
这是 CartItem 模型:
# models.py
class Item(models.Model):
cart_id = models.CharField(max_length=50)
quantity = models.IntegerField(default=1)
product = models.ForeignKey(PartModel, unique=False)
class Meta:
abstract = True
<snip>
class CartItem(Item):
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['date_added']
verbose_name = "Cart Item"
<snip>
“product”字段是 PartModel 模型的 ForeignKey:
# models.py
class PartModel(models.Model):
family = models.ForeignKey(PartFamily)
name = models.CharField("Model Name", max_length=50, unique=True)
slug = models.SlugField(help_text="http://www.Knowele.com/<b>*slug*</b>",
unique=True)
<snip>
buildpart = models.ManyToManyField('self', through='BuildPart',
symmetrical=False, related_name='+')
class Meta:
ordering = ['name']
verbose_name = "Product Model"
<snip>
PartModel 模型通过 buildpart 字段和 BuildPart 模型与其自身具有多对多关系,以促进可以由其他目录项组成的目录项的概念:
# models.py
class Build(models.Model):
build = models.ForeignKey(PartModel, related_name='+')
part = models.ForeignKey(PartModel, related_name='+')
quantity = models.PositiveSmallIntegerField(default=1)
class Meta:
abstract = True
unique_together = ('build', 'part')
def __unicode__(self):
return self.build.name + ' with ' + str(self.quantity) + ' * ' + \
self.part.family.make.name + ' ' + self.part.name
class BuildPart(Build):
pass
class Meta:
verbose_name = "Build Part"
我似乎无法在模板(上面列出)中进行必要的 ForeignKey 遍历,以便在 CartItem 模型中获取与用户项目关联的所有部分。是我在模板中做的不对还是我没有在我的视图中打包正确的查询集?
这个问题的第二部分是,一旦我得到这些部分,我需要它们按照 PartType 模型的“order”整数字段中指定的顺序显示:
# models.py
class PartType(models.Model):
name = models.CharField("Part Type", max_length=30, unique=True)
slug = models.SlugField(unique=True)
order = models.PositiveSmallIntegerField()
description = models.TextField(blank=True, null=True)
class Meta:
ordering = ['name']
verbose_name = "Product Type"
def __unicode__(self):
return self.name
class PartFamily(models.Model):
make = models.ForeignKey(PartMake)
type = models.ForeignKey(PartType)
name = models.CharField("Family Name", max_length=30,
unique=True)
slug = models.SlugField(unique=True)
url = models.URLField("URL", blank=True, null=True)
description = models.TextField(blank=True, null=True)
class Meta:
ordering = ['name']
verbose_name = "Product Family"
verbose_name_plural = "Product Families"
def __unicode__(self):
return self.name
如您所见,在 PartModel 模型中,“family”字段是 PartFamily 模型的 ForeignKey,而在 PartFamily 模型中,“type”字段是 PartType 模型的 ForeignKey,其中是 all - 零件需要订购的重要“订单”字段。
我希望这是有道理的,你会明白为什么这对于像我这样的菜鸟来说如此复杂。
【问题讨论】:
我已经回答了您之前问题的第 1 部分。答案还是一样的;这次你在做buildpart.part_set
,但buildpart 仍然是多对多访问器,所以没有part_set 这样的东西,只需遍历buildpart.all
。
另外,真的不清楚为什么你有所有这些抽象模型,然后你会继承这些模型。重点是什么? BuildPart
应该直接打开字段,然后删除 Build
模型。
感谢丹尼尔·罗斯曼!你让它为我工作!如果您以正常方式重新发布答案,我会给您获胜的答案,以便我可以单击复选标记。 另外,您(或其他人)能否告诉我如何让他们以正确的顺序列出(通过 PartType 模型中的“订单”字段?为了回答您的问题,我需要抽象模型,因为多个模型继承自它们,为了简洁起见,我只是剪掉了这些模型,但它们存在并且我使用它们。你会在我之前的问题中看到这些其他模型。再次感谢!
第二个问题的答案:***.com/questions/6540032/…
【参考方案1】:
只需迭代 item.product.buildpart.all
:
% for item in cart_items %
[...]
% for part in item.product.buildpart.all %
part.name [...]
% endfor %
% endfor %
【讨论】:
以上是关于Django 多外键导航的主要内容,如果未能解决你的问题,请参考以下文章