Вывод связанных данных из двух и более таблиц в представлении DetailView

Рейтинг: 0Ответов: 1Опубликовано: 10.05.2023

Не нашел информации как передаются все именованные аргументы **kwargs в переопределенном методе get_context_data в вызове представления.

Есть 3 модели:

class User(models.Model):
    email = models.CharField(unique=True)
    company_id = models.IntegerField(blank=True, null=True)
    first_name = models.CharField(blank=True, null=True)
    last_name = models.CharField(blank=True, null=True)
class Company(models.Model):
    logo = models.CharField(blank=True, null=True)
    name = models.CharField(blank=True, null=True)
    full_name = models.CharField(blank=True, null=True)
    address = models.CharField(blank=True, null=True)
    phone = models.CharField(blank=True, null=True)
    email = models.CharField(blank=True, null=True)
    kpp = models.CharField(blank=True, null=True)
    okved = models.CharField(blank=True, null=True)
    bik = models.CharField(blank=True, null=True)   
class Order(models.Model):
    user_id = models.IntegerField(blank=True, null=True)
    amount_total_cents = models.BigIntegerField()
    amount_mean_cents = models.BigIntegerField()
    created_at = models.DateTimeField()

Связь между моделями:

Компания-Юзер 1кМ, Юзер-Заказ 1кМ

При прямых выводах данных в представлении без переопределения метода get_context_data проблем нет. Впрочем, нет проблем и при переопределении метода и связывании через первичный ключ двух таблиц:

1. company/urls.py

urlpatterns = [
    path('company/<int:pk>', CompanyShow.as_view(), name='company_show')
]

company/views.py

class CompanyShow(DetailView):
    model = Company
    template_name = 'company/company_show.html'
    context_object_name = 'company'

    def get_context_data(self, **kwargs):
        context = super(CompanyShow, self).get_context_data(**kwargs)
        context['users'] = User.objects.filter(company_id = self.kwargs['pk'])
        return context

company_show.html

    <p>ID: {{ company.id }}</p>
    <p>Наименование: {{ company.name }}</p>
    <p>Сотрудники:
    {% for user in users %}
        <li>
        <a href="{% url 'user:user_show' user.id %}">{{ user }}</a>
        </li>
    {% endfor %}
    </p>

2. user/urls.py

urlpatterns = [
    path('user/<int:pk>', UserShow.as_view(), name='user_show')
]

user/views.py

class UserShow(DetailView):
    model = User
    template_name = 'user/user_show.html'
    context_object_name = 'user'

user_show.html

    <p>ID: {{ user.id}}</p>
    <p>Имя: {{ user.first_name }}</p>
    <p>Фамилия: {{ user.last_name }}</p>
    {% if user.company_id %}
        <a href="{% url 'company:company_show' user.company_id %}">
            Профиль компании (id {{ user.company_id }})
        </a>
    {% else %}
        Нет привязки к компании
    {% endif %}

Однако, сложность в том, когда связывание идет в заказах:

order/urls.py

urlpatterns = [
    path('order/<int:pk>', OrderShow.as_view(), name='order_show')
]

order/views.py

class OrderShow(DetailView):
    model = Order
    template_name = 'order/order_show.html'
    context_object_name = 'order'

    def get_context_data(self, **kwargs):
        context = super(OrderShow, self).get_context_data(**kwargs)
        context['users'] = User.objects.filter(id = self.kwargs['user_id'])  
        return context

order_show.html

    <p> Сотрудник:
    {% for user in users %}
        <li>
        <a href="{% url 'user:user_show' user.id %}">{{ user }}</a>
        </li>
    {% endfor %}
    </p>

Ошибка:

Exception Type:     KeyError
Exception Value:    'user_id'

Вопрос следующий:

Какой параметр для матчинга передаваться должен из **kwargs в order/views.py, чтобы список нужных объектов был отфильтрован согласно id таблицы юзера в таблице заказов поля user_id? Причем по итогу в html вывести требуется компанию - как для этого связать следом таблицу юзеров и компанию?

print(self.kwargs) # {'pk': 554} print(kwargs) # {'object': <Order: № 554>}

Выходит, что аргументы не добавляются в текущей реализации.

Ответы

▲ 0Принят

Оказалось все просто, если копать не в сторону kwargs: context['users'] = User.objects.filter(id = self.object.user_id)

Итоговое представление:

class OrderShow(DetailView):
    model = Order
    template_name = 'order/order_show.html'
    context_object_name = 'order'
    
    def get_context_data(self, **kwargs):
        context = super(OrderShow, self).get_context_data(**kwargs)   
        context['users'] = User.objects.filter(id = self.object.user_id)  
        return context

А вот с 3 таблицами, где у двух нет прямой связи:

class OrderShow(DetailView):
    model = Order
    template_name = 'order/order_show.html'
    context_object_name = 'order'
    
    def get_context_data(self, **kwargs):
        context = super(OrderShow, self).get_context_data(**kwargs)   
        context['users'] = User.objects.filter(id = self.object.user_id)        
        for user in context['users']:
            context['companies'] = Company.objects.filter(id=user.company_id)
        return context