Django - Проблема с запросом к БД с использованием внешнего ключа
Я использую Django для веб-приложения и у меня есть следующая модель данных:
class classi(models.Model):
nome = models.TextField(null=True)
class Meta:
db_table = 'classi'
class users(models.Model):
name = models.TextField(null=True)
email = models.TextField(null=True)
password = models.TextField(null=True)
classe = models.ForeignKey(classi, db_column='classe', on_delete=models.CASCADE, null=True)
class Meta:
db_table = 'users'
class smartphone(models.Model):
marca = models.TextField(null=True)
modello = models.TextField(null=True)
possessore = models.ForeignKey(users, db_column='possessore', on_delete=models.CASCADE, null=True)
class Meta:
db_table = 'smartphone'
Моя цель - показать на HTML-странице все классификации, а для каждой классификации - всех пользователей, а для каждого пользователя - все смартфоны.
Как я могу реализовать мой view.py и мой html файл?
Единственное решение, которое я нашел, это просканировать всю таблицу с помощью цикла for и через условие выбрать строку, используя внешний ключ:
{% for c in classi %}
<p>{{ c.nome }}</p>
{% for u in users %}
{% if u.classe == c %}
<p>{{ u.name }}, {{ u.email }}, {{ u.password }}</p>
{% for s in smartphone %}
{% if s.possessore == u %}<p>{{ s.marca }}, {{ s.modello }}</p> {% endif %}
{% endfor %}
{% endif %}
{% endfor %}
{% endfor %}
Есть ли лучшее решение?
Вы можете использовать *prefetch_related для предварительной выборки связанного объекта из внешнего ключа. Дополнительная информация: https://docs.djangoproject.com/fr/4.1/ref/models/querysets/#prefetch-related
Вид:
def view(request):
classe = Classi.objects.all().prefetch_related("users_set").prefetch_related("users_set__smartphone_set")
context["classe"] =) classe
return render(request, 'template.html', context)
И html:
{% for c in classe %}
<p>{{ c.nome }}</p>
{% for u in c.users_set %}
<p>{{ u.name }}, {{ u.email }}, {{ u.password }}</p>
{% for s in u.smartphone_set %}
<p>{{ s.marca }}, {{ s.modello }}</p>
{% endfor %}
{% endfor %}
{% endfor %}
Вы можете использовать обратные отношения, которые будут иметь только элементы, имеющие связь
Общим форматом является obj.{model}_set
, но вы также можете установить его на что-то другое в models.py с помощью related_name
attr в поле ForeignKey
{% for c in classi %}
<p>{{ c.nome }}</p>
{% for u in c.user_set.all %}
<p>{{ u.name }}, {{ u.email }}, {{ u.password }}</p>
{% for s in u.smartphone_set.all %}
<p>{{ s.marca }}, {{ s.modello }}</p>
{% endfor %}
{% endfor %}
{% endfor %}
Или, и это, вероятно, более чистый вариант:
Проделайте обратный путь, перебирая смартфоны в верхней части, и просто упорядочьте смартфоны по имени в представлении с помощью smartphoneList = smartphone.objects.all().order_by('possessore__classe__nome')
, чтобы они были сгруппированы вместе
{% for s in smartphoneList %}
<p>{{ s.possessore.classe.nome }}</p>
<p>{{ s.possessore.name }}, {{ s.possessore.email }}, {{ s.possessore.password }}</p>
<p>{{ s.marca }}, {{ s.modello }}</p>
{% endfor %}
Примечание после написания этого я заметил, что @Lucas Grugru уже выложил обратный путь отношений... Из моего тестирования он не требует предварительной выборки, но, возможно, это хорошая идея (я также не имею понятия). Я все еще публикую это, потому что думаю, что циклический перебор смартфонов может быть более чистым способом сделать это