Request Set Limit for ManyToMany MultipleSelect in Django Admin

I have a model that looks like this:

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

However, in the django admin MultipleSelect form field that appears for event_dates in EventAdmin , I would like to limit the set of event_dates requests that were not in the past.

The query will look something like this:

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

But where can I set this set of queries so that only dates that have not passed appear in the field?

(I currently do not have a custom form for EventAdmin , but we will add it with pleasure.)

+6
source share
2 answers

You can 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 displayed, even if some dates in the past are still related to Event .

If you also need all the dates that you previously associated with Event , you could manipulate ModelForm as follows

 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'] 
+14
source

The easiest way is to do it in 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 benefit that it only returns dates for the current event that you are watching, 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__id=event_id, event_date__gte = datetime.date.today() ) super().get_field_queryset(db, db_field, request) 
+2
source

Source: https://habr.com/ru/post/945522/


All Articles