Django表单-如何创建一个自定义表单模板与一个循环字段?



我正在创建一个使用Django模板引擎的web应用程序。说到这里,我的一个模型叫做Order。除其他模型外,Order模型还使用Food模型-这是ManyToMany关系。Food模型使用Category模型来定义食品类别(应该包含披萨,汉堡,葡萄酒,啤酒等食品类别)-这也是ManyToMany关系。

现在,我试图创建一个表单,其中用户将显示一个表单与分离的类别。到目前为止,Food模型中的所有食物都是一个接一个地显示出来的,一个在另一个的下面。它们没有在表单模板中分类。目前,它们默认显示为一个简单的食物列表,用户可以选择其中的任何一种。我希望用户可以选择他们想要的任何食物,但要分类显示(Pizza类别下的所有披萨,burgers类别下的所有汉堡,等等)。

我的models.py是这样的:

class Category(models.Model):
"""
Model for food categories
"""
name = models.CharField(max_length=100)
description = models.TextField(max_length=300)
date_created = models.DateTimeField(auto_now=True)
def __str__(self) -> str:
return f"{self.name} / {self.description[0 : 50]}..."
class Food(models.Model):
"""
Model for foods
"""
name = models.CharField(max_length=150)
description = models.TextField(max_length=400)
category = models.ManyToManyField(Category)
price = models.FloatField()
date_created = models.DateTimeField(auto_now=True)
def __str__(self) -> str:
return f"{self.name} / {', '.join(self.category.values_list('name', flat=True))} / {self.price} EUR"

class Order(models.Model):
"""
Model for orders
"""
order_statuses = [
("PR", "Status 1"),
("PS", "Status 2"),
]
customer_name = models.CharField(max_length=255)
customer_email = models.EmailField(blank=True)
ordered_foods = models.ManyToManyField(Food)
table = ForeignKey(Table, on_delete=models.CASCADE)
status = models.CharField(choices=order_statuses,
default="PR",
max_length=2)
total_price = models.FloatField(editable=False, default=0)
date_created = models.DateTimeField(auto_now=True)
date_completed = models.DateTimeField(blank=True,
default=datetime.datetime.strptime('2099-12-31 00:00:00', '%Y-%m-%d %H:%M:%S'))

def __str__(self) -> str:
return f"{self.id} / {self.customer_name} / {self.table.name} {self.table.number} / STATUS: {self.get_status_display()} / {self.total_price} EUR"

我的create_order.html(模板的形式,看起来像这样):

<form method="post">
{% csrf_token %}
{{ form | crispy }}
<button type="submit" class="btn btn-success">Submit</button>
</form>

我也使用crispy_forms,如果它有任何不同。

我愿意接受任何关于如何在表单模板中对食物进行分类的建议。

Thank you very much

要做到这一点,您需要做以下更改

  1. models.py中将related_name='foods'添加到Food模型中的类别中,如下所示:
category = models.ManyToManyField(Category, related_name='foods')

我们将在后面使用related_name

  1. forms.py中添加类别字段到您的订单中,这样您就会有这样的内容:
class OrderForm(forms.ModelForm):
class Meta:
model = Order
fields = [
'customer_name',
'customer_email',
'category',
'ordered_foods',
'ordered_foods',
'status',
]
# add this line and don't forget to add category to the field or use '__all__'
category = forms.ModelChoiceField(queryset=Category.objects.all())
  1. 现在我们将使用AJAX,你需要导入jQuery,将这段代码添加到你的js文件:
$(document).ready(function(){
var $category = $('#id_category');
function updateFoodChoices() {
var output = [];
output.push(`<option value="" disabled selected>Please select category</option>`)
$('#id_ordered_foods').html(output.join(''));
var selected = $category.val();
if (selected) {
$.ajax({
type: 'GET',
url: `/foodbycat/?cat_id=${selected}`,
success: function(response) {
const foods = response.data
$('#id_ordered_foods').empty()
var output = [];
foods.forEach(food => {
output.push(`<option value="${food.id}">${food.name} / ${food.price} EUR</option>`);
});
$('#id_ordered_foods').html(output.join(''));
},
error: function(error) {
console.log('error', error)
}
});
}
}
updateFoodChoices();
$category.change(updateFoodChoices);
});

这段代码将根据所选类别更新食物选择,为了让它工作,我们需要在views.py

中添加一些代码
  1. 将此功能添加到views.py:
def ajaxGetFoodByCategory(request):
cat_id = request.GET.get('cat_id')
if cat_id is not None:
category = get_object_or_404(Category, id=cat_id)
foods = category.foods.all()
# data = serializers.serialize('json', category.foods.all())
data = []
for food in foods:
item = {
'id': food.id,
'name': food.name,
'price': str(food.price),
}
data.append(item)
print(data)
return JsonResponse({'data': data})
else:
return HttpResponseBadRequest()

这段代码将获取所选类别的id并返回包含该类别的食物列表

  1. 好了,我们差不多完成了我们只需要将这一行添加到urls.py
path('foodbycat/', views.ajaxGetFoodByCategory, name='foodby-ctg'),

您需要检查添加到urls.py的路径是否与js代码中的url匹配

最新更新