Как запросить другую модель Django в представлении шаблона на основе отношения к другой модели

у меня есть эти модели

class Protocol(models.Model):
    name = models.CharField(max_length=200)

class Description(models.Model):
    name = models.CharField(max_length=200)
    protocol = models.ForeignKey(Protocol)

class Trait(models.Model):
    desc = models.CharField(max_length=200)
    protocol = models.ForeignKey(Protocol)

class State(models.Model):
    desc = models.CharField(max_length=200)
    trait = models.ForeignKey(Trait)

class Expression(models.Model):
    state = models.ForeignKey(State)
    description = models.ForeignKey(Description)

Таким образом, протокол (например, протокол «А») состоит из определенного количества признаков (например, рост, вес, цвет). Каждая черта может иметь несколько состояний (например, низкое, среднее, высокое). Затем описание представляет собой набор выражений, связанных с конкретным протоколом. Например, Описание №1 составлено по протоколу «А» и состоит из двух выражений: рост -> низкий, вес -> высокий; но цвет признака не указан.

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

Так:

| Trait  | Expression |
|--------+------------|
| height |            |
| weight | high       |
| color  | blue       |

Используя оболочку, я могу легко вернуть то, что мне нужно

# Select a Description
desc = Description.objects.first()

# Get the protocol
protocol = desc.protocol

# Get all traits in the selected protocol
all_traits = protocol.trait_set.all()

# Get all the expressions in this description
expressions = desc.expression_set.all()

# Print all traits within the selected protocol and their related expression (if any)
for trait in all_traits:
    print(trait.desc)
    expr = expressions.filter(state__trait_id = trait.id).first()
    print(expr.state.desc)

Однако я не могу понять, как это сделать в представлении, особенно я хотел бы продолжать использовать DetailView, но это не является строгим требованием, если это невозможно. Там в любом случае?

Спасибо

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
406
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я нашел способ сделать это, хотя я не полностью удовлетворен, потому что я чувствую, что это не очень элегантное решение.

Я создал description_extras.py в каталоге templatetags/ внутри своего приложения (не забудьте __init__.py рассматривать его как пакет)

Внутри description_extras.py я создал собственный фильтр, например:

from django import template

register = template.Library()

@register.filter
def expr_trait(expression,trait_id):
    return expression.filter(state__trait_id = trait_id).first()

Затем в шаблоне я загружаю пользовательский фильтр с помощью

{% load description_extras %}

И тогда я могу вызвать фильтр следующим образом:

{% for trait in description.protocol.trait_set.all %}
    <tr>
        <td>{{ trait.desc }}</td>
        <td>{{ description.expression_set.all|expr_trait:trait.id }}</td>
    </tr>
{% endfor %}

Другие вопросы по теме