how to show avaliable sizes of clothes on the form? Django

427 Views Asked by At

I'm developing online clothing store on Django. Now I faced the issue: I have a form which helps user to add to his cart some clothes. I need to show which sizes of this clothes are avaliable. To do this, I need to refer to the database. But how to do it from the form?

models.py:

from django.db import models
from django.urls import reverse
from multiselectfield import MultiSelectField

class Category(models.Model):
    name = models.CharField(max_length=200, db_index=True)
    slug = models.SlugField(max_length=200, db_index=True, unique=True)

    class Meta:
        ordering = ('name',)

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('shop:product_list_by_category',
                       args=[self.slug])

class Product(models.Model):
    category = models.ForeignKey(Category, related_name='products', on_delete=models.CASCADE)
    name = models.CharField(max_length=200, db_index=True)
    slug = models.SlugField(max_length=200, db_index=True)
    image = models.FileField(blank=True, upload_to=get_upload_path)

    SIZE_CHOICES = (('XXS', 'XXS'),
                    ('XS', 'XS'),
                    ('S', 'S'),
                    ('M', 'M'),
                    ('XL', 'XL'),
                    ('XXL', 'XXL'))

    sizes = MultiSelectField(choices=SIZE_CHOICES,
                             max_choices=6,
                             max_length=17)

    description = models.TextField(blank=True)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    stock = models.PositiveIntegerField()
    available = models.BooleanField(default=True)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ('name',)
        index_together = (('id', 'slug'),)

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('shop:product_detail',
                       args=[self.id, self.slug])

my form:

forms.py

from django import forms

PRODUCT_QUANTITY_CHOICES = [(i, str(i)) for i in range(1, 21)]

class CartAddProductForm(forms.Form):
    quantity = forms.TypedChoiceField(choices=PRODUCT_QUANTITY_CHOICES, coerce=int)
    update = forms.BooleanField(required=False, initial=False, widget=forms.HiddenInput)
    #  size = ??

the view which uses this form:

views.py

def product_detail(request: WSGIRequest, product_id: int, product_slug: str) -> HttpResponse:
    product = get_object_or_404(Product,
                                id=product_id,
                                slug=product_slug,
                                available=True)
    cart_product_form = CartAddProductForm()
    return render(request, 'shop/product/detail.html', {'product': product,
                                                        'cart_product_form': cart_product_form})

shop/product/detail.html:

{% extends "shop/base.html" %}
<head>
    <meta charset="UTF-8">
    <title>Detail</title>
</head>
<body>
{% block content %}
    <br>
    <b>{{ product.name }} </b> <br>
    <i>{{ product.description }} </i> <br>
    {{ product.price }} <br>
    <img src="{{ product.image.url }}" width="300" height="500"> <br>
    Available sizes: <br>
    {{ product.sizes }}<br>
    <form action="{% url "cart:add_to_cart" product.id %}" method="post">
        {{ cart_product_form }}
        {% csrf_token %}
        <input type="submit" value="Add to cart">
    </form>
{% endblock %}
</body>

I tried to create a function which gets avaliable sizes and send to the form:

forms.py

def get_sizes(product: Product):
    return product.sizes

But to do this I need to refer to the Product from the form, I don't know how to do it.

2

There are 2 best solutions below

0
On BEST ANSWER

my solution is:

forms.py

from django import forms
from django.forms import ModelForm
from shop.models import Product


class CartAddProductForm(ModelForm):
    class Meta:
        model = Product
        fields = ['sizes']

    def __init__(self, pk, *args, **kwargs):
        super(CartAddProductForm, self).__init__(*args, **kwargs)
        sizes = tuple(Product.objects.get(pk=pk).sizes)
        sizes_list = []
        for item in sizes:
            sizes_list.append((item, item))
        self.fields['sizes'] = forms.ChoiceField(choices=sizes_list)

when I create the form, I pass the pk:

views.py

product = get_object_or_404(Product,
                            id=product_id,
                            slug=product_slug,
                            available=True)
pk = product.pk
cart_product_form = CartAddProductForm(instance=product, pk=pk)
0
On

How about dividing each clothes by size(with quantity)? Clothes with different size can be treated as different product.

product

ID name image description price ...
1 jean a.jpg good jean 12345 ...

size

ID product_id size quantity ...
1 1 xxxl 12345 ...
2 1 xxl 1234 ...
3 1 xl 123 ...

If quantity is greater than 0, that size of clothes is available.