Django combine DetailView et FormView
J'ai une vision où j'ai besoin d'afficher des informations sur un certain modèle de l'instance j'ai donc utiliser un DetailView
. J'ai aussi besoin de ce même point de vue pour traiter une forme régulière (pas un modèle de formulaire), à la fois de l'affichage de la forme sur GET
et de le valider sur POST
. Pour ce faire, je suis en train d'utiliser un FormView
cependant, la combinaison de deux clases ne fonctionne pas:
class FooView(FormView, DetailView):
# configs here
Dans GET
(pour des raisons de simplicité de la question, je ne montre que le problème avec GET
depuis POST
a un autre problème), il ne fonctionne pas parce que la forme n'est jamais ajouté au contexte. La raison a à voir avec la méthode de résolution de l'ordre pour la classe:
>>> inspect.getmro(FooView)
(FooView,
django.views.generic.edit.FormView,
django.views.generic.detail.DetailView,
django.views.generic.detail.SingleObjectTemplateResponseMixin,
django.views.generic.base.TemplateResponseMixin,
django.views.generic.edit.BaseFormView,
django.views.generic.edit.FormMixin,
django.views.generic.detail.BaseDetailView,
django.views.generic.detail.SingleObjectMixin,
django.views.generic.base.ContextMixin,
django.views.generic.edit.ProcessFormView,
django.views.generic.base.View,
object)
Dans la demande, Django a pour obtenir la forme et l'ajouter au contexte. Qui se passe dans ProcessFormView.get
:
def get(self, request, *args, **kwargs):
"""
Handles GET requests and instantiates a blank version of the form.
"""
form_class = self.get_form_class()
form = self.get_form(form_class)
return self.render_to_response(self.get_context_data(form=form))
Cependant le premier de la classe avec la MRE qui a get
défini est BaseDetailView
:
def get(self, request, *args, **kwargs):
self.object = self.get_object()
context = self.get_context_data(object=self.object)
return self.render_to_response(context)
Comme vous pouvez le voir le BaseDetailView.get
n'appelle jamais super
d'où le ProcessFormView.get
ne sera jamais appelé d'où la forme ne sera pas ajouté au contexte. Ceci peut être résolu par la création d'un mixin point de vue où toutes ces nuances pour GET
et POST
peuvent être pris en charge, cependant je ne me sens pas c'est une solution propre.
Ma question: est-il possible d'accomplir ce que je veux avec Django par défaut de CBV mise en œuvre sans créer mixin?
source d'informationauteur miki725
Vous devez vous connecter pour publier un commentaire.
Une solution serait d'utiliser mixin, comme par limelights' commentaire ci-dessus.
Une autre approche est d'avoir deux points de vue distincts, l'un pour un
DetailView
et de l'autre unFormView
. Ensuite, le modèle de l'ancien, d'afficher le même formulaire que vous utilisez dans le dernier, sauf que vous ne pouvez pas laisser laaction
attribut vide -- au lieu de cela, mettre l'url de laFormView
. Quelque chose le long des lignes de ce (veuillez méfiez-vous de toutes les erreurs que j'écris ceci sans aucun test):Dans
views.py
:Dans
my_detail_view.html
:Dans
urls.py
:Noter que le
require_POST
décorateur est facultatif, dans le cas que vous ne voulez pas leMyFormView
pour être accessible par lesGET
et voulez seulement être traitées que lorsque le formulaire est soumis.Django a aussi une assez longue de la documentation à propos de ce problème.
https://docs.djangoproject.com/en/1.8/topics/class-based-views/mixins/#using-formmixin-with-detailview
Ils conseillent d'en faire 2 points de vue différents, et ont la vue de détails, reportez-vous à la vue de formulaire sur le post.
Je suis en train de voir si ce hack peut fonctionner:
Dans Django Par Exemple de lightbird, ils sont à l'aide d'une bibliothèque, MCBV, mélanger générique vues:
Vous pouvez suivre les explications ici: aide-fonctions
Et de l'utiliser pour mélanger FormView et la fenêtre detravail, ou que ce soit
Code: MCBV
En utilisant FormMixin
views.py
forms.py
urls.py
modèle
J'ai effectué ma solution à l'aide ModelForms et quelque chose comme ceci:
Sur la méthode get_context_data de ma fenêtre detravail j'ai fait:
Et mon FormView était comme: