如何从Django模型获取下拉选项?订单页面产品选项空白排查
Django订单页面产品下拉选项空白问题排查与修复
问题描述
在Django项目中,订单页面的HTML无法渲染OrderModel关联的产品下拉选项,期望显示ProductModel的model_name字段,但当前下拉选项为空白。相关原代码如下:
原models.py代码
from cgi import print_form from email.policy import default from enum import unique from django.db import models # Create your models here. class ProductModel(models.Model): product_id = models.CharField(max_length=100,unique=True, default = '0') product_name = models.CharField(max_length=100, default=" ") model_name = models.CharField(max_length=100, default=" ") def __str__(self): return str(self.product_id) productchoice = (ProductModel.objects) class OrderModel(models.Model): order_id = models.AutoField(unique=True, primary_key=True) Customer_name = models.CharField(max_length=100) Father_name = models.CharField(max_length=100) Village = models.CharField(max_length=100) Tehsil = models.CharField(max_length=100) District = models.CharField(max_length=100) State = models.CharField(max_length=100) product = models.ForeignKey(ProductModel, on_delete = models.CASCADE, default= 0) def __str__(self): return str(self.order_id)
原views.py代码
from email import message_from_binary_file from django.shortcuts import render from .models import OrderModel, ProductModel from .forms import OrderForm, ProductForm from django.http import HttpResponse, HttpResponseRedirect from django.contrib import messages from django.contrib.messages import get_messages # Create your views here. def home(request): order_form = OrderForm if request.method == 'POST': order_form = OrderForm(request.POST) if order_form.is_valid(): order_form.save() messages.success(request, ('Your data was successfully added!')) return HttpResponseRedirect('/') else: messages.error(request, order_form.errors) orders = OrderModel.objects.all() context = {'order':orders, 'form':order_form} return render(request,'Orders/addorder.html',context) def product(request): product_form = ProductForm if request.method == 'POST': product_form = ProductForm(request.POST) if product_form.is_valid(): product_form.save() messages.success(request,"Your Products is successfully saved!") return HttpResponseRedirect('/') else: messages.error(request,product_form.errors) products = ProductModel.objects.all() context = {'product':products, 'form':product_form} return render(request,'Orders/addproduct.html',context)
原HTML模板代码
{% extends 'OMS/index.html' %} {% load static %} {% block title %} <title>Order</title> {% endblock %} {% block main %} <link rel="stylesheet" href="{% static 'addorder.css' %}"> <div class="container mp-3"> <h1>Create your Order</h1> <form action="" method="POST"> {% csrf_token %} <div> <label for="Customer Name" class="form-label">Customer Name: </label> {{ form.Customer_name }} </div> <div> <label for="Father Name" class="form-label">Father Name: </label> {{ form.Father_name }} </div> <div> <label for="Village" class="form-label">Village: </label> {{ form.Village }} </div> <div> <label for="Tehsil" class="form-label">Tehsil: </label> {{ form.Tehsil }} </div> <div> <label for="District" class="form-label">District: </label> {{ form.District }} </div> <div> <label for="State" class="form-label">State: </label> {{ form.State }} </div> <div> <select name="product" id="productselection"> {% for form in form %} <option value="{{ form.product.product_id }}">{{ form.product.model_name }}</option> {% endfor %} </select> </div> <button type="submit">Submit</button> {% if messages %} <ul class="messages"> {% for message in messages %} <li {% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li> {% endfor %} </ul> {% endif %} </form> </div> {% endblock %}
原forms.py代码
from django import forms from .models import OrderModel, ProductModel, productchoice class OrderForm(forms.ModelForm): Customer_name = forms.CharField(widget=forms.TextInput(attrs={ "class":"input" })) class Meta: model = OrderModel fields = "__all__" class ProductForm(forms.ModelForm): class Meta: model = ProductModel fields = "__all__"
问题排查
- 模板渲染逻辑错误:HTML中手动编写的
<select>循环的是form对象本身({% for form in form %}),会遍历表单字段而非产品数据,同时变量名冲突导致无法获取产品信息。 - 上下文未传递产品数据:视图
home函数未将ProductModel实例列表传入模板上下文,手动渲染下拉时无数据源。 ProductModel的__str__方法不符合需求:当前__str__返回product_id,即使使用Django表单自动生成下拉,显示的也是产品ID而非期望的model_name。- 外键默认值存在风险:
OrderModel的product字段设置default=0,若数据库中无ID为0的产品,会导致关联错误。
修复方案(推荐使用Django表单自动渲染)
步骤1:修改ProductModel的__str__方法
让__str__返回model_name,表单生成的下拉选项会直接显示产品型号:
# models.py class ProductModel(models.Model): product_id = models.CharField(max_length=100, unique=True, default='0') product_name = models.CharField(max_length=100, default=" ") model_name = models.CharField(max_length=100, default=" ") def __str__(self): return self.model_name # 修改为返回model_name # 移除无用的productchoice变量 class OrderModel(models.Model): order_id = models.AutoField(unique=True, primary_key=True) Customer_name = models.CharField(max_length=100) Father_name = models.CharField(max_length=100) Village = models.CharField(max_length=100) Tehsil = models.CharField(max_length=100) District = models.CharField(max_length=100) State = models.CharField(max_length=100) # 允许订单暂时不选产品,设置null=True, blank=True;否则移除default product = models.ForeignKey(ProductModel, on_delete=models.CASCADE, null=True, blank=True) def __str__(self): return str(self.order_id)
步骤2:简化HTML模板,使用表单自动渲染下拉
删除手动编写的<select>代码,直接使用Django表单生成的字段:
{% extends 'OMS/index.html' %} {% load static %} {% block title %} <title>Order</title> {% endblock %} {% block main %} <link rel="stylesheet" href="{% static 'addorder.css' %}"> <div class="container mp-3"> <h1>Create your Order</h1> <form action="" method="POST"> {% csrf_token %} <div> <label for="Customer Name" class="form-label">Customer Name: </label> {{ form.Customer_name }} </div> <div> <label for="Father Name" class="form-label">Father Name: </label> {{ form.Father_name }} </div> <div> <label for="Village" class="form-label">Village: </label> {{ form.Village }} </div> <div> <label for="Tehsil" class="form-label">Tehsil: </label> {{ form.Tehsil }} </div> <div> <label for="District" class="form-label">District: </label> {{ form.District }} </div> <div> <label for="State" class="form-label">State: </label> {{ form.State }} </div> <!-- 替换手动select为表单字段 --> <div> <label for="{{ form.product.id_for_label }}" class="form-label">产品型号: </label> {{ form.product }} </div> <button type="submit">Submit</button> {% if messages %} <ul class="messages"> {% for message in messages %} <li {% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li> {% endfor %} </ul> {% endif %} </form> </div> {% endblock %}
步骤3(可选):优化表单字段样式
如果需要给产品下拉添加样式,可在OrderForm中自定义widget:
# forms.py from django import forms from .models import OrderModel, ProductModel class OrderForm(forms.ModelForm): Customer_name = forms.CharField(widget=forms.TextInput(attrs={ "class":"input" })) # 自定义产品下拉的样式 product = forms.ModelChoiceField( queryset=ProductModel.objects.all(), widget=forms.Select(attrs={ "class": "input" }) ) class Meta: model = OrderModel fields = "__all__" class ProductForm(forms.ModelForm): class Meta: model = ProductModel fields = "__all__"
备选方案:手动渲染下拉(不推荐)
如果一定要手动编写<select>,需修改视图和模板:
修改视图传递产品数据
# views.py def home(request): order_form = OrderForm() # 实例化表单,原代码是类而非实例 if request.method == 'POST': order_form = OrderForm(request.POST) if order_form.is_valid(): order_form.save() messages.success(request, ('Your data was successfully added!')) return HttpResponseRedirect('/') else: messages.error(request, order_form.errors) orders = OrderModel.objects.all() # 添加产品列表到上下文 products = ProductModel.objects.all() context = {'order': orders, 'form': order_form, 'products': products} return render(request,'Orders/addorder.html',context)
修改模板循环产品列表
<!-- HTML模板中的select部分 --> <div> <label for="productselection" class="form-label">产品型号: </label> <select name="product" id="productselection"> {% for product in products %} <option value="{{ product.id }}">{{ product.model_name }}</option> {% endfor %} </select> </div>
内容的提问来源于stack exchange,提问作者Parvinder Mainn
相关产品推荐
相关产品推荐

