stelity
stelity

Reputation: 41

django model formset factory how to write {{ form.field }}

So for forms, if you have quantity = IntegerField() in forms.py, then in the html file you can write {{ form.quantity }} to get the input for the quantity. How can do you the samething for modelformset_factory?

I've created a formset to ask the user for the item name and quantity. The item name is given by the loop. I need to move the modelformset factory inside the loop for each iteration, but I don't know how

#views.py
    #for showing items
    if (Items.objects.filter(item_category="Produce").exists()):
        produce = Items.objects.filter(item_category="Produce", show=True, quantity__gte=1)
    if (Items.objects.filter(item_category="Grains").exists()):
        grains = Items.objects.filter(item_category="Grains", show=True, quantity__gte=1)
    if (Items.objects.filter(item_category="Protein/Dairy").exists()):
        protein_dairy = Items.objects.filter(item_category="Protein/Dairy", show=True, quantity__gte=1)
    if (Items.objects.filter(item_category="extras").exists()):
        extras = Items.objects.filter(item_category="extra items", show=True, quantity__gte=1)

    
    #playing with formset
    form_extras = Items.objects.filter(show=True).count()
    formset = modelformset_factory(Cart, form=CustomerOrderForm,extra=form_extras)
    form = formset(queryset=Items.objects.none())
    if request.method == 'POST':
        form = formset(request.POST)
        #work on this
        if form.is_valid():
            print("is valid")
            form = formset(request.POST)
            instances = form.save(commit=False)
            for instance in instances:
                #item previously in cart
                if (Cart.objects.filter(username=request.user, item_name=form.cleaned_data.get('item_name')).exists()):
                    cart_instance = Cart.objects.get(username=request.user, item_name=form.cleaned_data.get('item_name'))
                    cart_instance.quantity = cart_instance.quantity + form.cleaned_data.get('quantity')
                    cart_instance.save()
                else:
                    #item never in cart, create new instance
                    item_instance = Items.objects.get(item_name=form.cleaned_data.get('item_name'))

                    Cart.objects.create(username=request.user, item_name=form.cleaned_data.get('item_name'), weight=item_instance.weight, quantity=form.cleaned_data.get('quantity'), description=item_instance.description, image=item_instance.image, price=item_instance.price, storage_type=item_instance.storage_type, item_category=item_instance.item_category, limit=item_instance.limit,)
        
            timestamp = datetime.date.today()
            messages.success(request,"Sucessfully added your items to your cart! " + str(timestamp))
            return redirect('/')
        else:
            print("form not valid for cart")
            form = formset()

    user_produce_points = request.user.profile.produce_points
    user_grain_points = request.user.profile.grain_points
    user_protein_dairy_points = request.user.profile.protein_dairy_points
    user_extras_points = request.user.profile.extra_items_points

Home.html:

#home.html
<form method="POST">
        {% csrf_token %}
        {{ form.management_form }}
        {{form.as_p}} 
        <div class="row">    

          {% for item in produce %}
            <div class="card" style="width: 18rem;">

                <img src="/media/{{ item.image }}" class="card-img-top" alt="...">

                <div class="card-body">
                    <h5 class="card-title text-center">
                        <b>{% if item.storage_type == "Frozen" %}
                              Frozen 
                            {% endif %}
                        {{ item.item_name }} ({{ item.weight }} oz)</b></h5>

                    <h6 class ="card-title text-center" style="color:green;font-size: 16px;"><b>{{ item.price }} Produce 
                      {% if item.price < 2 %}
                      Point
                      {% else %}
                      Points
                      {% endif %}

                    </b></h6>
                    
                    <p class="card-text">{{ item.description }}</p>
                    <br><br>

                
                      <div class="input-quantity">
                      
                        <input type="hidden" name="form-{{forloop.counter}}-item_name" value="{{ item.item_name }}">
                        {{form.quantity}}
                        {{form.item_name}}
                        {{form.field}}

                        Quantity: <input style="max-width:3em;" type="number" name="form-{{forloop.counter}}-quantity" pattern="[0-9]{3}" min="0" max="{{ item.limit }}">
            
                      </div>

                    
                </div>
            </div>
            {% endfor %}
            <br>

            <button type="submit" style="height:38px;" class="btn btn-primary btn-lg sharp" type="button">Add to Cart</button>
              </form>

Upvotes: 0

Views: 613

Answers (1)

Django Docs always has a nice example, it always helps me.

You sadly didn't post (I'm assuming you didn't) the rest of the view function so I can only guess that form in the template refers to the formset created in the view and that is gets passed. And if it does, you would need to first create the for-loop before accessing it in name="form-{{forloop.counter}}-item_name". You could create it like this:

{% for form_line in form %}
    <!--form_line rendering you have-->
    <p>Form #{{ forloop.counter }}</p>
    {{ form_line.quantity }}
    {{ form_line.item_name }}
    {{ form_line.field }}
{% endfor %}

In your template you also have the produce variable. I am unsure what that refers to, again, maybe because I can't see the whole view function.

Upvotes: 1

Related Questions