Vista basata sulla classe Django: come si passano parametri aggiuntivi al metodo as_view?


95

Ho una visualizzazione basata sulla classe personalizzata

# 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)

Voglio passare il parametro slug (o altri parametri alla vista) in questo modo

MyView.as_view(slug='hello_world')

Devo sostituire qualche metodo per poterlo fare?

Risposte:


113

Se il tuo urlconf ha un aspetto simile a questo:

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

quindi lo slug sarà disponibile all'interno delle funzioni di visualizzazione (come 'get_queryset') in questo modo:

self.kwargs['slug']

18
Per evitare un'eccezione nel caso in cui si tratti di un parametro opzionale: utilizzareself.kwargs.get('slug', None)
Risadinha

6
Solo curioso, quando / dove viene popolato questo "self.kwargs"? Sto cercando la funzione della classe di base in cui è impostata.
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

Non rispondere alla domanda.
Kireeti K

Questo metodo è ora deprecato, ora puoi usareurl('<slug:slug>', MyView.as_view(), name='my_named_view')
Rahat Zaman

91

Ogni parametro passato al as_viewmetodo è una variabile di istanza della classe View. Ciò significa che per aggiungere slugcome parametro devi crearlo come variabile di istanza nella tua sottoclasse:

# 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)

Questo dovrebbe MyView.as_view(slug='hello_world')funzionare.

Se stai passando le variabili attraverso parole chiave, usa ciò che ha suggerito Mr Erikkson: https://stackoverflow.com/a/11494666/9903


2
Non farlo mai import *. Ha modificato il tuo post.
holms

@holms per l'illuminazione dei futuri lettori, PEP8 dice "Le importazioni di caratteri jolly (da <module> import ) dovrebbero essere evitate". Non dovrebbe essere forte come deve e questo è un esempio ma sì, sicuramente * dovrebbe evitare le importazioni di caratteri jolly: python.org/dev/peps/pep-0008/#imports

Niente è un must da nessuna parte, possiamo rompere tutto ciò che vogliamo in qualsiasi modo vogliamo, ma pep8 è solo una raccomandazione di pratiche, e nella comunità di python è una regola pratica usare tutte queste pratiche il più possibile per evitare ulteriori problemi. Il mio linter è sempre vuoto quando eseguo il commit del codice :) non importa cosa.
holms

Qual è il valore di slug = 'hello_world' per una variabile effettiva?
Gonzalo Dambra

19

Vale la pena notare che non è necessario eseguire l'override get_object()per cercare un oggetto in base a uno slug passato come parola chiave arg: è possibile utilizzare gli attributi di un SingleObjectMixin https://docs.djangoproject.com/en/1.5/ref/ class-based-views / 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 }}

(entrambi slug_fielde slug_url_kwargpredefinito su 'slug')


1
devo trasformare la mia risposta in una risposta wiki e aggiungervi il vostro codice?

15

Se vuoi aggiungere un oggetto al contesto per il modello, puoi sovrascrivere get_context_datae aggiungere al suo contesto. La richiesta è anche una parte di nel caso in cui sia necessario request.user .

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

Cosa MyObject?
Rob Kwasowski

13

Puoi passare parametri da urls.py https://docs.djangoproject.com/en/1.7/topics/http/urls/#passing-extra-options-to-view-functions

Funziona anche per visualizzazioni generiche. Esempio:

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

In questo caso i parametri passati alla vista non dovrebbero essere necessariamente variabili di istanza della classe View. Utilizzando questo metodo non è necessario codificare il nome della pagina predefinita nel modello YourView, ma puoi semplicemente passarlo come parametro da urlconf.


grazie, lo stavo cercando da un po '!
Ilja

7

Come affermato da Yaroslav Nikitenko , se non si vuole codificare una nuova variabile di istanza alla classe di visualizzazione, è possibile passare le opzioni extra per visualizzare le funzioni da urls.pycome questo:

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

Volevo solo aggiungere come usarlo dalla vista. Puoi implementare uno dei seguenti metodi:

# 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
Volevo modificare questo nella risposta di Yaroslav Nikitenko , ma è stato rifiutato, quindi ho creato il mio perché sentivo che erano le informazioni mancanti quando ne avevo bisogno.
Emile Bergeron

Grazie per il tuo post! Non ricordo se sono stato io a rifiutare la tua modifica e perché.
Yaroslav Nikitenko

@YaroslavNikitenko Col senno di poi, era troppo grande per una modifica e migliore come risposta sotto forma di una nuova risposta.
Emile Bergeron

@EmileBergeron La domanda iniziale riguardava visioni generiche come la DetailViewclasse. Potresti spiegare come usarlo lì?
bartaelterman

3

Per django 3.0, questo è ciò che ha funzionato per me:

# 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'),
]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.