Django使用模型字段中的每个不同值执行某项操作

时间:2018-09-22 14:00:13

标签: django django-models django-forms

我知道我以前已经看过这个,但是现在我已经准备好实现它了,找不到我了。

我试图按类别和子类别列出页面上的项目,但是我只想要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

2 个答案:

答案 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
    )

因此,我们将CategorySubCategory存储在专用表中,并将模型与ForeignKey链接在一起。

({SubCategory 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