Vue basée sur la classe Django pour créer et mettre à jour
dire que je veux créer un Class Based View qui à la fois met à jour et crée un objet. D'un question précédente j'ai compris que je pouvais faire une des choses suivantes:
1) Utiliser 2 vues génériques CreateView
et UpdateView
qui, je pense, signifierait avoir deux URL pointant vers deux classes différentes.
2) Utiliser une vue par classe qui hérite de la base View
, ce qui, je pense, signifierait avoir deux URL pointant vers seulement 1 classe (j'ai créé qui hérite View
).
j'ai deux questions:
A) Quel est le meilleur?
b) ccbv.co.uk montre une base View
, mais je ne vois aucune méthode get, post etc documenté, est-ce correct?
5 réponses
Pourquoi devez-vous gérer à la fois créer et mettre à jour par une seule vue? Il est beaucoup plus simple d'avoir deux vues distinctes, chacune héritant de sa classe de vue générique respective. Ils peuvent partager la même forme et le même modèle si vous le souhaitez, et ils sont très probablement servis à partir D'URLs différentes, donc je ne vois pas ce que vous obtiendriez en le faisant dans une vue unique.
donc: utilisez deux vues, l'une héritant de CreateView
et l'autre de UpdateView
. Ils gèrent assez bien tout ce dont vous pourriez avoir besoin, tandis que la seconde approche vous exigerait de réinventer la roue vous-même. Si vous avez des cas où vous avez un code "housekeeping" commun qui est utilisé à la fois lors de la création ou de la mise à jour d'objets, l'option d'utiliser un mixin, ou vous pouvez peut-être créer votre propre vue qui couvre les deux cas d'utilisation, héritant à la fois de CreateView
et UpdateView
.
je suis tombé dans une situation où je voulais quelque chose comme ça. Voici ce que j'ai trouvé (notez que si vous essayez de l'utiliser comme une vue de mise à jour et qu'il ne peut pas trouver l'objet demandé, il se comportera comme une vue de création plutôt que de lancer un 404):
from django.views.generic.detail import SingleObjectTemplateResponseMixin
from django.views.generic.edit import ModelFormMixin, ProcessFormView
class CreateUpdateView(SingleObjectTemplateResponseMixin, ModelFormMixin,
ProcessFormView):
def get_object(self, queryset=None):
try:
return super(CreateUpdateView,self).get_object(queryset)
except AttributeError:
return None
def get(self, request, *args, **kwargs):
self.object = self.get_object()
return super(CreateUpdateView, self).get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
return super(CreateUpdateView, self).post(request, *args, **kwargs)
il s'avère que UpdateView
et CreateView
héritent exactement des mêmes classes et mixins. La seule différence réside dans les méthodes get/post. Voici comment ils sont définis dans la source de django (1.8.2):
class BaseCreateView(ModelFormMixin, ProcessFormView):
"""
Base view for creating an new object instance.
Using this base class requires subclassing to provide a response mixin.
"""
def get(self, request, *args, **kwargs):
self.object = None
return super(BaseCreateView, self).get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
self.object = None
return super(BaseCreateView, self).post(request, *args, **kwargs)
class CreateView(SingleObjectTemplateResponseMixin, BaseCreateView):
"""
View for creating a new object instance,
with a response rendered by template.
"""
template_name_suffix = '_form'
class BaseUpdateView(ModelFormMixin, ProcessFormView):
"""
Base view for updating an existing object.
Using this base class requires subclassing to provide a response mixin.
"""
def get(self, request, *args, **kwargs):
self.object = self.get_object()
return super(BaseUpdateView, self).get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
return super(BaseUpdateView, self).post(request, *args, **kwargs)
class UpdateView(SingleObjectTemplateResponseMixin, BaseUpdateView):
"""
View for updating an object,
with a response rendered by template.
"""
template_name_suffix = '_form'
comme vous pouvez le voir, les méthodes get et post de CreateView positionnent self.object = None
alors que le UpdateView
le positionne à self.get_object()
. Tout ce que j'ai fait c'est combiner ces deux dans ma méthode CreateUpdateView.get_object
qui tente d'appeler la classe de parent get_object
et retourne None
plutôt que de soulever une exception s'il n'y a pas d'objet.
pour servir une page 404 lorsqu'il est utilisé comme une vue de mise à jour, vous pourriez probablement remplacer as_view
et passez - lui un argument booléen update_only
. Si update_only
est True
et que la vue ne trouve pas l'objet, alors levez le 404.
comme suggéré par @scubabuddha j'ai rencontré une situation similaire et j'ai utilisé sa réponse modifiée comme @mario-orlandi suggéré dans son commentaire:
from django.views.generic import UpdateView
class CreateUpdateView(UpdateView):
def get_object(self, queryset=None):
try:
return super().get_object(queryset)
except AttributeError:
return None
j'ai utilisé Cette solution avec Django 1.11 mais je pense qu'elle peut fonctionner avec Django 2.0.
mise à Jour
je confirme que cette solution fonctionne avec Django 2.0.7.
pour partager le code entre votre UpdateView
et CreateView
, au lieu de créer une classe combinée, vous pouvez utiliser une superclasse commune comme mixin. De cette façon, il pourrait être plus facile de séparer les différentes préoccupations. Et-vous pouvez réutiliser beaucoup de code Django existant.
class BookFormView(PJAXContextMixin):
template_name = 'library/book_form.html'
form_class = BookForm
def form_valid(self, form):
form.instance.owner = self.request.user
return super().form_valid(form)
class Meta:
abstract = True
class BookCreateView(BookFormView, CreateView):
pass
class FormatUpdateView(BookFormView, UpdateView):
queryset = Book.objects
vous pouvez également utiliser Django Smartmin qui est inspiré de CBV de Django. Voici un exemple tiré de la documentation: https://smartmin.readthedocs.org/en/latest/quickstart.html