Working with forms and multiple models

Hi everyone !

I’m working on a “create_order” page and can’t really figure out how to get the user’s choices through the POST method (I mean how to work with the form exactly as I want a dropdown list) :

    <div id="create_order_box">
    <p id="create_order_box_title">Create order</p>
    <form id="create_order_form" action="" method="POST">
        {% csrf_token %}
        <label type="text">Customer : </label>
        <select id="" name="customer_list">
            {% for customer in customer_list %}
            <option value="{{ customer.customer_name }}">{{ customer.customer_name }}</option>
            {% endfor %}
        </select>

        <label type="text">Product : </label>
        <select id="" name="product_list">
            {% for product in product_list %}
            <option value="{{ product.product_name }}">{{ product.product_name }}</option>
            {% endfor %}
        </select>

        <label type="text">Quantity : </label>
        <input type="text">

        <input type="submit" value="Submit">
    </form>
</div>

Here is my view :

    def create_order(request):
    if request.method == "POST":
        form = OrderForm(request.POST)

        if form.is_valid():
            form.save()
            return redirect("/")
    else:
        form = OrderForm()

    template_name = "dashboard/create_order.html"
    context = {
        "form":form,
    }
    
    return render(request,template_name,context)

OrderForm definition :

    class OrderForm(ModelForm):
    class Meta:
        model = OrderModel
        fields = '__all__'

All my models :

    class ProductModel(models.Model):
    product_name = models.CharField(max_length=80, default="")
    product_description = models.CharField(max_length=180, default="")

    def __str__(self):
        return self.product_name

class OrderModel(models.Model):
    PENDING = "PE"
    OUT_FOR_DELIVERY = "OD"
    DELIVERED = "DE"

    ORDER_STATUS_CHOICES = [
        (PENDING,"Pending"),
        (OUT_FOR_DELIVERY,"Out for delivery"),
        (DELIVERED,"Delivered"),
    ]
    
    order_date = models.DateTimeField(auto_now_add=True)
    order_customer = models.ForeignKey(CustomerModel, related_name="order_customer", on_delete=models.CASCADE)
    order_product = models.ForeignKey(ProductModel, related_name="order_product", on_delete=models.CASCADE)
    order_status = models.CharField(max_length=2, choices=ORDER_STATUS_CHOICES, default=PENDING)

    def __str__(self):
        return self.order_status

class CustomerModel(models.Model):
    customer_first_name = models.CharField(max_length=40, default="")
    customer_surname = models.CharField(max_length=40, default="")

    def __str__(self):
        return self.customer_first_name

Thank you in advance for your help ! :slight_smile:

When you’re constructing your form using the form fields, e.g.

{{form.order_customer}}

and

{{form.order_product}}

it will populate the proper form fields after being posted.
The form.cleaned_data dict gives you access to the valid fields in the bound form.

Hi @KenWhitesell !

Thank you for your answer, indeed that was it, and also writing the form like this helped populate (Select comes from django.forms) :

    class OrderForm(ModelForm):
        class Meta:
            model = OrderModel
            fields = '__all__'
            widgets = {
                "order_customer": Select(choices=CustomerModel.objects.all()),
                "order_product": Select(choices=ProductModel.objects.all()),
            }