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 уже выложил обратный путь отношений... Из моего тестирования он не требует предварительной выборки, но, возможно, это хорошая идея (я также не имею понятия). Я все еще публикую это, потому что думаю, что циклический перебор смартфонов может быть более чистым способом сделать это

Вернуться на верх