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?

25
demandé sur Community 2013-06-19 17:38:16

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 .

5
répondu Berislav Lopac 2015-05-21 17:18:38

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.

38
répondu scubabuddha 2016-03-02 20:41:20

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.

4
répondu Paolo Melchiorre 2018-07-13 08:41:08

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
1
répondu Risadinha 2016-07-24 09:59:58

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

0
répondu iMitwe 2015-10-06 07:31:27