[Solved]-Limiting the queryset for ManyToMany MultipleSelect in Django admin



You could try:

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

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

but then only dates in the future are shown, even if some dates in the past are still associated to Event.

If you also want all the dates you previously associated to Event you could manipulate ModelForm as following

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()))
            self.fields['event_dates'].queryset = EventDate.objects.filter(event_date__gte=date.today())

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


Simplest way is to do it in the admin

Your models

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

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

Now in your admin file

This has the added advantage that it only returns event dates only for the current event that you are looking at using the reverse lookup 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_date__gte = datetime.date.today()

        super().get_field_queryset(db, db_field, request)
๐Ÿ‘คDr Manhattan

Leave a comment