Vista basada en clases de Django: ¿Cómo paso parámetros adicionales al método as_view?


95

Tengo una vista personalizada basada en clases

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

Quiero pasar el parámetro slug (u otros parámetros a la vista) como este

MyView.as_view(slug='hello_world')

¿Necesito anular algún método para poder hacer esto?

Respuestas:


113

Si su urlconf se parece a esto:

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

entonces el slug estará disponible dentro de sus funciones de vista (como 'get_queryset') así:

self.kwargs['slug']

18
Para evitar una excepción en caso de que este sea un parámetro opcional: useself.kwargs.get('slug', None)
Risadinha

6
Solo por curiosidad, ¿cuándo / dónde está poblado este "self.kwargs"? Estoy buscando la función de clase base donde se establece esto.
binithb

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

Sin responder la pregunta.
Kireeti K

Este método ahora está obsoleto, ahora puede usarurl('<slug:slug>', MyView.as_view(), name='my_named_view')
Rahat Zaman

91

Cada parámetro que se pasa al as_viewmétodo es una variable de instancia de la clase View. Eso significa que para agregar slugcomo parámetro, debe crearlo como una variable de instancia en su subclase:

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

Eso debería MyView.as_view(slug='hello_world')funcionar.

Si está pasando las variables a través de palabras clave, use lo que sugirió el Sr. Erikkson: https://stackoverflow.com/a/11494666/9903


2
Nunca lo hagas import *. Editó su publicación.
holms

@holms para la ilustración de los futuros lectores, PEP8 dice " Deben evitarse las importaciones de comodines (desde <module> import )". Debería no es tan fuerte como debe y este es un ejemplo, pero sí, definitivamente * debería evitar las importaciones de comodines: python.org/dev/peps/pep-0008/#imports

Nada es obligatorio en ningún lugar, podemos romper cualquier cosa que queramos de la forma que queramos, pero pep8 es solo una recomendación de prácticas, y en la comunidad de Python es una regla general usar todas estas prácticas tanto como sea posible para evitar más problemas. Mi linter siempre está vacío cuando envío mi código :) pase lo que pase.
holms

¿Cuál es el valor de slug = 'hello_world' para una variable real?
Gonzalo Dambra

19

Vale la pena señalar que no necesita anular get_object()para buscar un objeto basado en un slug pasado como una palabra clave arg; puede usar los atributos de un SingleObjectMixin https://docs.djangoproject.com/en/1.5/ref/ vistas basadas en clases / 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 }}

(ambos slug_fieldy slug_url_kwargpredeterminado a 'slug')


1
¿Debería convertir mi respuesta en una respuesta wiki y agregarle su código?

15

Si desea agregar un objeto al contexto de la plantilla, puede anularlo get_context_datay agregarlo a su contexto. La solicitud también es parte de uno mismo en caso de que necesite 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

¿Qué es MyObject?
Rob Kwasowski

13

Puede pasar parámetros desde urls.py https://docs.djangoproject.com/en/1.7/topics/http/urls/#passing-extra-options-to-view-functions

Esto también funciona para vistas genéricas. Ejemplo:

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

En este caso, los parámetros pasados ​​a la vista no deben ser necesariamente variables de instancia de la clase Vista. Con este método, no necesita codificar el nombre de la página predeterminada en el modelo YourView, pero puede pasarlo como un parámetro de urlconf.


gracias, estuve buscando esto durante bastante tiempo!
Ilja

7

Según lo indicado por Yaroslav Nikitenko , si usted no desea codificar una nueva variable de instancia de la clase View, puede pasar opciones adicionales para ver las funciones de urls.pyla siguiente manera:

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

Solo quería agregar cómo usarlo desde la vista. Puede implementar uno de los siguientes métodos:

# 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
Quería editar esto en la respuesta de Yaroslav Nikitenko , pero fue rechazado, así que hice el mío porque sentí que era la información que faltaba cuando la necesitaba.
Emile Bergeron

¡Gracias por tu publicación! No recuerdo si fui yo quien rechazó tu edición y por qué.
Yaroslav Nikitenko

@YaroslavNikitenko En retrospectiva, era demasiado grande para una edición y mejor como respuesta en forma de una nueva respuesta.
Emile Bergeron

@EmileBergeron La pregunta inicial fue sobre vistas genéricas como la DetailViewclase. ¿Podrías explicar cómo se usa allí?
bartaelterman

3

Para django 3.0, esto es lo que funcionó para mí:

# 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'),
]
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.