Как отобразить несколько самосвязанных данных внешнего ключа в Django/HTML?
Я пытаюсь создать веб-приложение django для отображения различных данных (вопрос и некоторые дополнительные данные). Мои данные состоят из тела вопроса и отраслевого руководства, которое содержит несколько пунктов. Каждый пункт может содержать дополнительные подварианты и т. д.
Примерные данные:
Тело вопроса: Все ли были знакомы с расположением, назначением, испытанием и эксплуатацией противопожарных дверей? Отраслевое руководство:
- Эксплуатационная готовность
- Техническое обслуживание и тестирование
- Регламентные проверки
- Регламентное техническое обслуживание
- Еженедельно
- Ежемесячно
- ...
Ниже представлены мои модели:
class BaseGuidance(models.model):
text = models.CharField(max_length=2000)
parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name="sub_options")
class Meta:
abstract = True
def __str__(self):
return self.text
class IndustryGuidance(BaseGuidance):
pass
class Question(models.model):
body = models.CharField(max_length=400)
industry_guidance = models.ForeignKey(IndustryGuidance, on_delete=models.CASCADE, null=True, blank=True)
Вот мой вид, который отображает HTML:
def index(request):
questions = Question.objects.all()
industry_guidance = IndustryGuidance.objects.prefetch_related(
'sub_options',
).all()
return render(request, "sire/index.html",{
"questions": questions,
"industry_guidance": industry_guidance
})
Ниже приведен мой HTML:
<td scope="col">
<ul class="list-group">
{% for guidance in industry_guidance %}
<li>{{ guidance.text }} </li>
<ul>
{% for sub_option in guidance.sub_options.all %}
<li>{{ sub_option.text }}</li>
{% endfor %}
</ul>
{% endfor %}
</ul>
</td>
Я действительно запутался в том, как именно я должен подойти к этой проблеме, чтобы получить все данные и отобразить их соответствующим образом.
Я попробовал prefetch_related, но мое веб-приложение не загрузилось, видимо, застряв в каком-то цикле for loop. Я также думаю о перестройке своих моделей, но не смог найти никаких рекомендаций или лучших практик по этому вопросу.
В конечном счете, я хотел бы отобразить каждый вопрос в таблице с относящимися к нему отраслевыми рекомендациями в виде списка. Каждый подвариант должен быть отступом в другом списке. Каждая пуля подварианта должна быть в другом списке, и так далее... Все данные, касающиеся вопроса, должны находиться в одной строке.
Я бы рекомендовал вам использовать django-mptt при работе с деревьями. Вот пример использования:
pip install django-mptt
добавьте «mptt» в ваш INSTALLED_APPS
список в settings.py
INSTALLED APPS = [
...,
"mptt",
]
Измените parent
поле вашей BaseGuidance
модели в models.py
:
from mptt.fields import TreeForeignKey
from mptt.models import MPTTModel
class BaseGuidance(MPTTModel):
text = models.CharField(max_length=2000)
parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name="sub_options")
class Meta:
abstract = True
class MPTTMeta:
order_insertion_by = ['-id']
parent_attr = 'parent'
def __str__(self):
return self.text
После изменения модели перенесите изменения:
python ./manage.py makemigrations
python ./manage.py migrate
Затем измените свои представления:
def index(request):
questions = (
Question.objects.select_related('industry_guidance')
.prefetch_related('industry_guidance__sub_options') # Fetch sub-options for the MPTT structure
)
context = []
for question in questions:
guidance_tree = (
question.industry_guidance.get_descendants(include_self=True)
if question.industry_guidance else None
)
context.append({
"question": question,
"guidance_tree": guidance_tree,
})
return render(request, "index.html", {"context": context})
И ваш sire/index.html
файл:
{% for item in context %}
<tr>
<td>{{ item.question.body }}</td>
<td>
<ul>
{% if item.guidance_tree %}
{% recursetree item.guidance_tree %}
<li>{{ node.text }}</li>
<ul>
{% for child in node.get_children %}
<li>{{ child.text }}</li>
{% endfor %}
</ul>
{% endrecursetree %}
{% else %}
<li>No guidance available for this question.</li>
{% endif %}
</ul>
</td>
</tr>
{% endfor %}
Надеюсь, это вам поможет!