fix: improved UI
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.forms import modelform_factory
|
||||
from django.http import Http404, HttpResponse, HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404, render
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.views.generic import CreateView, DeleteView, DetailView, ListView, UpdateView, View
|
||||
|
||||
from backoffice.forms import ProductVariantForm
|
||||
from backoffice.forms import ProductInitialPriceForm, ProductVariantForm
|
||||
from backoffice.mixins import (
|
||||
BackofficeCRUDMixin,
|
||||
BackofficeHtmxMixin,
|
||||
@@ -63,8 +65,9 @@ class ProductCreateView(BackofficeCRUDMixin, BackofficeStyledFormMixin, CreateVi
|
||||
"""Página completa (no modal), con el mismo aspecto/widgets que la página de
|
||||
detalle (incluido el combobox de marca/categorías/etiquetas), pero todo en
|
||||
un único formulario: nada se envía al servidor hasta pulsar "Crear
|
||||
producto" (variantes, precios, imágenes y remesas sí requieren que el
|
||||
producto exista, así que se añaden después desde el detalle)."""
|
||||
producto". Las imágenes y el precio inicial se suben/crean en el mismo
|
||||
envío (variantes y remesas sí requieren que el producto ya exista, así que
|
||||
esas se añaden después desde el detalle)."""
|
||||
|
||||
model = Product
|
||||
permission_required = 'shop.add_product'
|
||||
@@ -72,9 +75,47 @@ class ProductCreateView(BackofficeCRUDMixin, BackofficeStyledFormMixin, CreateVi
|
||||
fields = ('sku', 'name', 'description', 'stock', 'brand', 'categories', 'tags', 'hidden', 'is_shipping_method')
|
||||
template_name = 'backoffice/products/product_create.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.setdefault('price_form', ProductInitialPriceForm())
|
||||
context.setdefault('image_errors', [])
|
||||
return context
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse_lazy('backoffice:product_detail', args=[self.object.pk])
|
||||
|
||||
def form_valid(self, form):
|
||||
price_form = ProductInitialPriceForm(self.request.POST)
|
||||
image_files = self.request.FILES.getlist('images')
|
||||
image_field = forms.ImageField()
|
||||
image_errors = []
|
||||
|
||||
for file in image_files:
|
||||
try:
|
||||
image_field.clean(file)
|
||||
except ValidationError as exc:
|
||||
image_errors.append(f'{file.name}: {", ".join(exc.messages)}')
|
||||
|
||||
if not price_form.is_valid() or image_errors:
|
||||
return self.render_to_response(
|
||||
self.get_context_data(form=form, price_form=price_form, image_errors=image_errors)
|
||||
)
|
||||
|
||||
self.object = form.save()
|
||||
|
||||
for file in image_files:
|
||||
ProductImage.objects.create(product=self.object, original=file)
|
||||
|
||||
if price_form.cleaned_data.get('price') is not None:
|
||||
ProductPrice.objects.create(
|
||||
product=self.object,
|
||||
price=price_form.cleaned_data['price'],
|
||||
tax=price_form.cleaned_data['tax'],
|
||||
current=True,
|
||||
)
|
||||
|
||||
return HttpResponseRedirect(self.get_success_url())
|
||||
|
||||
|
||||
class ProductDeleteView(BackofficeCRUDMixin, BackofficeModalDeleteMixin, DeleteView):
|
||||
model = Product
|
||||
@@ -121,6 +162,7 @@ class ProductDetailView(BackofficeCRUDMixin, DetailView):
|
||||
context['variants'] = self.object.variants.prefetch_related('attribute_values__attribute')
|
||||
context['batches'] = ProductBatch.objects.filter(product=self.object)
|
||||
context['images'] = self.object.images.all()
|
||||
context['prices'] = self.object.prices.select_related('tax')
|
||||
return context
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user