2013-09-04 3 views
5

Ich habe ein boolesches Feld auf meinem Modell, das angibt, ob jemand seine Mitgliedschaft abgebrochen hat oder nicht. Ich versuche, einen benutzerdefinierten SimpleListFilter zu erstellen, mit dem dieses Feld gefiltert werden kann.SimpleListFIlter Standard

Allerdings möchte ich nur diejenigen zeigen, die standardmäßig nicht abgebrochen werden. Gibt es eine Möglichkeit, die Option "Nein" standardmäßig auszuwählen? Das ist mein Filter so weit:

class CanceledFilter(SimpleListFilter): 

    title = 'Canceled' 

    # Parameter for the filter that will be used in the URL query. 
    parameter_name = 'canceled' 

    def lookups(self, request, model_admin): 
     return (
      (True, 'Yes'), 
      (False, 'No'), 
     ) 

    def queryset(self, request, queryset): 

     if self.value() is True or self.value() is None: 
      return queryset.filter(canceled=True) 
     if self.value() is False: 
      return queryset.filter(canceled=False) 

EDIT: ich etwas klarer sein sollte. Ich versuche speziell dies in der Admin-Oberfläche zu tun. Wenn ich den obigen Filter als list_filter in admin hinzufüge. Ich bekomme einen Filter auf der Seite der Admin-Seite mit 3 Auswahlmöglichkeiten: Alle, Ja und Nein.

Ich möchte, dass die "Nein" -Auswahl oder keine der Auswahlmöglichkeiten standardmäßig eingestellt ist. Stattdessen ist die Auswahl "Alle" immer standardmäßig festgelegt. Gibt es irgendeinen nicht hacky Weg, die Standardfilterwahl oder etwas so einzustellen.

Grundlegend im Admin, wenn sie die Mitglieder anzeigen, möchte ich nur die aktive (nicht abgebrochen) standardmäßig anzeigen. Wenn sie auf "Alle" oder "Ja" klicken, möchte ich die stornierten anzeigen.

Update: Hinweis das ist das gleiche wie Frage Default filter in Django admin, aber ich diese Frage ist jetzt 6 Jahre alt. Die angenommene Antwort wird als Django 1.4 markiert markiert. Ich bin nicht sicher, ob diese Antwort immer noch mit neueren Django-Versionen funktioniert oder immer noch die beste Antwort ist.

Angesichts des Alters der Antworten auf die andere Frage, bin ich mir nicht sicher, wie wir vorgehen sollten. Ich glaube nicht, dass es einen Weg gibt, die beiden zusammenzuführen.

+0

möglich duplicate von [Standardfilter in Django admin] (http://StackOverflow.com/questions/851636/default-filter-in-django-admin) –

+0

Ich fügte ein Update hinzu, das die doppelte Situation erklärt. Die Fragen sind die gleichen, aber die andere ist jetzt ziemlich alt. Ich bin mir nicht sicher, wie wir vorgehen sollen. – Jon

+0

Die oben gewählte Antwort (nicht die akzeptierte) auf die ältere Frage ist immer noch gültig (Django 1.8) - wie ich dort geäußert habe. Überlassen wir die Entscheidung den Moderatoren. ;) –

Antwort

4

zu tun hatte, das gleiche und stolperte über deine Frage. So habe ich es in meinem Code korrigiert (angepasst an Ihr Beispiel):

class CanceledFilter(SimpleListFilter): 

title = 'Canceled' 

# Parameter for the filter that will be used in the URL query. 
parameter_name = 'canceled' 

def lookups(self, request, model_admin): 
    return (
     (2, 'All'), 
     (1, 'Yes'), 
     (0, 'No'), 
    ) 

def queryset(self, request, queryset): 

    if self.value() is None: 
     self.used_parameters[self.parameter_name] = 0 
    else: 
     self.used_parameters[self.parameter_name] = int(self.value()) 
    if self.value() == 2: 
     return queryset 
    return queryset.filter(cancelled=self.value()) 

Einige Erläuterungen sind erforderlich. Die Querystring ist nur ein Teil der URL und genau das, was der Name impliziert: Eine Abfrage Zeichenfolge. Deine Werte kommen als Strings, nicht als Booleans oder Integers. Wenn Sie also self.value() aufrufen, wird eine Zeichenfolge zurückgegeben.

Wenn Sie die URL untersuchen, die Sie erhalten, wenn Sie auf Ja/Nein klicken, wenn Sie keinen benutzerdefinierten Listenfilter verwenden, wird er als 1/0 angezeigt, nicht als True/False. Ich ging mit dem gleichen Schema.

Für Vollständigkeit und unsere zukünftigen Leser, fügte ich auch 2 für Alle hinzu. Ohne zu überprüfen, nehme ich an, dass das vorher None war. Aber None wird auch verwendet, wenn nichts ausgewählt ist, standardmäßig Alle.Außer, in unserem Fall muss es standardmäßig False sein, also musste ich einen anderen Wert wählen. Wenn Sie die Option Alle nicht benötigen, entfernen Sie einfach den endgültigen if-Block in der Methode queryset und das erste Tupel in der Methode lookups.

So funktioniert es, wie funktioniert es? Der Trick ist, in Erkenntnis, dass self.value() nur zurückgibt:

self.used_parameters.get(self.parameter_name, None) 

das entweder ein String oder None, je nachdem, ob sich der Schlüssel im Wörterbuch gefunden wird oder nicht. Das ist also die zentrale Idee: Wir stellen sicher, dass es Ganzzahlen und keine Zeichenketten enthält, so dass self.value() im Aufruf von queryset.filter() verwendet werden kann. Sonderbehandlung für den Wert für "Alle": 2: Geben Sie in diesem Fall einfach queryset statt eines gefilterten Abfrage-Sets zurück. Ein weiterer spezieller Wert ist None, was bedeutet, dass im Wörterbuch kein Schlüssel parameter_name vorhanden ist. In diesem Fall erstellen wir eins mit dem Wert 0, so dass False der Standardwert wird.

Hinweis: Ihre Logik war dort falsch; Sie möchten standardmäßig nicht storniert werden, aber Sie behandeln None genauso wie True. Meine Version korrigiert das.

ps: ja, könnten Sie für 'True' überprüfen und 'False' statt True und False in Ihrer querystring Methode, aber dann würden Sie die richtige Auswahl bemerken würde, nicht weil hervorgehoben wird die ersten Elemente in Ihrem Tupel nicht zusammenpassen (Sie vergleichen Strings dann mit booleans). Ich habe versucht, die ersten Elemente in den Tupelstrings zu machen, aber dann müsste ich einen Stringvergleich machen oder eval, um 'True' zu True zu entsprechen, was irgendwie hässlich/unsicher ist. Also halte dich am besten an ganze Zahlen, wie in meinem Beispiel.

0

Blick auf Abschnitt namens in dem unten stehenden Link „Extra-Manager Methods Hinzufügen“:

http://www.djangobook.com/en/2.0/chapter10.html

Sie können einen zusätzlichen models.Manager zum Modell hinzufügen, um nur die Menschen zurück, die ihre Mitgliedschaft nicht storniert hat . Eine grobe Umsetzung der zusätzlichen models.Manager würde wie folgt aussehen:

class MemberManager(models.Manager): 
    def get_query_set(self): 
    return super(MemberManager, self).get_query_set().filter(membership=True) 

class Customer(models.Model): 
    # fields in your model 
    membership = BooleanField() # here you can set to default=True or default=False for when they sign up inside the brackets 

    objects = models.Manager # default Manager 
    members = MemberManager() # Manager to filter for members only 

Immer, wenn Sie benötigen nur eine Liste von Ihnen derzeitigen Mitglieder zu bekommen, würden Sie dann rufen Sie einfach:

Customer.members.all() 
+0

Ich habe eine Bearbeitung hinzugefügt, um das Problem besser zu erklären. Ich versuche dies in der Admin-Oberfläche zu tun. Ich denke, ein SimpleListFilter ist der Weg, dies zu erreichen, aber es scheint unmöglich, einen Standardfilterwert zu setzen. – Jon