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 sé 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.