0

I'm Working on a project and i'm trying to make a product variation,

I have a Product, a Color Variation (FK=Product) and a Size Variation (FK=Color Variation)

I'm using inline formsets to acomplished that, but when i save more then one Color Variation, i get error saying that get() returned 2 objects.

On my CreateView form_valid, first i save the product, then i loop into the variants and inside this loop i made another loop to save the sizes.

So for example, if i have Color Red, it will save, then loop to all the sizes that belong to color red and save, and after will check for another Color variation.But this only works when i have only 1 color variation

How can i get the fk of the variation that is beeing looped and pass to the size ?

Here are my CreateView:

def get_context_data(self, **kwargs):
        ctx = super(ProductCreate, self).get_context_data(**kwargs)
        if self.request.POST:
            ctx['variants'] = VariantFormSet(self.request.POST or None, self.request.FILES or None, prefix='variants')
            ctx['sizes']    = SizeFormSet(self.request.POST or None, self.request.FILES or None, prefix='sizes')
        else: 
            ctx['variants'] = VariantFormSet(prefix='variants')
            ctx['sizes'] = SizeFormSet(prefix='sizes')
        return ctx

def form_valid(self, form):
        form.instance.vendor          = get_vendor(self.request)
        form.instance.product_slug    = slugify(form.instance.product_name)
        
        context         = self.get_context_data()
        variants        = context['variants']
        sizes           = context['sizes']
        with transaction.atomic():
            self.object = form.save()
            if variants.is_valid():
                for variant in variants:
                    variant.instance.product = self.object                
                    variant.save()
                    
                    if sizes.is_valid():
                        for size in sizes:
                            size.instance.product = Variant.objects.get(product=self.object)
                            size.save()
            
                
                return redirect('product_list')

Models.py

class Product(models.Model):
    vendor                      = models.ForeignKey(UserVendor, on_delete=models.CASCADE)
    category                    = models.ForeignKey(Category, on_delete=models.CASCADE)
    product_name                = models.CharField(max_length=255, unique=True)

class Variant(models.Model):
    product                     = models.ForeignKey(Product, on_delete=models.CASCADE)
    product_color               = models.CharField(max_length=25)
    product_color_code          = models.CharField(max_length=10, blank=True , null=True)
    product_price               = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
    product_stock               = models.IntegerField(blank=True, null=True)

class Size(models.Model):
    product                     = models.ForeignKey(Variant, on_delete=models.CASCADE)
    size_name                   = models.CharField(max_length=20, blank=True, null=True)
    size_stock                  = models.IntegerField(blank=True, null=True)
    size_price                  = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)

Forms.py

class ProductForm(forms.ModelForm):
    product_name                  = forms.CharField(widget=forms.TextInput(attrs={'class':'form__input'}))
    product_description           = forms.CharField(widget=forms.Textarea(attrs={'class':'form__input'}))
    class Meta:
        model = Product
        fields = {'product_name','product_description','category','is_available'}
       
class SizeForm(forms.ModelForm):
    class Meta:
        model = Size
        fields = '__all__'

class VariantForm(forms.ModelForm):    
    class Meta:
        model = Variant
        fields = '__all__'

VariantFormSet = inlineformset_factory(
    Product, Variant, form = VariantForm,
    extra=1, can_delete=True, can_delete_extra=True
)

SizeFormSet = inlineformset_factory(
    Variant, Size, form = SizeForm,
    extra=1, can_delete=True, can_delete_extra=True
)

I already try to check for nested inline, and django-extra-views, but i couldnt make it work with dynamic add from jquery

0 Answers0