it-swarm.com.de

Django Klassenbasierte Ansicht für Erstellen und Aktualisieren

Angenommen, ich möchte eine Klassenbasierte Ansicht erstellen, die sowohl Aktualisierungen als auch (erstellt ein Objekt erstellt. Aus einer vorherigen Frage habe ich herausgefunden, dass ich eines der folgenden Dinge tun könnte:

1) Verwenden Sie zwei generische Ansichten CreateView und UpdateView, die meiner Meinung nach zwei URLs bedeuten, die auf zwei verschiedene Klassen verweisen.

2) Verwenden Sie eine klassenbasierte Ansicht, die die Basis View erbt, was meiner Meinung nach bedeuten würde, dass zwei URLs auf nur eine Klasse verweisen (die ich erstellt habe und die View erbt).

Ich habe zwei Fragen:

a) Was ist besser?

b) ccbv.co.uk zeigt eine Basis View, aber ich sehe keine get, post etc-Methoden, ist das richtig?

25
GrantU

Warum müssen Sie sowohl das Erstellen als auch das Aktualisieren mit einer einzigen Ansicht durchführen? Es ist viel einfacher, zwei separate Ansichten zu haben, von denen jede von ihrer jeweiligen generischen Ansichtsklasse erbt. Sie können dasselbe Formular und dieselbe Vorlage freigeben, wenn Sie möchten, und sie werden höchstwahrscheinlich von verschiedenen URLs aus bereitgestellt. Ich kann also nicht erkennen, was Sie davon hätten, wenn Sie es in eine einzige Ansicht bringen.

Also: Verwenden Sie zwei Ansichten, eine von CreateView und die andere von UpdateView. Diese können so ziemlich alles, was Sie benötigen, handhaben, während Sie bei der zweiten Vorgehensweise das Rad selbst neu erfinden müssten. Wenn es Fälle gibt, in denen Sie einen allgemeinen "Housekeeping" -Code haben, der sowohl beim Erstellen als auch beim Aktualisieren von Objekten verwendet wird, können Sie entweder ein Mixin verwenden oder eine eigene Ansicht erstellen, die beide Anwendungsfälle abdeckt und sowohl von CreateView als auch von UpdateView erbt.

6
Berislav Lopac

Ich bin in eine Situation geraten, in der ich so etwas wollte. Folgendes habe ich mir ausgedacht (beachten Sie: Wenn Sie versuchen, es als Aktualisierungsansicht zu verwenden und das angeforderte Objekt nicht finden kann, verhält es sich wie eine Erstellungsansicht, anstatt eine 404 zu werfen):

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)

Es stellt sich heraus, dass UpdateView und CreateView von genau denselben Klassen und Mixins erben. Der einzige Unterschied besteht in den get/post-Methoden. So werden sie in der Django-Quelle (1.8.2) definiert:

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'

Wie Sie sehen, setzen die CreateView-Methoden get und post self.object = None, während UpdateView sie auf self.get_object() setzt. Alles, was ich getan habe, ist die Kombination dieser beiden in meiner CreateUpdateView.get_object-Methode, die versucht, den get_object der übergeordneten Klasse aufzurufen und None zurückzugeben, anstatt eine Ausnahme auszulösen, wenn kein Objekt vorhanden ist.

Wenn Sie eine 404-Seite als Aktualisierungsansicht bereitstellen möchten, können Sie as_view wahrscheinlich überschreiben und ein boolesches update_only-Argument übergeben. Wenn update_onlyTrue ist und die Ansicht das Objekt nicht finden kann, dann erhöhen Sie den Wert 404. 

38
scubabuddha

Wie von @scubabuddha vorgeschlagen, bin ich in eine ähnliche Situation geraten und habe seine Antwort modifiziert als @ mario-orlandi in seinem Kommentar vorgeschlagen:

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

Ich habe diese Lösung mit Django 1.11 verwendet, aber ich denke, dass es mit Django 2.0 funktionieren kann.

Aktualisieren

Ich bestätige, dass diese Lösung mit Django 2.0 und 2.1 funktioniert.

6

Um Code zwischen Ihrer UpdateView und CreateView zu teilen, anstatt eine kombinierte Klasse zu erstellen, können Sie eine gemeinsame Superklasse als Mixin verwenden. Auf diese Weise ist es möglicherweise einfacher, die verschiedenen Anliegen zu trennen. Und - Sie können viel vorhandenen Django-Code wiederverwenden.

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
Risadinha

Sie können auch Django Smartmin verwenden, das vom CBV of Django inspiriert ist. Hier ein Beispiel aus der Dokumentation: https://smartmin.readthedocs.org/de/latest/quickstart.html

0
iMitwe

Einfachste und im Grunde die beste Lösung aller link

class WorkerUpdate(UpdateView):
form_class = WorkerForm

def get_object(self, queryset=None):

    # get the existing object or created a new one
    obj, created = Worker.objects.get_or_create(mac=self.kwargs['mac'])

    return obj

und das ist es danke @chriskief

0
vladtyum