Django ListView: Как я могу создать условный атрибут, доступный в моем шаблоне? - PullRequest
1 голос
/ 04 августа 2020

Я использую ListView для вывода списка некоторых объектов из модели. Я хочу выделить записи в отображаемом списке, где указанный элемент был создан текущим пользователем, и я планирую сделать это с помощью небольшой цветной точки (кружка), созданной с использованием CSS. Вот тестовый пример.

# models.py

from django.db import models
from django.contrib.auth.models import User

class Foo(models.Model):
    created_by = models.ForeignKey(
        User,
        to_field='username',
        on_delete=models.PROTECT,
        related_name='foos_as_usernames',
        blank=False
    )
    stuff = models.CharField(max_length=128, blank=True)
#views.py

from django.views.generic import ListView

class FooListView(ListView):
    model = Foo

    def get_context_data(self, **kwargs):
        context = super(FooListView, self).get_context_data(**kwargs)

        # Here I want to conditionally set a dot_class attribute based on
        # comparing Foo.created_by with the current user, i.e.
        # if object.created_by == user:
        #     object.dot_class = 'its-me'
        # What do I add here to create the dot_class attribute in the object_list?
        # Is there some other way I can pass a list to the foo_list.html template?

        return context

# foo_list.html

{% load static %}
<!DOCTYPE html>
<html>
<head>
    <title>FooBar</title>
    <style>
        .its-me { height: 8px; width: 8px; background-color: dodgerblue; border-radius: 50%; display: inline-block; }
    </style>
</head>
<body>
    <table>
        <tr>
            <th>&nbsp;</th>
            <th>Stuff</th>
        </tr>
        {% for obj in object_list %}
        <tr>
            <td><span class="{{ obj.dot_class }}"></span></td>
            <td>{{ obj.stuff }}</td>
        </tr>
        {% endfor %}
    </table>
</body>

По ряду причин мне нужно сделать это в CBV, а не аннотировать объекты в модели.

Как я могу добавить атрибут к объектам в контексте object_list? Или как передать список в свой шаблон?

Спасибо и всего наилучшего ... Пол

Ответы [ 3 ]

2 голосов
/ 04 августа 2020

, если вы хотите отправить как шаблон переменной, попробуйте этот способ:

def get_context_data(self, **kwargs):
    context = super(FooListView, self).get_context_data(**kwargs)
    foo_list = context['foo_list']
    for object in foo_list:
        if object.created_by == self.request.user:
            foo.dot_class = 'its-me'
            foo.save()
    context['foo_list'] = foo_list
    return context

, тогда вы можете использовать его непосредственно в шаблоне:

<td><span class="{{obj.dot_class}}"></span></td>
0 голосов
/ 05 августа 2020

@ Ответ Прутви Барота очень помог, но не совсем то, что мне нужно. Я понял, что вы не можете связываться с object_list и не можете перебирать object_list и другой список в том же блоке кода. Чтобы преодолеть это, я создаю полностью новый единый список, который объединяет данные object_list с новыми данными и перебираю их. Вот код:

# models.py

from django.db import models
from django.contrib.auth.models import User

class Foo(models.Model):
    created_by = models.ForeignKey(
        User,
        to_field='username',
        on_delete=models.PROTECT,
        related_name='foos_as_usernames',
        blank=False
    )
    stuff = models.CharField(max_length=128, blank=True)

# views.py

from django.views.generic import ListView

class FooListView(ListView):
    model = Foo

    class NewFoo:
        def __init__(self, created_by, stuff, dot_class):
            self.created_by = created_by
            self.stuff = stuff
            self.dot_class = dot_class

    def get_context_data(self, **kwargs):
        context = super(FooListView, self).get_context_data(**kwargs)

        new_foo_list = []
        foo_list = context['foo_list']

        for foo in foo_list:
            dot_class = ''
            if foo.created_by == self.request.user:
                dot_class = 'its-me'

            new_foo = self.NewFoo(foo.created_by, foo.stuff, dot_class)
            new_foo_list.append(new_foo)

        context['new_foo_list'] = new_foo_list

        return context
# foo_list.html

{% load static %}
<!DOCTYPE html>
<html>
<head>
    <title>FooBar</title>
    <style>
        .its-me { height: 8px; width: 8px; background-color: dodgerblue; border-radius: 50%; display: inline-block; }
    </style>
</head>
<body>
    <table>
        <tr>
            <th>&nbsp;</th>
            <th>Stuff</th>
        </tr>
        {% for obj in new_foo_list %}
        <tr>
            <td><span class="{{ obj.dot_class }}"></span></td>
            <td>{{ obj.stuff }}</td>
        </tr>
        {% endfor %}
    </table>
</body>
0 голосов
/ 04 августа 2020

Возможно, вы можете напрямую использовать данные аутентификации, которые уже доступны в вашем шаблоне, если вы хотите обрабатывать конкретно объекты, принадлежащие текущему подключенному пользователю: cf django do c authentication-data-in -templates Итак, ваш шаблон будет выглядеть примерно так:

...
<body>
<table>
    <tr>
        <th>&nbsp;</th>
        <th>Stuff</th>
    </tr>
    {% for obj in object_list %}
    <tr>
        <td><span class={% if user.is_authenticated and obj.created_by == user%}"MY_FOO"{% else %}"OTHERS_FOO"{% endif%}></span></td>
        <td>{{ obj.stuff }}</td>
    </tr>
    {% endfor %}
</table>
....
</body>
...