如何在 views.py 中呈现与对象 ID 相关的所有数据
How to render all data related to object id in views.py
我正在尝试为餐厅创建一个 Web 应用程序以显示可用的不同菜单,早餐、午餐、晚上等。我已经为菜单、菜单类别和菜单项创建了模型。我有一个 menu.html 页面,其中显示了可用于查看 image of menu list on site 的菜单。当用户单击他们希望查看的菜单时,我希望发生的是 menu_detail 页面加载并填充该特定菜单所需的类别和项目。当前单击时,它将根据 id 加载正确的菜单,但随后仅加载具有相同 id 的单个类别,而不是与该菜单相关的所有类别,并且不会呈现任何项目
models.py
from django.db import models
"""
A Menu represents a collection of categories of food items. For example,
a restaurant may have a Lunch menu, and a Dinner menu.
"""
class Menu(models.Model):
name = models.CharField(max_length=246, unique=True,)
slug = models.SlugField(max_length=24, unique=True, help_text='The slug is the URL friendly version of the menu name, so that this can be accessed at a URL like mysite.com/menus/dinner/.')
additional_text = models.CharField(max_length=128, null=True, blank=True, help_text='Any additional text that the menu might need, i.e. Served between 11:00am and 4:00pm.')
order = models.PositiveSmallIntegerField(default=0, help_text='The order of the menu determines where this menu appears alongside other menus.')
class Meta:
verbose_name = 'menu name'
def __str__(self):
return self.name
"""
A Menu Category represents a grouping of items within a specific Menu.
An example of a Menu Category would be Appetizers, or Pasta.
"""
class MenuCategory(models.Model):
menu = models.ForeignKey(Menu, null=True, help_text='The menus that this category belongs to, i.e. \'Lunch\'.', on_delete=models.SET_NULL)
name = models.CharField(max_length=32, verbose_name='menu category name')
additional_text = models.CharField(max_length=128, null=True, blank=True, help_text='The additional text is any bit of related information to go along with a menu category, i.e. the \'Pasta\' category might have details that say \'All entrees come with salad and bread\'.')
order = models.IntegerField(default=0, help_text='The order is the order that this category should appear in when rendered on the templates.')
class Meta:
verbose_name = 'menu category'
verbose_name_plural = 'menu categories'
def __str__(self):
return self.name
"""
A Menu Item is an item of food that the restaurant makes. A Menu Item can
belong to multiple Menu Categories to facilitate menus that have the same item
across multiple menus.
"""
class MenuItem(models.Model):
CLASSIFICATION_CHOICES = (
('neither', 'Neither'),
('vegan', 'Vegan'),
('vegetarian', 'Vegetarian'),
)
name = models.CharField(max_length=48, help_text='Name of the item on the menu.')
menu = models.ForeignKey(Menu, null=True, blank=True, help_text='The menus that this category belongs to, i.e. \'Lunch\'.', on_delete=models.SET_NULL)
description = models.CharField(max_length=256, null=True, blank=True, help_text='The description is a simple text description of the menu item.')
category = models.ManyToManyField(MenuCategory, blank=True, verbose_name='menu category', help_text='Category is the menu category that this menu item belongs to, i.e. \'Appetizers\'.')
order = models.IntegerField(default=0, verbose_name='order', help_text='The order is to specify the order in which items show up on the menu.')
price = models.DecimalField(max_digits=6, decimal_places=2, help_text='The price is the cost of the item.')
classification = models.CharField(max_length=10, choices=CLASSIFICATION_CHOICES, default=0, verbose_name='classification', help_text='Select if this item classifies as Vegetarian, Vegan, or Neither.')
spicy = models.BooleanField(default=False, verbose_name='spicy?', help_text='Is this item spicy?')
contains_peanuts = models.BooleanField(default=True, verbose_name='contain peanuts?', help_text='Does this item contain peanuts?')
gluten_free = models.BooleanField(default=False, verbose_name='gluten free?', help_text='Is this item Gluten Free?')
def menu_name(self):
return ",".join([str(p) for p in self.category.all()])
class Meta:
verbose_name = 'menu item'
verbose_name_plural = 'menu items'
verbose_name = 'menu name'
def __str__(self):
return self.name
views.py
from django.shortcuts import render, redirect, reverse, get_object_or_404
from django.views.generic import ListView
from .models import Menu, MenuCategory, MenuItem
# Create your views here.
def listMenus(request):
menu = Menu.objects.all()
context = {
'menu': menu,
}
return render(request, 'menu/menu.html', context)
def get_menu_detail(request, menu_id):
""" A view to show individual product details """
detail = get_object_or_404(Menu, id=menu_id)
menuField = MenuCategory.objects.filter(id=menu_id)
getItem = MenuItem.objects.all()
context = {
'detail': detail,
'menuField': menuField,
'getItem': getItem
}
return render(request, 'menu/menu_detail.html', context)
我仍在研究 python 和框架,所以请原谅我的愚蠢,但如果有人能够指出我正确的方向,我将不胜感激。
要获取属于菜单的类别和项目,您可以这样做:
menuField = MenuCategory.objects.filter(menu=detail) # detail is an instance of Menu
getItem = MenuItem.objects.filter(menu=detail)
此外,由于 detail
是菜单的实例,您可以像这样使用向后查找管理器:
menuField = detail.menucategory_set.all()
getItem = detail.menuitem_set.all()
您可以使用ForeignKey
中的related_name
参数更改反向查找管理器名称,默认情况下它将是小写模型的名称加上_set
。
-已编辑-
在您的特定情况下,首先您要显示属于某个菜单的所有菜单类别,然后列出属于每个类别且也属于该菜单的菜单项,为此您可以执行以下操作:
查看:
from django.db.models import Prefetch
...
def get_menu_detail(request, menu_id):
menu = get_object_or_404(Menu, id=menu_id)
categories = (
MenuCategory.objects.prefetch_related(
Prefetch(
"menuitem_set",
queryset=MenuItem.objects.filter(
menu=menu
), # prefetch only items that belong to the menu
)
)
.filter(menuitem__menu=menu) # categories with items belong to the menu
.distinct()
)
context = {
"menu": menu,
"categories": categories,
}
return render(request, "menu/menu_detail.html", context)
然后,您可以在模板中包含如下内容:
<h1>{{ menu.name }}</h1>
{% for category in categories %}
<h2>{{ category.name }}</h2>
<ul>
{% for menu_item in category.menuitem_set.all %}
<li>{{ menu_item.name }}</li>
{% endfor %}
</ul>
{% endfor %}
我正在尝试为餐厅创建一个 Web 应用程序以显示可用的不同菜单,早餐、午餐、晚上等。我已经为菜单、菜单类别和菜单项创建了模型。我有一个 menu.html 页面,其中显示了可用于查看 image of menu list on site 的菜单。当用户单击他们希望查看的菜单时,我希望发生的是 menu_detail 页面加载并填充该特定菜单所需的类别和项目。当前单击时,它将根据 id 加载正确的菜单,但随后仅加载具有相同 id 的单个类别,而不是与该菜单相关的所有类别,并且不会呈现任何项目
models.py
from django.db import models
"""
A Menu represents a collection of categories of food items. For example,
a restaurant may have a Lunch menu, and a Dinner menu.
"""
class Menu(models.Model):
name = models.CharField(max_length=246, unique=True,)
slug = models.SlugField(max_length=24, unique=True, help_text='The slug is the URL friendly version of the menu name, so that this can be accessed at a URL like mysite.com/menus/dinner/.')
additional_text = models.CharField(max_length=128, null=True, blank=True, help_text='Any additional text that the menu might need, i.e. Served between 11:00am and 4:00pm.')
order = models.PositiveSmallIntegerField(default=0, help_text='The order of the menu determines where this menu appears alongside other menus.')
class Meta:
verbose_name = 'menu name'
def __str__(self):
return self.name
"""
A Menu Category represents a grouping of items within a specific Menu.
An example of a Menu Category would be Appetizers, or Pasta.
"""
class MenuCategory(models.Model):
menu = models.ForeignKey(Menu, null=True, help_text='The menus that this category belongs to, i.e. \'Lunch\'.', on_delete=models.SET_NULL)
name = models.CharField(max_length=32, verbose_name='menu category name')
additional_text = models.CharField(max_length=128, null=True, blank=True, help_text='The additional text is any bit of related information to go along with a menu category, i.e. the \'Pasta\' category might have details that say \'All entrees come with salad and bread\'.')
order = models.IntegerField(default=0, help_text='The order is the order that this category should appear in when rendered on the templates.')
class Meta:
verbose_name = 'menu category'
verbose_name_plural = 'menu categories'
def __str__(self):
return self.name
"""
A Menu Item is an item of food that the restaurant makes. A Menu Item can
belong to multiple Menu Categories to facilitate menus that have the same item
across multiple menus.
"""
class MenuItem(models.Model):
CLASSIFICATION_CHOICES = (
('neither', 'Neither'),
('vegan', 'Vegan'),
('vegetarian', 'Vegetarian'),
)
name = models.CharField(max_length=48, help_text='Name of the item on the menu.')
menu = models.ForeignKey(Menu, null=True, blank=True, help_text='The menus that this category belongs to, i.e. \'Lunch\'.', on_delete=models.SET_NULL)
description = models.CharField(max_length=256, null=True, blank=True, help_text='The description is a simple text description of the menu item.')
category = models.ManyToManyField(MenuCategory, blank=True, verbose_name='menu category', help_text='Category is the menu category that this menu item belongs to, i.e. \'Appetizers\'.')
order = models.IntegerField(default=0, verbose_name='order', help_text='The order is to specify the order in which items show up on the menu.')
price = models.DecimalField(max_digits=6, decimal_places=2, help_text='The price is the cost of the item.')
classification = models.CharField(max_length=10, choices=CLASSIFICATION_CHOICES, default=0, verbose_name='classification', help_text='Select if this item classifies as Vegetarian, Vegan, or Neither.')
spicy = models.BooleanField(default=False, verbose_name='spicy?', help_text='Is this item spicy?')
contains_peanuts = models.BooleanField(default=True, verbose_name='contain peanuts?', help_text='Does this item contain peanuts?')
gluten_free = models.BooleanField(default=False, verbose_name='gluten free?', help_text='Is this item Gluten Free?')
def menu_name(self):
return ",".join([str(p) for p in self.category.all()])
class Meta:
verbose_name = 'menu item'
verbose_name_plural = 'menu items'
verbose_name = 'menu name'
def __str__(self):
return self.name
views.py
from django.shortcuts import render, redirect, reverse, get_object_or_404
from django.views.generic import ListView
from .models import Menu, MenuCategory, MenuItem
# Create your views here.
def listMenus(request):
menu = Menu.objects.all()
context = {
'menu': menu,
}
return render(request, 'menu/menu.html', context)
def get_menu_detail(request, menu_id):
""" A view to show individual product details """
detail = get_object_or_404(Menu, id=menu_id)
menuField = MenuCategory.objects.filter(id=menu_id)
getItem = MenuItem.objects.all()
context = {
'detail': detail,
'menuField': menuField,
'getItem': getItem
}
return render(request, 'menu/menu_detail.html', context)
我仍在研究 python 和框架,所以请原谅我的愚蠢,但如果有人能够指出我正确的方向,我将不胜感激。
要获取属于菜单的类别和项目,您可以这样做:
menuField = MenuCategory.objects.filter(menu=detail) # detail is an instance of Menu
getItem = MenuItem.objects.filter(menu=detail)
此外,由于 detail
是菜单的实例,您可以像这样使用向后查找管理器:
menuField = detail.menucategory_set.all()
getItem = detail.menuitem_set.all()
您可以使用ForeignKey
中的related_name
参数更改反向查找管理器名称,默认情况下它将是小写模型的名称加上_set
。
-已编辑-
在您的特定情况下,首先您要显示属于某个菜单的所有菜单类别,然后列出属于每个类别且也属于该菜单的菜单项,为此您可以执行以下操作:
查看:
from django.db.models import Prefetch
...
def get_menu_detail(request, menu_id):
menu = get_object_or_404(Menu, id=menu_id)
categories = (
MenuCategory.objects.prefetch_related(
Prefetch(
"menuitem_set",
queryset=MenuItem.objects.filter(
menu=menu
), # prefetch only items that belong to the menu
)
)
.filter(menuitem__menu=menu) # categories with items belong to the menu
.distinct()
)
context = {
"menu": menu,
"categories": categories,
}
return render(request, "menu/menu_detail.html", context)
然后,您可以在模板中包含如下内容:
<h1>{{ menu.name }}</h1>
{% for category in categories %}
<h2>{{ category.name }}</h2>
<ul>
{% for menu_item in category.menuitem_set.all %}
<li>{{ menu_item.name }}</li>
{% endfor %}
</ul>
{% endfor %}