我知道我以前已经看过这个,但是现在我已经准备好实现它了,找不到我了。
我试图按类别和子类别列出页面上的项目,但是我只想要1个类别,然后是该类别中的子类别。希望我的代码会有意义。
class Objects(models.Model):
# Main Checkbox.
category = models.CharField(
max_length=100,
blank=True,
)
# Checkboxes under Main Checkbox.
subcategory = models.CharField(
max_length=100,
blank=True,
)
所以我的对象存储为:
category1, subcategory1
category1, subcategory2
category2, subcategory1
category2, subcategory2
当显示时应该给我:
category1
subcategory1
subcategory2
category2
subcategory1
subcategory2
如何设置查询,以便我的结果向我显示每个“不同的” category
?
答案 0 :(得分:3)
首先,您应该对对象进行规范化,这意味着您可以将子类别保留为单独的对象,并使用models.foreignKey
将它们链接在一起。参见Willem Van Onsem's answer。
但是,要解决当前问题,您应该可以使用regroup template tag来汇总类别。
对于您来说,它看起来像:
{% regroup objects by category as categories %}
{% for category in categories %}
{{ category.grouper }}
{% for subcategory in category.list %}
{{ subcategory }}
{% endfor %}
{% endfor %}
答案 1 :(得分:3)
许多计算机科学家认为这是错误的设计,因为它引入了数据重复。想象一下,您以后想要更改类别的名称,这意味着您需要查找该类别的所有所有并将其重命名。如果仅将其用于Object
s模型,那也许是可行的,但是如果所有类型的元素都属于Category
s,那么这很容易失控。
此外,它还限制了类别:两个不同类别永远不能具有相同的名称(在这里可能是合理的),也不能在Category
上附加很多属性:假设我们想要为类别添加description
,那么该描述需要在所有行中重复,或者如果我们决定仅将其存储在一个行中,那么将很难找到该特定行。此外,如果有两行描述不同,那么该选择什么描述?
数据库也将非常庞大:每一行应重复相同的类别。如果一个类别平均需要15个字符,这意味着-根据编码的不同-我们很容易浪费每行8个字节(如果该字符串包含UTF-8编码,则该行包含16个字节的字符串,并且只有ASCII字符,但是ForeignKey
将经常使用8个字节)。如果我们添加一个平均长度为63个字符的描述,那么我们将再次浪费每行 64个字节。对于少量的行,这不是问题,但是问题很容易扩展成问题。当然,以上只是对可能出现的问题的估计,不要将其视为“实数”:数据库占用的大小由许多在这里忽略或估计的参数确定。
是的,所有这些问题可能都可以解决,但是与其解决 ad-hoc 问题,不如对数据库进行规范化。
规范化通常意味着我们引入了额外的表,例如每个Category
存储一个 记录,并使用ForeignKey
来引用该记录。以您为例,标准化变体为:
class Category(models.Model):
name = models.CharField(max_length=100)
class SubCategory(models.Model):
name = models.CharField(max_length=100)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
class Object(models.Model):
subcategory = models.ForeignKey(
SubCategory,
null=True,
on_delete=models.SET_NULL
)
因此,我们将Category
和SubCategory
存储在专用表中,并将模型与ForeignKey
链接在一起。
Sub
)Category
s的呈现列表现在我们对模型进行了归一化,我们可以使用以下方式有效地渲染Category
:
# app/views.py
def some_view(request):
categories = Category.objects.prefetch_related('subcategory_set')
return render(request, 'app/some_template.html', {'categories': categories})
,然后在app/templates/some_template.html
中将其呈现为:
<ul>
{% for cat in categories %}
<li>{{ cat.name }}</li>
<ul>
{% for subcat in cat.subcategory_set %}
<li>{{ subcat.name }}</li>
{% endfor %}
</ul>
{% endfor %}
</ul>
因此,我们遍历所有categories
,并且对于每个cat
,我们遍历subcategory_set
。