Джанго что-то делает с каждым другим значением в поле модели - PullRequest
0 голосов
/ 22 сентября 2018

Я знаю, что видел это раньше, но сейчас не могу найти, что готов реализовать это.

Я пытаюсь перечислить элементы на странице по категориям и подкатегориям, но яхотите только 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 голосов
/ 22 сентября 2018

Дублирование данных анти-паттерн

Многие компьютерные специалисты считают это плохим дизайном, поскольку он вводит дублирование данных .Представьте, что вы позже захотите изменить название категории, а это значит, что вам нужно найти всех вхождений этой категории и переименовать их.Если вы используете это только для модели Object s, то это возможно выполнимо, но если все виды элементов принадлежат Category s, то это легко выходит из-под контроля.

Более того, это также ограничиваеткатегории: две разные категории не могут иметь одно и то же имя (что может быть здесь разумно), и мы не можем добавить много свойств к Category: представьте, что мы хотим добавить description для категории, тогда это описание необходимо повторить для всех строк, или, если мы решим сохранить его только в одной строке, будет сложно найти эту конкретную строку.Кроме того, если есть две строки с разными описаниями, то какое описание выбрать?

База данных также будет очень большой: каждая строка должна повторять одну и ту же категорию.Если категория в среднем занимает 15 символов, это означает, что мы - в зависимости от кодировки - легко потратим 8 байтов на строку (ну, строка содержит 16 байтов для строки, учитывая, что это кодировка UTF-8, и только символы ASCII, ноForeignKey будет часто использовать 8 байтов).Если бы мы добавили описание, содержащее в среднем 63 символа, то мы бы снова потратили еще 64 байта на строку .Для небольшого количества строк это не проблема, но проблема легко масштабируется проблематично.Выше, конечно, только оценки того, какие проблемы могут возникнуть, не рассматривайте это как «действительные числа»: размер базы данных определяется множеством параметров, которые здесь либо игнорируются, либо оцениваются.

Да, все эти проблемы, вероятно, можно решить, но вместо решения проблем ad-hoc лучше нормализовать базу данных.

Нормализация моделей

Нормализацияобычно означает, что мы вводим дополнительные таблицы, в которых хранится, например, одна запись на Category, и используем ForeignKey s для ссылки на эту запись.Для вашего примера нормализованный вариант будет:

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 s и SubCategory s в выделенных таблицах и связываем модели вместе с ForeignKey s.

Отображение списков (Sub) Category s

Теперь, когда мы нормализовали модели, мы можем эффективно визуализировать Category s с:

# 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.

0 голосов
/ 22 сентября 2018

Прежде всего вы должны попытаться нормализовать свои объекты, то есть вы можете сохранить свои подкатегории в качестве отдельного объекта и использовать models.foreignKey, чтобы связать их вместе.См. ответ Виллема Ван Онсема .

Однако, чтобы решить текущую проблему, вы должны использовать тег шаблона regroup для агрегирования категорий.

В вашем случае это будет выглядеть примерно так:

{% regroup objects by category as categories %}
{% for category in categories %}
    {{ category.grouper }}
    {% for subcategory in category.list %}
        {{ subcategory }}
    {% endfor %}
{% endfor %}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...