简体   繁体   中英

Django inline formsets with Class-based view

I'm trying to do Django class-based CreateView inline formsets. I have a product model and a productImage model and productImage is inline everything looks fine but after i submit my product the images that are selected in formset will not save. Here is my code

models.py:

     class Product(models.Model):
        name=models.CharField(max_length=200, db_index=True),
        slug=models.SlugField(max_length=200, db_index=True, allow_unicode=True),
        description=models.TextField(blank=True),
        vector_column=SearchVectorField(null=True, editable=False),
        meta={"indexes": (GinIndex(fields=["vector_column"]),)}
        category = models.ForeignKey(Category, related_name='products', 
                   on_delete=models.CASCADE)
        price = models.DecimalField(max_digits=10, decimal_places=2)
        available = models.BooleanField(default=True)

        def get_absolute_url(self):
            return reverse('shop:product_detail', args=[self.id, self.slug])
        
     class ProductImage(models.Model):
        product = models.ForeignKey(Product, default=None, on_delete=models.CASCADE)
        image = models.ImageField(upload_to='products/%y/%m/%d')

        def __str__(self):
             return self.product.name

views.py

class ProductCreate(StaffAccessMixin, ProductFormValidMixin, ProductFieldsMixin,
                 CreateView):
model = Product

def get_context_data(self, **kwargs):
    context = super(ProductCreate, self).get_context_data(**kwargs)
    if self.request.POST:
        context['product_image_formset'] = ProductImageFormset(self.request.POST)
    else:
        context['product_image_formset'] = ProductImageFormset()
    return context


template_name = 'products/product-create-update.html'

ProductFormValidMixin:

class ProductFormValidMixin():
  def form_valid(self, form):
    context = self.get_context_data()
    product_image_formset = context['product_image_formset']
    if self.request.user.is_superuser:
        self.obj = form.save()
        if product_image_formset.is_valid():
            product_image_formset.instance = self.obj
            product_image_formset.save()
        return redirect('administration:product-update', pk=self.obj.pk)
    else:
        self.obj = form.save(commit=False)
        self.obj.available = False
    return super().form_valid(form)

ProductFieldsMixin:

class ProductFieldsMixin():
  def dispatch(self, request, *args, **kwargs):
    if request.user.is_superuser:
        self.fields = ["name",
                       "slug",
                       "description",
                       "category",
                       "price",
                       "available",
                       "image",
                       ]
    else:
        raise Http404
    return super().dispatch(request, *args, **kwargs)

forms.py:

from django.forms.models import inlineformset_factory
from .models import Product, ProductImage

ProductImageFormset = inlineformset_factory(Product, ProductImage, fields=('image',), 
extra=3)

Formset template:

<h5 class="text-info">Add Product Metas</h5>
 {{ product_image_formset.management_form|crispy }}

  {% for form in product_image_formset.forms %}
       <tr class="{% cycle 'row1' 'row2' %} formset_row-{{product_image_formset.prefix }}">
         {% for field in form.visible_fields %}
                <td>
                    {# Include the hidden fields in the form #}
                     {% if forloop.first %}
                           {% for hidden in form.hidden_fields %}
                                 {{ hidden }}
                           {% endfor %}
                     {% endif %}
                     {{ field.errors.as_ul }}
                     {{ field|as_crispy_field }}
               </td>
          {% endfor %}
     </tr>
  {% endfor %}

Everything is ok and my product form is saved after submit but the images i select in my form set won't save

Problem solved!

This code will work for other types of data but not for images and files to solve this problem get_context_data function should be like this:

def get_context_data(self, **kwargs):
    context = super(ProductCreate, self).get_context_data(**kwargs)
    if self.request.POST:
    context['product_image_formset']=ProductImageFormset(self.request.POST,
                                                         **self.request.FILES**)
    else:
        context['product_image_formset'] = ProductImageFormset()
    return context

In my first code self.request.FILES was missing:) and because of that images couldn't saved

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM