urls tutorial template example desde cero django django-class-based-views

tutorial - Vista basada en la clase de Django para crear y actualizar



httpresponse django example (5)

Digamos que quiero crear una Vista basada en clase que actualiza y crea un objeto. A partir de una pregunta anterior , resolví que podía hacer una de las siguientes cosas:

1) Utilice 2 vistas genéricas, CreateView y UpdateView lo que creo que significaría tener dos URL que apuntan a dos clases diferentes.

2) Utilice una vista basada en clase que herede la View base, lo que creo que significaría tener dos direcciones URL que apuntan a solo 1 clase (creé que hereda la View ).

Tengo dos preguntas:

a) ¿Cuál es mejor?

b) ccbv.co.uk muestra una View base, pero no veo ningún método documentado de obtención, publicación, etc. ¿es correcto?


¿Por qué necesita manejar tanto la creación como la actualización mediante una única vista? Es mucho más simple tener dos vistas separadas, cada una heredada de su clase de vista genérica respectiva. Si lo desean, pueden compartir el mismo formulario y la misma plantilla, y lo más probable es que se sirvan desde diferentes URL, por lo que no veo lo que obtendría al convertirlo en una vista única.

Entonces: use dos vistas, una CreateView de CreateView y la otra de UpdateView . Estos manejan casi todo lo que pueda necesitar, mientras que el segundo enfoque requeriría que reinventara la rueda usted mismo. Si los casos tienen un código de "mantenimiento" común que se usa al crear o actualizar objetos, la opción de usar un mixin, o quizás pueda crear su propia vista que cubra ambos casos de uso, heredando tanto de CreateView como de UpdateView .


Como sugirió @scubabuddha me encontré con una situación similar y utilicé su respuesta modificada como @ mario-orlandi sugirió en su comentario:

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

Utilicé esta solución con Django 1.11, pero creo que puede funcionar en Django 2.0.

Actualizar

Confirmo que esta solución funciona con Django 2.0.7.


Me encontré con una situación en la que quería algo como esto. Esto es lo que se me ocurrió (tenga en cuenta que si está intentando usarlo como una vista de actualización y no puede encontrar el objeto solicitado, se comportará como una vista de creación en lugar de lanzar 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)

Resulta que UpdateView y CreateView heredan de exactamente las mismas clases y combinaciones. La única diferencia está en los métodos get / post. Así es como se definen en la fuente 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''

Como puede ver, los métodos de creación y publicación de self.object = None establecen self.object = None mientras que UpdateView establece en self.get_object() . Todo lo que he hecho es combinar esos dos en mi método CreateUpdateView.get_object que intenta llamar a la clase primaria '' get_object '' y devuelve None lugar de generar una excepción si no hay ningún objeto.

Para servir a una página 404 cuando se utiliza como vista de actualización, probablemente podría anular as_view y pasarle un argumento booleano update_only . Si update_only es True y la vista no puede encontrar el objeto, suba el 404.


Para compartir código entre su UpdateView y CreateView , en lugar de crear una clase combinada, puede usar una superclase común como mixin. De esa manera, podría ser más fácil separar las diferentes preocupaciones. Y - puedes reutilizar una gran cantidad de código Django existente.

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