Wie kann ich dem Django-Administrator einen benutzerdefinierten Filter hinzufügen (die Filter, die auf der rechten Seite eines Modell-Dashboards angezeigt werden)? Ich weiß, dass es einfach ist, einen Filter einzuschließen, der auf einem Feld dieses Modells basiert, aber was ist mit einem "berechneten" Feld wie diesem:
class NewsItem(models.Model):
headline = models.CharField(max_length=4096, blank=False)
byline_1 = models.CharField(max_length=4096, blank=True)
dateline = models.DateTimeField(help_text=_("date/time that appears on article"))
body_copy = models.TextField(blank=False)
when_to_publish = models.DateTimeField(verbose_name="When to publish", blank=True, null=True)
# HOW CAN I HAVE "is_live" as part of the admin filter? It's a calculated state!!
def is_live(self):
if self.when_to_publish is not None:
if ( self.when_to_publish < datetime.now() ):
return """ <img alt="True" src="/media/img/admin/icon-yes.gif"/> """
else:
return """ <img alt="False" src="/media/img/admin/icon-no.gif"/> """
is_live.allow_tags = True
class NewsItemAdmin(admin.ModelAdmin):
form = NewsItemAdminForm
list_display = ('headline', 'id', 'is_live')
list_filter = ('is_live') # how can i make this work??
python
django
django-admin
sghael
quelle
quelle
Antworten:
Vielen Dank an gpilotino, der mir den Schub in die richtige Richtung gegeben hat, um dies umzusetzen.
Ich habe festgestellt, dass der Code der Frage eine Datumszeit verwendet, um herauszufinden, wann sie aktiv ist. Also habe ich die DateFieldFilterSpec verwendet und sie in Unterklassen unterteilt.
from django.db import models from django.contrib.admin.filterspecs import FilterSpec, ChoicesFilterSpec,DateFieldFilterSpec from django.utils.encoding import smart_unicode from django.utils.translation import ugettext as _ from datetime import datetime class IsLiveFilterSpec(DateFieldFilterSpec): """ Adds filtering by future and previous values in the admin filter sidebar. Set the is_live_filter filter in the model field attribute 'is_live_filter'. my_model_field.is_live_filter = True """ def __init__(self, f, request, params, model, model_admin): super(IsLiveFilterSpec, self).__init__(f, request, params, model, model_admin) today = datetime.now() self.links = ( (_('Any'), {}), (_('Yes'), {'%s__lte' % self.field.name: str(today), }), (_('No'), {'%s__gte' % self.field.name: str(today), }), ) def title(self): return "Is Live" # registering the filter FilterSpec.filter_specs.insert(0, (lambda f: getattr(f, 'is_live_filter', False), IsLiveFilterSpec))
Zur Verwendung können Sie den obigen Code in eine filter.py einfügen und in das Modell importieren, zu dem Sie den Filter hinzufügen möchten
quelle
Sie müssen eine benutzerdefinierte FilterSpec schreiben (nirgendwo dokumentieren). Schauen Sie sich hier ein Beispiel an:
http://www.djangosnippets.org/snippets/1051/
quelle
In der aktuellen Django-Entwicklungsversion werden benutzerdefinierte Filter unterstützt: https://docs.djangoproject.com/de/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_filter
quelle
Das kannst du leider nicht. Derzeit können Nicht-Feldelemente nicht als list_filter-Einträge verwendet werden.
Beachten Sie, dass Ihre Admin-Klasse nicht funktioniert hätte, selbst wenn es sich um ein Feld handelte, da ein Tupel mit einem einzelnen Element ein Komma benötigt:
('is_live',)
quelle
Nur eine Randnotiz: Sie können die taubstummen Häkchen auf dem Django-Administrator einfacher wie folgt verwenden:
def is_live(self): if self.when_to_publish is not None: if ( self.when_to_publish < datetime.now() ): return True else: return False is_live.boolean = True
quelle
Kein optimaler Weg (CPU-weise), aber einfach und wird funktionieren, also mache ich es so (für meine kleine Datenbank). Meine Django-Version ist 1.6.
In admin.py:
class IsLiveFilter(admin.SimpleListFilter): title = 'Live' parameter_name = 'islive' def lookups(self, request, model_admin): return ( ('1', 'islive'), ) def queryset(self, request, queryset): if self.value(): array = [] for element in queryset: if element.is_live.__call__() == True: q_array.append(element.id) return queryset.filter(pk__in=q_array)
...
class NewsItemAdmin(admin.ModelAdmin): form = NewsItemAdminForm list_display = ('headline', 'id', 'is_live') list_filter = (IsLiveFilter)
Die Schlüsselidee hierbei ist der Zugriff auf benutzerdefinierte Felder in einem QuerySet über die Funktion __call __ () .
quelle
Der Benutzer liefert Waren in einige Länder portofrei. Ich wollte diese Länder filtern:
Alle - alle Länder, Ja - portofrei, Nein - Porto.
Die Hauptantwort auf diese Frage hat bei mir nicht funktioniert (Django 1.3). Ich denke, weil
field_path
die__init__
Methode keinen Parameter enthält . Auch es wurde untergeordnetDateFieldFilterSpec
. Daspostage
Feld ist ein FloatFieldfrom django.contrib.admin.filterspecs import FilterSpec class IsFreePostage(FilterSpec): def __init__(self, f, request, params, model, model_admin, field_path=None): super(IsFreePostage, self).__init__(f, request, params, model, model_admin, field_path) self.removes = { 'Yes': ['postage__gt'], 'No': ['postage__exact'], 'All': ['postage__exact', 'postage__gt'] } self.links = ( ('All', {}), ('Yes', {'postage__exact': 0}), ('No', {'postage__gt': 0})) if request.GET.has_key('postage__exact'): self.ttl = 'Yes' elif request.GET.has_key('postage__gt'): self.ttl = 'No' else: self.ttl = 'All' def choices(self, cl): for title, param_dict in self.links: yield {'selected': title == self.ttl, 'query_string': cl.get_query_string(param_dict, self.removes[title]), 'display': title} def title(self): return 'Free Postage' FilterSpec.filter_specs.insert(0, (lambda f: getattr(f, 'free_postage', False), IsFreePostage))
In self.links liefern wir Diktate. wird verwendet, um HTTP-Abfragezeichenfolgen wie
?postage__exact=0
für jeden der möglichen Filter zu erstellen. Filter sind meiner Meinung nach kumulativ. Wenn also zuvor eine Anfrage für "Nein" gestellt wurde und wir jetzt eine Anfrage für "Ja" haben, müssen wir die Abfrage "Nein" entfernen.self.removes
Gibt an, was für jede Abfrage entfernt werden muss. Diechoices
Methode erstellt die Abfragezeichenfolgen, gibt an, welcher Filter ausgewählt wurde, und legt den angezeigten Namen des Filters fest.quelle
Hier ist die Antwort und implementiert den benutzerdefinierten Filter so einfach wie möglich, dies könnte helfen
Django Admin Datumsbereich Filter
quelle