113 votes

Vue de Django basée sur les classes : Comment passer des paramètres supplémentaires à la méthode as_view ?

J'ai une vue personnalisée basée sur des classes

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

Je veux passer dans le paramètre slug (ou d'autres paramètres à la vue) comme ceci

MyView.as_view(slug='hello_world')

Dois-je modifier certaines méthodes pour pouvoir le faire ?

125voto

Daniel Eriksson Points 1724

Si votre urlconf ressemble à quelque chose comme ceci :

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

alors le slug sera disponible dans vos fonctions de vue (comme 'get_queryset') comme ceci :

self.kwargs['slug']

22 votes

Pour éviter une exception dans le cas où il s'agit d'un paramètre facultatif : utiliser self.kwargs.get('slug', None)

6 votes

Par curiosité, quand et où ce "self.kwargs" est-il renseigné ? Je cherche la fonction de la classe de base où il est défini.

0 votes

Sur github.com/django/django/blob/master/django/views/generic/ sur class View: def as_view(cls, **initkwargs): def view(request, *args, **kwargs):

105voto

omouse Points 2840

Chaque paramètre passé à la fonction as_view est une variable d'instance de la classe View. Cela signifie que pour ajouter slug en tant que paramètre, vous devez le créer comme une variable d'instance dans votre sous-classe :

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

Cela devrait faire MyView.as_view(slug='hello_world') travail.

Si vous faites passer les variables par des mots-clés, utilisez ce que M. Erikkson a suggéré : https://stackoverflow.com/a/11494666/9903

3 votes

Ne le faites jamais. import * . Modifié votre message.

1 votes

@holms pour éclairer les futurs lecteurs, PEP8 dit "Les importations avec caractères génériques (de <module> import ) devraient être évités". Should n'est pas aussi fort que must et c'est un exemple mais oui, définitivement, *should avoid les importations joker : python.org/dev/peps/pep-0008/#imports

0 votes

Rien n'est obligatoire nulle part, nous pouvons casser tout ce que nous voulons de la manière que nous voulons, mais pep8 est juste une recommandation de pratiques, et dans la communauté python, c'est une règle de base d'utiliser toutes ces pratiques autant que possible pour éviter d'autres problèmes. Mon linter est toujours vide quand je commite mon code :) quoi qu'il arrive.

19voto

Fush Points 61

Il est intéressant de noter que vous n'avez pas besoin de remplacer get_object() afin de rechercher un objet sur la base d'un slug passé en tant qu'arg de mot-clé - vous pouvez utiliser les attributs d'une balise 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 }}

(les deux slug_field y slug_url_kwarg par défaut 'slug' )

1 votes

Dois-je transformer ma réponse en une réponse wiki et y ajouter votre code ?

16voto

Vous pouvez passer des paramètres à partir de urls.py https://docs.djangoproject.com/en/1.7/topics/http/urls/#passing-extra-options-to-view-functions

Cela fonctionne également pour les vues génériques. Exemple :

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

Dans ce cas, les paramètres transmis à la vue ne doivent pas nécessairement être des variables d'instance de la classe View. En utilisant cette méthode, vous n'avez pas besoin de coder en dur le nom de la page par défaut dans le modèle YourView, mais vous pouvez simplement le passer comme paramètre depuis urlconf.

15voto

Aleck Landgraf Points 191

Si vous voulez ajouter un objet dans le contexte du modèle, vous pouvez remplacer l'option get_context_data et ajouter à son contexte. La demande fait également partie de self au cas où vous auriez besoin du demande.utilisateur .

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

0 votes

Qu'est-ce que MyObject ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X