【Youtobe trydjango】Django2.2教程和React实战系列十【动态路由、app内部路由】
1. 动态路由示例
1.1 动态路由
views.py
def dynamic_lookup_view(request, id):
obj = Product.objects.get(id=id)
context = {
'object': obj,
}
return render(request, "products/product_detail.html", context)
trydjango\urls.py
from products.views import dynamic_lookup_view
path('products/<int:id>', dynamic_lookup_view, name='product'), # 产品
效果
1.2 处理DoesNotExist不存在
当我们输入一个不存在的id进行查询:
views.py
中dynamic_lookup_view
方法
obj = get_object_or_404(Product, id=id)
或者
try:
obj = Product.objects.get(id=id)
except Product.DoesNotExist:
raise Http404
让页面返回404结果即可:
2. 如何删除对象
products\views.py
def product_delete_view(request, id):
obj = get_object_or_404(Product, id=id)
# POST requestt
if request.method == "POST":
# 确认删除
obj.delete()
return redirect('/') # 删除后页面重定向回主页
context = {
'object': obj,
}
return render(request, "products/product_delete.html", context)
新建模板文件
products\product_delete.html
{% extends 'base.html' %}
{% block content %}
<form action='.' method='POST'> {% csrf_token %}
<h1>确认要删除产品 “{{ object.title }}”?</h1>
<p><input type='submit' value='确定' /> <a href='../'>取消</a></p>
</form>
{% endblock %}
效果
3. 如何获取对象列表
products\views.py
中新建product_list_view
方法
def product_list_view(request):
queryset = Product.objects.all()
context = {
'object_list': queryset,
}
return render(request, "products/product_list.html", context)
trydjango\urls.py
路由
from products.views import product_list_view
path('products/', product_list_view, name='product-list'), # 产品列表
模板文件products/product_list.html
{% extends 'base.html' %}
{% block content %}
{% for instance in object_list %}
<p>{{ instance.id }} - {{ instance.title }}</p>
{% endfor %}
{% endblock %}
4. 动态链接网址
如何从上一步骤的查询出的列表清单跳转到单个对象的详情页或修改、删除页面?
模型文件products/models.py
from django.urls import reverse
def get_absolute_url(self):
return reverse("product-detail", kwargs={"id": self.id})
模板文件products/product_list.html
{% extends 'base.html' %}
{% block content %}
{% for instance in object_list %}
<p>{{ instance.id }} - <a href='{{ instance.get_absolute_url }}'>{{ instance.title }}</a></p>
{% endfor %}
{% endblock %}
urls.py
中name
修改下:
path('products/<int:id>', dynamic_lookup_view, name='product-detail'), # 产品
点击a标签即可跳转过去
5. 整理前面的各层级视图功能
在此先整理前面的各层级视图功能
整理各文件如下:
src\trydjango\products\templates\forms.py
from django import forms
from .models import Product
class ProductForm(forms.ModelForm):
title = forms.CharField(label='', widget=forms.TextInput(attrs={'placeholder': "[Your title]"}))
price = forms.DecimalField(initial=999999999)
description = forms.CharField(
required=False,
widget=forms.Textarea(
attrs={
'class': "new-class-name two",
'id': "my-id-for-textarea",
'rows': 20,
'cols': 100,
}))
class Meta:
model = Product
fields = [
'title',
'price',
'description',
]
def clean_title(self, *args, **kwargs):
title = self.cleaned_data.get('title')
if not "[" in title:
raise forms.ValidationError("This is not a valid title, title should in []")
if not "]" in title:
raise forms.ValidationError("This is not a valid title, title should in []")
return title
class RawProductForm(forms.Form):
title = forms.CharField(label='', widget=forms.TextInput(attrs={'placeholder': "Your title"}))
description = forms.CharField(
required=False,
widget=forms.Textarea(
attrs={
'class': "new-class-name two",
'id': "my-id-for-textarea",
'rows': 20,
'cols': 100,
}))
price = forms.DecimalField(initial=66.6)
src\trydjango\products\templates\products\product_create.html
一定要注意action
里面参数是create
{% extends 'base.html' %}
{% block content %}
<form action='create' method='POST'> {% csrf_token %}
{{ form.as_ul }}
<input type='submit' value='Save' />
</form>
{% endblock %}
src\trydjango\products\views.py
from django.shortcuts import get_object_or_404, redirect, render
from .forms import ProductForm
from .models import Product
def product_create_view(request):
form = ProductForm(request.POST or None)
if form.is_valid():
form.save()
form = ProductForm()
else:
print(form.errors)
context = {
'form': form,
}
return render(request, "products/product_create.html", context)
def product_update_view(request, id=id):
obj = get_object_or_404(Product, id=id)
form = ProductForm(request.POST or None, instance=obj)
if form.is_valid():
form.save()
context = {
'form': form,
}
return render(request, "products/product_create.html", context)
def product_list_view(request):
queryset = Product.objects.all() # 对象列表
context = {
'object_list': queryset,
}
return render(request, "products/product_list.html", context)
def product_detail_view(request, id):
obj = Product.objects.get(id=id)
context = {
'object': obj,
}
return render(request, "products/product_detail.html", context)
def product_delete_view(request, id):
obj = get_object_or_404(Product, id=id)
if request.method == "POST": # 确认删除
obj.delete()
return redirect('/') # 删除后页面重定向回主页
context = {
'object': obj,
}
return render(request, "products/product_delete.html", context)
src\trydjango\trydjango\urls.py
"""trydjango URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/2.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from pages.views import about_view, contact_view, home_view, social_view
from products.views import (product_create_view, product_delete_view,
product_detail_view, product_list_view,
product_update_view)
urlpatterns = [
path('products/', product_list_view, name='product-list'), # 列表
path('products/create', product_create_view, name='product-list'), # 列表
path('products/<int:id>', product_detail_view, name='product-detail'), # 详情
path('products/<int:id>/update/', product_update_view, name='product-update'), # 修改
path('products/<int:id>/delete/', product_delete_view, name='product-delete'), # 删除
path('', home_view, name='home'), # 主页
path('about/', about_view, name='product-detail'), # 关于
path('contact/', contact_view), # 联系方式
path('admin/', admin.site.urls), # 自带用户管理
]