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.