2013-05-21 13 views
6

Ho un modello che assomiglia a questo:limitare il set di query per ManyToMany MultipleSelect in Django Admin

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

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

Tuttavia, in Django di amministrazione MultipleSelect campo modulo che ottiene mostrare per event_dates nel EventAdmin, mi piacerebbe per limitare il queryset a date_evento che non sono nel passato.

Il set di query sarebbe qualcosa di simile:

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

Ma dove posso impostare questo set di query in modo che solo le date non ultimi appaiono nel campo?

(non hanno attualmente un modulo personalizzato per la EventAdmin, ma sarei felice di aggiungere uno.)

+0

Eventuali duplicati di [scatola ManyToMany Filtro in Django Admin] (http: // stackoverflow.com/questions/1226760/filter-manytomany-box-in-django-admin) – Wtower

risposta

14

si potrebbe provare:

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

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

ma poi vengono visualizzate solo le date future, anche se alcune date nel passato sono ancora associate a Event.

Se si desidera anche tutte le date che precedentemente associato a Event si poteva manipolare ModelForm come segue

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'] 
+0

sì, intendevo event_dates e ho aggiornato la domanda per rispecchiarlo accuratamente. Buon punto a voler mantenere event_date che sono nel passato ma già selezionate. La soluzione più completa è probabilmente quella che sto cercando, anche se ho imparato qualcosa di nuovo con limit_choices_to. Grazie! –

+0

Ho finito per usare il secondo approccio (più completo) quasi alla lettera, funziona alla grande. –

2

modo più semplice è quello di farlo in admin

I suoi modelli

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

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

Ora nel tuo file admin

Questo ha il vantaggio che restituisce solo date degli eventi solo per l'evento in corso che si sta cercando di usare la ricerca inversa 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)