Django klassenbasierte Ansicht: Wie übergebe ich zusätzliche Parameter an die as_view-Methode?


94

Ich habe eine benutzerdefinierte klassenbasierte Ansicht

# myapp/views.py
from django.views.generic import *

class MyView(DetailView):
    template_name = 'detail.html'
    model = MyModel

    def get_object(self, queryset=None):
        return queryset.get(slug=self.slug)

Ich möchte den Slug-Parameter (oder andere Parameter an die Ansicht) wie folgt übergeben

MyView.as_view(slug='hello_world')

Muss ich Methoden überschreiben, um dies zu tun?

Antworten:


113

Wenn Ihre urlconf ungefähr so ​​aussieht:

url(r'^(?P<slug>[a-zA-Z0-9-]+)/$', MyView.as_view(), name = 'my_named_view')

dann ist der Slug in Ihren Ansichtsfunktionen (wie 'get_queryset') wie folgt verfügbar:

self.kwargs['slug']

18
Um eine Ausnahme zu vermeiden, falls dies ein optionaler Parameter ist: Verwenden Sieself.kwargs.get('slug', None)
Risadinha

6
Nur neugierig, wann / wo ist dieses "self.kwargs" besiedelt? Ich suche nach der Basisklassenfunktion, in der dies eingestellt ist.
Binithb

In github.com/django/django/blob/master/django/views/generic/… inclass View: def as_view(cls, **initkwargs): def view(request, *args, **kwargs):
Apollo Data

Die Frage nicht beantworten.
Kireeti K

Diese Methode ist jetzt veraltet, jetzt können Sie verwendenurl('<slug:slug>', MyView.as_view(), name='my_named_view')
Rahat Zaman

90

Jeder Parameter, der an die as_viewMethode übergeben wird, ist eine Instanzvariable der View-Klasse. Das heißt, um slugals Parameter hinzuzufügen , müssen Sie ihn als Instanzvariable in Ihrer Unterklasse erstellen:

# myapp/views.py
from django.views.generic import DetailView

class MyView(DetailView):
    template_name = 'detail.html'
    model = MyModel
    # additional parameters
    slug = None

    def get_object(self, queryset=None):
        return queryset.get(slug=self.slug)

Das sollte MyView.as_view(slug='hello_world')funktionieren.

Wenn Sie die Variablen über Schlüsselwörter übergeben, verwenden Sie die Vorschläge von Herrn Erikkson: https://stackoverflow.com/a/11494666/9903


2
Mach das niemals import *. Habe deinen Beitrag bearbeitet.
Holms

@holms für die Aufklärung zukünftiger Leser, sagt PEP8 "Wildcard-Importe (vom <Modul> -Import ) sollten vermieden werden". Sollte nicht so stark sein wie muss und dies ist ein Beispiel, aber auf jeden Fall * sollte Wildcard-Importe vermeiden : python.org/dev/peps/pep-0008/#imports

Nichts ist irgendwo ein Muss, wir können alles, was wir wollen, auf jede gewünschte Weise brechen, aber pep8 ist nur eine Empfehlung für Praktiken, und in der Python-Community ist es eine Faustregel, alle diese Praktiken so oft wie möglich zu verwenden, um weitere Probleme zu vermeiden. Mein Linter ist immer leer, wenn ich meinen Code festschreibe :) egal was passiert.
Holms

Was ist der Wert von slug = 'hello_world' für eine tatsächliche Variable?
Gonzalo Dambra

19

Es ist erwähnenswert, dass Sie nicht überschreiben get_object()müssen, um ein Objekt basierend auf einem als Schlüsselwort arg übergebenen Slug nachzuschlagen. Sie können die Attribute von SingleObjectMixin https://docs.djangoproject.com/en/1.5/ref/ verwenden. klassenbasierte Ansichten / mixins-single-object / # singleobjectmixin

# views.py
class MyView(DetailView):
    model = MyModel
    slug_field = 'slug_field_name'
    slug_url_kwarg = 'model_slug'
    context_object_name = 'my_model'

# urls.py
url(r'^(?P<model_slug>[\w-]+)/$', MyView.as_view(), name = 'my_named_view')

# mymodel_detail.html
{{ my_model.slug_field_name }}

(beides slug_fieldund slug_url_kwargstandardmäßig 'slug')


1
Soll ich meine Antwort in eine Wiki-Antwort verwandeln und Ihren Code hinzufügen?

15

Wenn Sie dem Kontext für die Vorlage ein Objekt hinzufügen möchten, können Sie diesen überschreiben get_context_dataund zu seinem Kontext hinzufügen. Die Anfrage ist auch ein Teil von self, falls Sie die request.user benötigen .

def get_context_data(self, **kwargs):
        context = super(MyTemplateView, self).get_context_data(**kwargs)
        if 'slug' in self.kwargs:
            context['object'] = get_object_or_404(MyObject, slug=self.kwargs['slug'])
            context['objects'] = get_objects_by_user(self.request.user)

        return context

Was ist MyObject?
Rob Kwasowski

13

Sie können Parameter von urls.py https://docs.djangoproject.com/de/1.7/topics/http/urls/#passing-extra-options-to-view-functions übergeben

Dies funktioniert auch für allgemeine Ansichten. Beispiel:

url(r'^$', views.SectionView.as_view(), { 'pk': 'homepage', 'another_param':'?'}, name='main_page'),

In diesem Fall sollten die an die Ansicht übergebenen Parameter nicht unbedingt Instanzvariablen der View-Klasse sein. Mit dieser Methode müssen Sie den Standardseitennamen nicht fest in Ihr YourView-Modell codieren, sondern können ihn einfach als Parameter von urlconf übergeben.


danke, ich habe eine ganze Weile danach gesucht!
Ilja

7

Wie durch erklärte Jaroslaw Nikitenko , wenn Sie nicht, eine neue Instanz Variable in die View - Klasse hart codieren möchten , können Sie zusätzliche Optionen übergeben Funktionen anzuzeigen aus urls.pywie folgt aus :

url(r'^$', YourView.as_view(), {'slug': 'hello_world'}, name='page_name')

Ich wollte nur hinzufügen, wie man es aus der Ansicht verwendet. Sie können eine der folgenden Methoden implementieren:

# If slug is optional
def the_function(self, request, slug=None):
    # use slug here

# if slug is an optional param among others
def the_function(self, request, **kwargs):
    slug = kwargs.get("slug", None)
    other_param = kwargs.get("other_param", None)

# If slug is required
def the_function(self, request, slug):
    # use slug here

1
Ich wollte dies in Jaroslaw Nikitenkos Antwort bearbeiten , aber es wurde abgelehnt, also habe ich es mir selbst gemacht, weil ich das Gefühl hatte, dass es die fehlenden Informationen waren, als ich sie brauchte.
Emile Bergeron

danke für deinen Beitrag! Ich erinnere mich nicht, ob ich Ihre Bearbeitung abgelehnt habe und warum.
Jaroslaw Nikitenko

@YaroslavNikitenko Im Nachhinein war es zu groß für eine Bearbeitung und am besten als Antwort in Form einer neuen Antwort.
Emile Bergeron

@EmileBergeron Die erste Frage betraf generische Ansichten wie die DetailViewKlasse. Können Sie erklären, wie man es dort benutzt?
Bartaelterman

2

Für Django 3.0 hat das bei mir funktioniert:

# myapp/views.py
from django.views.generic import DetailView

class MyView(DetailView):
    template_name = 'detail.html'
    slug = None

    def get_object(self, queryset=None):
        self.slug = self.kwargs.get('slug', None)
        return queryset.get(slug=self.slug)

# myapp/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('slug/<slug:slug>/', views.MyView.as_view(), name='myview_by_tag'),
]
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.