Избегайте дублирования в цикле Django for с отношением "многие ко многим
Моя цель - перечислить названия тегов для каждой созданной заметки.
У меня возникают проблемы, потому что tag_title и note связаны через отношения "многие ко многим".
Как я обычно это делаю:
{% for note_tag in note_tags %}
{% if note_tag.note == note %}
{{note_tag.tag_title}}
{% endif %}
{% endfor %}
Однако, поскольку tag_title имеет отношение "многие ко многим" с NoteModel, note_tag.note выдает notes.NoteModel.None
Мои models.py выглядят следующим образом:
class NoteModel(models.Model):
note = models.CharField(
max_length = 5000,
)
note_title = models.CharField(
max_length = 500,
blank = False,
null = True,
)
project = models.ForeignKey(
IndividualProject,
on_delete=models.CASCADE,
related_name = "note_projects",
blank = False,
null = True,
)
tag = models.ManyToManyField(
'NoteTagModel',
related_name="tags",
blank= False,
through = "TaggedModel"
)
def __str__(self):
return f"{self.note_title}"
class NoteTagModel(models.Model):
note = models.ManyToManyField(
'NoteModel',
related_name="tag_notes",
blank= False,
through = "TaggedModel"
)
tag_title = models.CharField(
max_length = 200,
default = "General",
)
def __str__(self):
return f"{self.tag_title}"
class TaggedModel(models.Model):
note = models.ForeignKey(NoteModel, on_delete = models.CASCADE)
tag = models.ForeignKey(NoteTagModel, on_delete = models.CASCADE)
def __str__(self):
return f"{self.note} | {self.tag}"
class TagCommentaryModel(models.Model):
tag_title = models.ForeignKey(
NoteTagModel,
on_delete=models.CASCADE,
related_name="tag",
blank = False,
null = True,
)
tag_commentary = models.CharField(
max_length = 5000
)
def __str__(self):
return f"Tag: {self.tag_title} | Tag Commentary: {self.tag_commentary}"
Контекст в моем views.py выглядит следующим образом:
context = {
'note_form' : note_form,
'notes' : NoteModel.objects.filter(project = obj),
'notes_tag' : NoteTagModel.objects.all(),
'commentary' : TagCommentaryModel.objects.all(),
'projects' : IndividualProject.objects.all(),
'specific_project' : IndividualProject.objects.get(id=id),
'obj' : IndividualProject.objects.get(id=id),
'tagged' : TaggedModel.objects.all(),
}
Мой шаблон django выглядит следующим образом:
<div class = note_overview_container>
{% for note in notes %}
<div class = individual_note_container>
<div class = note_title>
{{ note.note_title }}
</div>
{% for note_tag in notes_tag %}
<div class = tag_title>
{{ note_tag.tag_title }}
</div>
<ul class = tag_commentary>
{% for commentary in commentary %}
{% if note_tag == commentary.tag_title %}
{% if note == commentary.note %}
<li>{{ commentary.tag_commentary }}</li>
{% endif %}
{% endif %}
{% endfor %}
</ul>
{% endfor %}
</div>
{% endfor %}
</div>
Любая помощь будет очень признательна
На мой взгляд, вы можете значительно упростить свои модели. Вы указываете от тега в NoteModel к NoteTagModel и наоборот & я не думаю, что это необходимо. Также TaggedModel кажется излишней. По крайней мере, если нет конкретной причины связывать их так, как вы это сделали.
class NoteModel(models.Model):
note = models.CharField(max_length = 5000)
note_title = models.CharField(max_length=500, blank=False, null=True)
project = models.ForeignKey(IndividualProject, on_delete=models.CASCADE, related_name="note_projects", blank=False, null=True)
// plural
tags = models.ManyToManyField(NoteTagModel, related_name="tags", blank=False)
def __str__(self):
return self.note_title
class NoteTagModel(models.Model):
// usually there is no need to point here again to the same model thats already pointing to this one
tag_title = models.CharField(max_length=200, default="General")
def __str__(self):
return self.tag_title
Если вы хотите получить обратный доступ от NoteTagModel к NoteModel, вы можете сделать следующее, например:
for tag in NoteTagModel.objects.all():
for note in tag.nodemodel_set.all():
print(note.note_title)
…
(я заключил html-классы в двойные кавычки)
<div class="note_overview_container">
{% for note in notes %}
<div class="individual_note_container">
<div class="note_title">
{{ note.note_title }}
</div>
<!-- loop over all the tags related to the note -->
{% for tag in note.tags.all %}
<div class=”tag_title”>
{{ tag.tag_title }}
</div>
<ul class="tag_commentary">
// commentary in commentary shouldnt be named the same
{% for comment in commentary %}
{% if note_tag == comment.tag_title %}
{% if note == comment.note %}
<li>{{ comment.tag_commentary }}</li>
{% endif %}
{% endif %}
{% endfor %}
</ul>
{% endfor %}
</div>
{% endfor %}
</div>