如何为django QuerySet的每个条目添加一些上下文

时间:2015-09-20 20:26:22

标签: python django django-queryset

我使用Django 1.8.4和Python 3.4

我有一个锦标赛模型,它定义了一个方法,如果禁止订阅,该方法会返回一个字符串。

class Tournament(models.Model):
    name = models.CharField(max_length=200, null=True, blank=True)
    subscriptions = models.ManyToManyField('ap_users.Profile')
    is_subscription_open = models.BooleanField(default=True)
    # ...

    def why_subscription_impossible(self, request):
        if not request.user.profile.is_profile_complete():
            return 'Your profile is not complete'
        elif not self.is_subscription_open:
            return 'Subscriptions are closed'
        elif <another_condition>:
            return 'Another error message'

        return None

我想使用通用ListView显示锦标赛列表,我想使用方法的结果来修改它的显示方式:

<table class="table">
    <thead>
        <td>Tournament</td>
        <td>Subscription</td>
    </thead>
    {% for tournament in tournament_list %}
        <tr>
            <td>{{ tournament.name }}</td>
            <td>
                {% if tournament.why_subscription_impossible %}
                    {{ tournament.why_subscription_impossible }}
                {% else %}
                    <a href="{% url 'ap_tournament:subscribe' tournament.id %}">Subscribe</a>
                {% endif %}
            </td>
        </tr>
    {% endfor %}
</table>

视图是从generic.ListView继承的基于类的通用视图。

class IndexView(generic.ListView):
    template_name = 'ap_tournament/index.html'

    def get_queryset(self):
        return Tournament.objects.all()

显示的解决方案不起作用,因为我需要传递当前请求,以获取有关已登录用户的信息。所以我尝试将方法的结果添加到视图中的上下文

class IndexView(generic.ListView):
    template_name = 'ap_tournament/index.html'

    def get_queryset(self):
        return Tournament.objects.all()

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

        additional_ctx_info = []
        for tournament in self.get_queryset():
            additional_ctx_info.append({
                'reason_to_not_subscribe': tournament.why_subscription_impossible(self.request)
            })

        context['subscr_info'] = additional_ctx_info
        return context

显然,这也不起作用。我不知道如何使用tournament_list中的当前索引访问subscr_info[n]。我知道获取索引的forloop.counter0,但我无法在模板中使用它(或者我不知道如何使用)。我试过了:

  • {{ subscr_info.forloop.counter0.reason_to_not_subscribe }}
  • {{ subscr_info.{{forloop.counter0}}.reason_to_not_subscribe }}

我还尝试在get_queryset()视图方法中注释QuerySet并读取有关aggregate()的内容,但我觉得这只适用于数据库支持的操作(AVG,COUNT,MAX等)。

我还觉得使用过滤器或模板标签在我的情况下不起作用,因为我需要在if标签中使用该方法的结果。

是否有更好的解决方案或完全不同的方法来实现我的目标?

2 个答案:

答案 0 :(得分:0)

您必须在views.py文件中创建tournament_list,并根据用户是否已记录并具有相应权限进行设置。

如果您需要计算某些内容,可以创建以下Counter类:

class Counter:
    count = 0

    def increment(self):
        self.count += 1
        return ''

    def decrement(self):
        self.count -= 1
        return ''

然后,您可以致电{{ counter.increment }}{{ counter.count }}在模板中使用它。 ({{ subscr_info.{{counter.count}}.reason_to_not_subscribe }}并且不要忘记在您的循环中放置{{ counter.increment }}

然而,我使用的更好的解决方法是创建一个包含主要元素和附加信息的字典,即

ctx_info = []
for tournament in self.get_queryset():
    ctx_info.append({
        'tournament': tournament
        'reason_to_not_subscribe': tournament.why_subscription_impossible(self.request)
    })

然后在ctx_info上循环。它更干净,但我不知道如何在ListView(我从未使用过)中实现它

顺便说一句,您的模板包含{{ why_subscription_impossible }}而非{{ tournament.why_subscription_impossible }},我不知道是否有意...

答案 1 :(得分:0)

在您看来,您也可以这样做:

tournaments = self.get_queryset()
for tournament in tournaments:
    tournament.reason_to_not_subscribe = tournament.why_subscription_impossible(self.request)

然后将tournaments添加到上下文中。