93 votes

Quand utiliser get, get_queryset, get_context_data dans Django?

J'ai appris récemment que vous devez remplacer la méthode get lorsque vous voulez faire quelque chose d'autre que ce que l'affichage par défaut n':

class ExampleView(generic.ListView):
    template_name = 'ppm/ppm.html'

    def get(self, request):
        manager = request.GET.get('manager', None)
        if manager:
            profiles_set = EmployeeProfile.objects.filter(manager=manager)
        else:
            profiles_set = EmployeeProfile.objects.all()
            context = {
                'profiles_set': profiles_set,
                'title': 'Employee Profiles'
            }

C'est assez simple, mais quand dois-je utiliser get_queryset ou get_context_data sur obtenir? Pour moi, il semble comme ils se sont contentés de faire la même chose, ou suis-je raté quelque chose? Puis-je les utiliser ensemble? C'est une source importante de confusion pour moi.

Donc je le répète: Dans quels cas puis-je utiliser obtenir plus de get_queryset ou get_context_data et vice versa?

178voto

Anonymous Points 7026

En effet, ils font des choses différentes.

get()

C'est une méthode de niveau supérieur, et il y en a une pour chaque verbe HTTP - get(), post(), patch(), etc. Vous serait de la remplacer quand vous voulez faire quelque chose avant qu'une demande est traitée par la vue, ou après. Mais ce n'est appelée que lorsque une vue de formulaire est chargé pour la première fois, non pas lorsque le formulaire est soumis. Exemple de base de la documentation. Par défaut, il va juste rendre la configuration du modèle et de retourner le code HTML.

class MyView(TemplateView):
    # ... other methods

    def get(self, *args, **kwargs):
        print('Processing GET request')
        resp = super().get(*args, **kwargs)
        print('Finished processing GET request')
        return resp

get_query_set()

Utilisée par ListViews - il détermine la liste des objets que vous souhaitez afficher. Par défaut, il va juste vous donner à tous pour le modèle que vous spécifiez. En substituant cette méthode, vous pouvez étendre ou de remplacer complètement cette logique. Documentation de Django sur le sujet.

class FilteredAuthorView(ListView):
    template_name = 'authors.html'
    model = Author

    def get_queryset(self):
        # original qs
        qs = super().get_queryset() 
        # filter by a variable captured from url, for example
        return qs.filter(name__startswith=self.kwargs.name)

get_context_data()

Cette méthode est utilisée pour remplir un dictionnaire à utiliser que le modèle de contexte. Par exemple, ListViews va peupler le résultat de l' get_queryset() comme author_list dans l'exemple ci-dessus. Vous serez probablement en substitution de cette méthode le plus souvent d'ajouter des éléments à afficher dans vos modèles.

def get_context_data(self, **kwargs):
    data = super().get_context_data(**kwargs)
    data['page_title'] = 'Authors'
    return data

Et puis dans votre modèle, vous pouvez faire référence à ces variables.

<h1>{{ page_title }}</h1>

<ul>
{% for author in author_list %}
    <li>{{ author.name }}</li>
{% endfor %}
</ul>

Maintenant pour répondre à votre question principale, la raison pour laquelle vous avez tant de nombreuses méthodes pour vous permettre de coller votre logique personnalisée avec précision de pin-point. Il permet, non seulement, votre code sera plus lisible et modulaire, mais aussi plus testable.

La documentation doit tout expliquer. Si pas encore assez, vous pouvez trouver les sources utiles. Vous verrez comment tout est mis en œuvre avec mixin qui ne sont possibles que parce que tout est compartimenté.

14voto

fips Points 2542

Regardons l'implémentation par défaut de du ListView get méthode:

https://github.com/django/django/blob/92053acbb9160862c3e743a99ed8ccff8d4f8fd6/django/views/generic/list.py#L158

class BaseListView(MultipleObjectMixin, View):
    """
    A base view for displaying a list of objects.
    """
    def get(self, request, *args, **kwargs):
        self.object_list = self.get_queryset()
        allow_empty = self.get_allow_empty()

        if not allow_empty:
            # When pagination is enabled and object_list is a queryset,
            # it's better to do a cheap query than to load the unpaginated
            # queryset in memory.
            if (self.get_paginate_by(self.object_list) is not None
                    and hasattr(self.object_list, 'exists')):
                is_empty = not self.object_list.exists()
            else:
                is_empty = len(self.object_list) == 0
            if is_empty:
                raise Http404(_("Empty list and '%(class_name)s.allow_empty' is False.")
                        % {'class_name': self.__class__.__name__})
        context = self.get_context_data()
        return self.render_to_response(context)

Vous remarquerez qu' get_queryset est appelée, dans la première ligne. Vous pouvez simplement remplacer que si vous voulez juste de retour de votre modèle queryset après l'application de certains, le filtrage de commande etc.

Vous n'avez pas besoin de remplacer l'ensemble de l' get méthode pour que, parce que vous allez être absent sur tout cela fonctionnalité à savoir la pagination, 404 chèques etc.

get_context_data fusionne la résultante de queryset ensemble avec les données de contexte comme une chaîne de requête de paramètres pour la pagination, etc.

Ce que je recommanderais serait de vérifier auprès de django reinhardt, de la source à chaque fois dans un certain temps et essayer de le comprendre un peu, de sorte que vous pouvez reconnaître la méthode la plus appropriée, vous pouvez remplacer/remplacer.

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