SabujXi/SKFCMS

Single Dropdown Selected (Brand) Problem (Product edit/update)

DTSREPO opened this issue · 5 comments

Everything fine but when I try to open product form from product list page, Brand not selected.
Template : backend/prod_form.html
Views : backend/product_view.py
I know it's my problem :(

You are creating brands variable in class level. So, that is like creating a static variable where you need to create instance variables. We discussed about this issue a whole day with examples including small discussion in other days. Your code is:

class CrudProduct(View):
    template = 'ecom_app/backend/prod_form.html'
    title = 'Product Form'
    heading = 'Product Form'
    cats = models.Category.objects.all()
    brands = models.Brands.objects.all()
    suppliers = models.Suppliers.objects.all()

    def get(self, request, prod_id=None):

        if prod_id:
            prod_id = int(prod_id)
            prod = models.Product.objects.get(pk=prod_id)
            context = {'prod': prod, 'cats': self.cats, 'brands': self.brands, 'suppliers': self.suppliers,
                       'title': self.title, 'heading': self.heading}
            return render(request, self.template, context)
        else:
            context = {'cats': self.cats, 'brands': self.brands, 'suppliers': self.suppliers, 'title': self.title,
                       'heading': self.heading}
            return render(request, self.template, context)

Look at this part:

class CrudProduct(View):
    template = 'ecom_app/backend/prod_form.html'
    title = 'Product Form'
    heading = 'Product Form'
    cats = models.Category.objects.all()
    brands = models.Brands.objects.all()
    suppliers = models.Suppliers.objects.all()

I told you guys that class level variables are evaluated only once when the interpreter or the system or the module or the class (depending on factors that I discussed with examples) gets loaded. After adding some brands restart the development server with CTRL+C or CTRL+BREAK) and you will see your desired result (brands are in the multiple selection on the product entry form).

So, you can refactor it like below:

class CrudProduct(View):
    template = 'ecom_app/backend/prod_form.html'
    title = 'Product Form'
    heading = 'Product Form'

    def get(self, request, prod_id=None):
        cats = models.Category.objects.all()
        brands = models.Brands.objects.all()
        suppliers = models.Suppliers.objects.all()
        # and the rest goes here

Do the same for post() too.

But if you want to put them in one place then create the __init__ method in the class.

class CrudProduct(View):
    template = 'ecom_app/backend/prod_form.html'
    title = 'Product Form'
    heading = 'Product Form'
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.cats = models.Category.objects.all()
        self.brands = models.Brands.objects.all()
        self.suppliers = models.Suppliers.objects.all()
        # and the rest goes here        
    def get(self, request, prod_id=None):
        # Live in peace here
        ...    

But the later way is not recommended. What if you need a filter with the query inside post or in a later version. Keep your code DRY, but don't be lazy!

@kamruljpi you also take a look at the matter and do not make the same mistake.

To err is human but to avoid such mistakes keep practicing. Keep calm and code with Python. Good luck.

@rubelnl @kamruljpi - I told you to refactor the code, give better reasonable names and append a View at the end of view classes. Change CrudProduct to what we discussed about good naming for scalable projects. Refactor other parts too if there are bad things lurking around.

Edited

class CrudProduct(View):
    template = 'ecom_app/backend/prod_form.html'
    title = 'Product Form'
    heading = 'Product Form'

    def get(self, request, prod_id=None):
        cats = models.Category.objects.all()
        brands = models.Brands.objects.all()
        suppliers = models.Suppliers.objects.all()
        if prod_id:
            prod_id = int(prod_id)
            prod = models.Product.objects.get(pk=prod_id)
            context = {'prod': prod, 'cats': cats, 'brands': brands, 'suppliers': suppliers,
                       'title': self.title, 'heading': self.heading}
            return render(request, self.template, context)
        else:
            context = {'cats': cats, 'brands': brands, 'suppliers': suppliers, 'title': self.title,
                       'heading': self.heading}
            return render(request, self.template, context)

Template ...

            <select name="brand" class="form-control">
                <option value="">--- Select Brand ---</option>
                {% with product_brands=prod.brands.all %}

                    {% for brand in brands %}
                        <option value="{{ brand.id }}"
                        {% for b in product_brands %}
                           {% if b.id == brand.id %}
                                selected="selected"
                           {% endif %}
                        {% endfor %}
                        >{{brand.name}}</option>
                    {% endfor %}

                {% endwith %}
            </select>

Not working ....

brand-prob

Look at the screenshot, it's working on my machine. Check again!

Let me know if I have missed any other part of your question.

Actually it's not my issue,
I mean when open product form from product list page for update or edit product there not selected my previous saved 'Brands Name',
Like first time i was saved product A, Brand B1
and 2nd times i need to edit this same product and change Brand B1 to Brand B2 but B2 should be selected.
@SabujXi