Python3 / Django-QuerySet不更新

时间:2018-10-23 19:16:58

标签: python django

我正在创建一个允许创建事件的网站,这些事件将同时显示在主页和事件列表上,以便人们可以单击事件以查看事件的描述,以及在活动中签到。在添加新事件时,如何在类中设置查询集以进行更新时遇到问题。

因此,此功能用于我们的主页。每次返回页面时,query_set都会更新,因此,添加新事件后,该事件将显示在此页面上。

def index(request):
    num_future_events = Event.objects.filter(date__gte=today).filter(approved=True).count()
    query_set = Event.objects.filter(date__gte=today).filter(approved=True).order_by('date', 'time')[:3]

    context = {
        'num_future_events': num_future_events,
        'query_set': query_set
    }

    return render(request, 'index.html', context=context)

这是我网站上事件列表页面的类。它使用查询集,但由于该类仅被调用一次,因此查询集将仅使用该类的初始化进行更新。

class EventListView(generic.ListView):
    model = Event
    query_set = Event.objects.filter(date__gte=today).exclude(approved=False).order_by('date', 'time')[:21]
    template_name = 'listPage.html'

    def get_queryset(self):
        return self.query_set

我希望获得帮助,以便在添加新事件时,EventListView类中设置的查询会自动更新,以使其显示在此页面上。

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:3)

如果我们看一下Django's source code for a ListView,我们会看到:

def get_queryset(self):
    """
    Return the list of items for this view.
    The return value must be an iterable and may be an instance of
    `QuerySet` in which case `QuerySet` specific behavior will be enabled.
    """
    if self.queryset is not None:
        queryset = self.queryset
        if isinstance(queryset, QuerySet):
            queryset = queryset.all()
    elif self.model is not None:
        queryset = self.model._default_manager.all()
    else:
        raise ImproperlyConfigured(
            "%(cls)s is missing a QuerySet. Define "
            "%(cls)s.model, %(cls)s.queryset, or override "
            "%(cls)s.get_queryset()." % {
                'cls': self.__class__.__name__
            }
        )
    ordering = self.get_ordering()
    if ordering:
        if isinstance(ordering, str):
            ordering = (ordering,)
        queryset = queryset.order_by(*ordering)
    return queryset

Django因此每次构造一个 new 查询集时,通过调用.all(),它会生成该查询集的 unvaluated 克隆,从而迫使其重新评估。

在这种情况下,我建议您不要覆盖get_queryset,而只需使用queryset属性,例如:

class EventListView(generic.ListView):
    model = Event
    queryset = Event.objects.filter(
        date__gte=today
    ).exclude(
        approved=False
    ).order_by('date', 'time')[:21]
    template_name = 'listPage.html'

或者,如果您真的想覆盖get_queryset函数,可以使用:

class EventListView(generic.ListView):
    model = Event
    template_name = 'listPage.html'

    def get_queryset(self):
        return Event.objects.filter(
            date__gte=today
        ).exclude(approved=False).order_by('date', 'time')[:21]

或:

class EventListView(generic.ListView):
    model = Event
    template_name = 'listPage.html'
    query_set = Event.objects.filter(
        date__gte=today
    ).exclude(approved=False).order_by('date', 'time')[:21]

    def get_queryset(self):
        return self.query_set.all()