Есть ли более изящное решение?

Представим, что есть две модели models.py
Мне нужно вывести список всех магазинов, но под каждым вывести список принадлежащих ему номеров телефонов. Решал 2 дня. И вот как я ее решил...
class Store(models.Model):
    name = models.CharField(max_length=200)
    address = models.CharField(max_length=200)

class Phones(models.Model):
    phone = models.CharField(max_length=50)
    store = models.ForeignKey(Store)

vievs.py
from django.shortcuts import render
from .models import Store, Phones

def get_store():
    stores = []
    for line in Store.objects.all():
        phone = line.phones_set.filter(show=1)
        l = []
        l.append(line)
        l.append(phone)
        stores.append(l)
    return stores

def index(request):
    template = 'myhomechita/page.html'
    context = { 'stores': get_store,}
    return render(request, template, context)

Часть шаблона
{% if stores %}
    <div class="footer-col-2">
        <div class="col-name">Наши магазины</div>
        <ul class='stores'>
        {% for block in stores %}
            <li>
            {% for unit in block %}
                {% if forloop.counter == 1 %}
                    <span>{{ unit.name }} - {{ unit.address }}</span>
                {% else %}
                <ul>
                    {% for phone in unit %}
                    <li>{{ phone.name }}: {{ phone.phone }}</li>
                    {% endfor %}
                </ul>
                {% endif %}
            {% endfor %}
            </li>
        {% endfor %}
        </ul>
    </div>
{% endif %}
  • Вопрос задан
  • 395 просмотров
Решения вопроса 1
dizballanze
@dizballanze
Software developer at Yandex
Не очень понятно зачем вы формируете список, можно просто передать в шаблон queryset, а всю остальную работу сделать в шаблоне, т.к. вы в шаблоне можете делать цикл по queryset. Шаблон в итоге примерно так буде выглядеть:
{% if stores_queryset %}
    <div class="footer-col-2">
        <div class="col-name">Наши магазины</div>
        <ul class='stores'>
        {% for store in stores_queryset %}
            <li>
                <span>{{ store.name }} - {{ store.address }}</span>
                <ul>
                    {% for phone in store. phones_set %}
                    <li>{{ phone.name }}: {{ phone.phone }}</li>
                    {% endfor %}
                </ul>
            </li>
        {% endfor %}
        </ul>
    </div>
{% endif %}

Насчет фильтрации телефонов с учетом show=1. Можно сделать кастомный manager, и тогда в phones_set будут уже только отфильтрованные телефоны.
Или проще - сделать property в моделе Store:
class Store(models.Model):
    name = models.CharField(max_length=200)
    address = models.CharField(max_length=200)

    @property
    def showed_phones(self):
        return self.phones_set.filter(show=1)

и тогда в шаблоне в соотв месте нужно юзать цикл {% for phone in store. showed_phones %}
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
@decembrin Автор вопроса
'stores': Store.objects.all()
{% if stores %}
                <div class="footer-col-2">
                    <div class="col-name">Наши магазины</div>
                    <ul class='stores'>
                    {% for store in stores_queryset %}
                        <li>
                            <span>{{ store.name }} - {{ store.address }}</span>
                            <ul>
                                {% for phone in store.phones_set %}
                                <li>{{ phone.name }}: {{ phone.phone }}</li>
                                {% endfor %}
                            </ul>
                        </li>
                    {% endfor %}
                    </ul>
                </div>
                {% endif %}

Сделал так, но это ничего не выводит {% for store in stores_queryset %}
Ответ написан
@ATNC
Full-stack web\python developer
В атрибуте store модели Phones добавьте related_name:
class Phones(models.Model):
    phone = models.CharField(max_length=50)
    store = models.ForeignKey(Store, related_name='phone_number')


После этого Вы сможете из модели Store достучаться до телефона вот так:

store = Store.objects.get(pk=1)
phone_num = store.phone_number.phone


Также Вы можете использовать связное имя в шаблонах. Как то так...

{% if stores %}
    <div class="footer-col-2">
        <div class="col-name">Наши магазины</div>
        <ul class='stores'>
        {% for store in stores %}
            <li>
          
                
                    <span>{{ store.name }} - {{ store.address }}</span>
              
                <ul>
                    
                    <li>{{ store.phone_number.name }}: {{ store.phone_number.phone }}</li>
                   
                </ul>
              
           
            </li>
        {% endfor %}
        </ul>
    </div>
{% endif %}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы