没有前缀的 URL
URLs with no prefixes
我想知道是否可以在没有任何额外前缀的情况下访问所有页面及其详细信息页面。
示例:
'''
/vegetables
/carrot --> (detail page for vegetables)
/fruits
/apple --> (detail page for fruits)
'''
示例 URL 模式,我根据要求添加视图。
#urls.py
urlpatterns = [
path('', views.index, name='index'),
path('fruits/', views.all_fruits, name='fruits'),
path('vegetables/', views.all_vegetables, name='vegetables'),
path('<slug:slug>/', views.fruit_detail, name='fruit'),
path('<slug:slug>/', views.vegatable_detail, name='vegetable'),
]
#views.py
from .models import Fruit, Vegetable
def index(request):
return render (request, 'index.html')
def all_fruits(request):
fruits=Fruit.objects.all()
return render(request, 'fruits.html', {'fruits':fruits})
def all_vegetables(request):
vegetables=Vegetable.objects.all()
return render(request, 'vegetables.html', {'vegetables':vegetables})
def fruit_detail (request, slug):
fruit = get_object_or_404(Fruit, slug=slug)
return render(request, 'fruit_detail.html', {'fruit':fruit})
def vegetable_detail (request, slug):
vegetable = get_object_or_404(Vegetable, slug=slug)
return render(request, 'vegetable_detail.html', {'vegetable':vegetable})
可以预见;尝试访问蔬菜详情页面时,由于使用了水果的视图而出错。
提前感谢您的帮助和反馈。
当您首先在 Fruit
个对象中查找特定的 slug,然后在 Vegetable
个对象中查找特定的 slug 并将找到的实例添加到模板上下文中时,您可以通过编写特殊的重定向视图来实现您想要实现的目标 但是它是非常低效和“肮脏”的。使用标准 urls(就像你现在所做的那样)Django 路由器将不知道当有人输入时你指的是哪个 slug
例如 yoursite.com/xyzabc
Django 不知道它是否应该查找例如插入 fruit
table 或 vegetable
table。
您应该像现在一样继续创建问题,但我建议您使用(在我看来)使用 Django 的更成熟的解决方案generic views. Of course you can use them without deep understanding of Class Based Views,但我强烈建议您使用它们。
简介
正如您可能注意到的那样,您对所有基于函数的视图使用了“相同的”copy/paste 代码。在一个小项目上这样做没问题但是你应该总是想让你的代码灵活、可扩展,更重要的是易于refactor/reformat
ListView
当您的大部分视图都专注于呈现像 all_fruits
和 all_vegetables
这样的对象列表时, 很有用
DetailView
当您想显示带有特定实例信息的模板时很有用。这正是您在 fruit_detail
和 vegetable_detail
中所做的
你的代码是用 CBV 写的
views.py
from .models import Fruit, Vegetable
from django.views.generic.base import TemplateView
from django.views.generic.detail import DetailView
from django.views.generic.list import ListView
class IndexView(TemplateView):
template_name = 'index.html'
# former all_fruits view
class FruitListView(ListView):
model = Fruit
template_name = 'fruits.html'
class VegetableListView(ListView):
model = Vegetable
template_name = 'vegetables.html'
# former fruit_detail view
class FruitDetailView(DetailView):
model = Fruit
template_name = 'fruit_detail.html'
class VegetableDetailView(DetailView):
model = Vegetable
template_name = 'vegetable_detail.html'
如果您仔细研究通用视图,您会发现如果您根据 Django 的文档构建项目树,甚至可以跳过 template_name
部分
urls.py
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('fruits/', views.FruitListView.as_view(), name='fruits'),
path('vegetables/', views.VegetableListView.as_view(), name='vegetables'),
path('fruits/<slug:slug>/', views.FruitDetailView.as_view(), name='fruit'),
path('vegetables/<slug:slug>/', views.VegetableDetailView.as_view(), name='vegetable'),
]
上面的答案显示了应该如何按照最佳 Django 实践来完成,但我们知道有时客户有特殊需求,例如由于 CEO 的原因所以为了完全回答这里的问题是如何访问多个详细信息页面使用一条路线的模型 (url)。
views.py
# instead of using two views VegetableDetailView and FruitDetalView
# we will use one common view to filter out the needed instance
# Rest of the code stays as in upper answer
...
class FruitOrVegetableDetailView(View):
def get(self, request, slug, *args, **kwargs)
try:
return render(request, 'fruit_detail.html',
{'fruit': Fruit.objects.get(slug=slug)})
except Fruit.DoesNotExist:
veg = get_object_or_404(Vegetable, slug=slug)
return render(request, 'vegetable_detail.html',
{'vegetable': veg})
当然我们需要改变路由
urls.py
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('fruits/', views.FruitListView.as_view(), name='fruits'),
path('vegetables/', views.VegetableListView.as_view(), name='vegetables'),
path('<slug:slug>/', views.FruitOrVegetableDetailView.as_view(), name='fruit_or_vegetable_detail'),
]
我想知道是否可以在没有任何额外前缀的情况下访问所有页面及其详细信息页面。
示例:
'''
/vegetables
/carrot --> (detail page for vegetables)
/fruits
/apple --> (detail page for fruits)
'''
示例 URL 模式,我根据要求添加视图。
#urls.py
urlpatterns = [
path('', views.index, name='index'),
path('fruits/', views.all_fruits, name='fruits'),
path('vegetables/', views.all_vegetables, name='vegetables'),
path('<slug:slug>/', views.fruit_detail, name='fruit'),
path('<slug:slug>/', views.vegatable_detail, name='vegetable'),
]
#views.py
from .models import Fruit, Vegetable
def index(request):
return render (request, 'index.html')
def all_fruits(request):
fruits=Fruit.objects.all()
return render(request, 'fruits.html', {'fruits':fruits})
def all_vegetables(request):
vegetables=Vegetable.objects.all()
return render(request, 'vegetables.html', {'vegetables':vegetables})
def fruit_detail (request, slug):
fruit = get_object_or_404(Fruit, slug=slug)
return render(request, 'fruit_detail.html', {'fruit':fruit})
def vegetable_detail (request, slug):
vegetable = get_object_or_404(Vegetable, slug=slug)
return render(request, 'vegetable_detail.html', {'vegetable':vegetable})
可以预见;尝试访问蔬菜详情页面时,由于使用了水果的视图而出错。
提前感谢您的帮助和反馈。
当您首先在 Fruit
个对象中查找特定的 slug,然后在 Vegetable
个对象中查找特定的 slug 并将找到的实例添加到模板上下文中时,您可以通过编写特殊的重定向视图来实现您想要实现的目标 但是它是非常低效和“肮脏”的。使用标准 urls(就像你现在所做的那样)Django 路由器将不知道当有人输入时你指的是哪个 slug
例如 yoursite.com/xyzabc
Django 不知道它是否应该查找例如插入 fruit
table 或 vegetable
table。
您应该像现在一样继续创建问题,但我建议您使用(在我看来)使用 Django 的更成熟的解决方案generic views. Of course you can use them without deep understanding of Class Based Views,但我强烈建议您使用它们。
简介
正如您可能注意到的那样,您对所有基于函数的视图使用了“相同的”copy/paste 代码。在一个小项目上这样做没问题但是你应该总是想让你的代码灵活、可扩展,更重要的是易于refactor/reformat
ListView
当您的大部分视图都专注于呈现像 all_fruits
和 all_vegetables
很有用
DetailView
当您想显示带有特定实例信息的模板时很有用。这正是您在 fruit_detail
和 vegetable_detail
你的代码是用 CBV 写的
views.py
from .models import Fruit, Vegetable
from django.views.generic.base import TemplateView
from django.views.generic.detail import DetailView
from django.views.generic.list import ListView
class IndexView(TemplateView):
template_name = 'index.html'
# former all_fruits view
class FruitListView(ListView):
model = Fruit
template_name = 'fruits.html'
class VegetableListView(ListView):
model = Vegetable
template_name = 'vegetables.html'
# former fruit_detail view
class FruitDetailView(DetailView):
model = Fruit
template_name = 'fruit_detail.html'
class VegetableDetailView(DetailView):
model = Vegetable
template_name = 'vegetable_detail.html'
如果您仔细研究通用视图,您会发现如果您根据 Django 的文档构建项目树,甚至可以跳过 template_name
部分
urls.py
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('fruits/', views.FruitListView.as_view(), name='fruits'),
path('vegetables/', views.VegetableListView.as_view(), name='vegetables'),
path('fruits/<slug:slug>/', views.FruitDetailView.as_view(), name='fruit'),
path('vegetables/<slug:slug>/', views.VegetableDetailView.as_view(), name='vegetable'),
]
上面的答案显示了应该如何按照最佳 Django 实践来完成,但我们知道有时客户有特殊需求,例如由于 CEO 的原因所以为了完全回答这里的问题是如何访问多个详细信息页面使用一条路线的模型 (url)。
views.py
# instead of using two views VegetableDetailView and FruitDetalView
# we will use one common view to filter out the needed instance
# Rest of the code stays as in upper answer
...
class FruitOrVegetableDetailView(View):
def get(self, request, slug, *args, **kwargs)
try:
return render(request, 'fruit_detail.html',
{'fruit': Fruit.objects.get(slug=slug)})
except Fruit.DoesNotExist:
veg = get_object_or_404(Vegetable, slug=slug)
return render(request, 'vegetable_detail.html',
{'vegetable': veg})
当然我们需要改变路由
urls.py
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('fruits/', views.FruitListView.as_view(), name='fruits'),
path('vegetables/', views.VegetableListView.as_view(), name='vegetables'),
path('<slug:slug>/', views.FruitOrVegetableDetailView.as_view(), name='fruit_or_vegetable_detail'),
]