【问题标题】:limiting the queryset for ManyToMany MultipleSelect in Django admin在 Django admin 中限制 ManyToMany MultipleSelect 的查询集
【发布时间】:2013-05-21 20:50:40
【问题描述】:

我有一个看起来像这样的模型:

class Event(models.Model):
    event_dates = ManyToManyField("EventDate")
    #...

class EventDate(models.Model):
    event_date = DateField()
    #...

但是,在 EventAdmin 中显示 event_dates 的 django admin MultipleSelect 表单字段中,我想将查询集限制为不是过去的 event_dates。

查询集类似于:

event_date_queryset = EventDate.objects.filter(event_date__gte = datetime.date.today()) 

但是我在哪里可以设置这个查询集,以便在字段中只显示非过去日期?

(我目前没有EventAdmin 的自定义表单,但很乐意添加一个。)

【问题讨论】:

标签: django django-admin


【解决方案1】:

你可以试试:

event_dates = models.ManyToManyField("EventDate", limit_choices_to={'event_date__gte': date.today()})

取自https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.ForeignKey.limit_choices_to

但随后仅显示未来的日期,即使过去的某些日期仍与 Event 相关联。

如果您还想要之前与Event 关联的所有日期,您可以按以下方式操作ModelForm

from datetime import date

from django.contrib import admin
from django import forms
from django.db.models import Q

from models import Event, EventDate

class EventAdminForm(forms.ModelForm):
    class Meta:
        model = Event

    def __init__(self, *args, **kwargs):
        super(EventAdminForm, self).__init__(*args, **kwargs)
        if 'event_dates' in self.initial:
            self.fields['event_dates'].queryset = EventDate.objects.filter(Q(pk__in=self.initial['event_dates']) | Q(event_date__gte=date.today()))
        else:
            self.fields['event_dates'].queryset = EventDate.objects.filter(event_date__gte=date.today())

class EventAdmin(admin.ModelAdmin):
    form = EventAdminForm
    filter_horizontal = ['event_dates']

【讨论】:

  • 是的,我的意思是 event_dates 并更新了问题以准确反映这一点。希望保留过去但已选择的 event_dates 的好处。更完整的解决方案可能是我所追求的,尽管我通过 limit_choices_to 学到了一些新东西。谢谢!
  • 我最终几乎一字不差地使用了第二种(更全面的)方法,效果很好。
  • 这太棒了。
【解决方案2】:

最简单的方法是在管理员中完成

你的模型

class Event(models.Model):
    event_dates = ManyToManyField("EventDate")
    #...

class EventDate(models.Model):
    event_date = DateField()
    #...

现在在您的管理文件中

这有一个额外的好处,它只返回您正在使用反向查找event__id=event_id查看的当前事件的事件日期

class EventAdmin(admin.ModelAdmin):
    def get_field_queryset(self, db, db_field, request):
        """
        If the ModelAdmin specifies ordering, the queryset should respect that
        ordering.  Otherwise don't specify the queryset, let the field decide
        (returns None in that case).
        """
        if db_field.name == 'event_dates':
            event_id = int(request.resolver_match.args[0])

            return db_field.remote_field.model._default_manager.filter(
                              event__id=event_id,
                              event_date__gte = datetime.date.today()
            )

        super().get_field_queryset(db, db_field, request)

【讨论】:

  • 对于 Django 2 应用程序,我只需要将 id get 更改为 request.resolver_match.kwargs['object_id']
猜你喜欢
  • 2013-02-11
  • 2015-06-23
  • 1970-01-01
  • 2016-10-26
  • 1970-01-01
  • 1970-01-01
  • 2011-10-05
  • 1970-01-01
  • 2011-09-01
相关资源
最近更新 更多