3 Django 创建表关系 请求生命周期流程图 路由层 无名/有名分组 反向解析

Django

1 ORM创建表关系

表与表之间的关系:一对多,多对多,一对一。
判断表关系的方法:换位思考。

案例:图书表,出版社表,作者表,作者详情表

图书表和出版社表是一对多的关系,外键字段建在多的一方,即图书表上;
图书表和作者表是多对多的关系,需要创建第三张表来存储两张表的外键字段;
作者表与作者详情表是一对一的关系,外键字段建在查询频率较高的一方,即作者表上。
1.1 创建表
from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=32, verbose_name='书名')
    price = models.DecimalField(max_length=8, max_digits=2, verbose_name='价格')

class Publish(models.Model):
    name = models.CharField(max_length=32, verbose_name='出版社名')
    addr = models.CharField(max_length=128, verbose_name='出版社地址')

class Author(models.Model):
    name = models.CharField(max_length=32, verbose_name='作者姓名')
    age = models.IntegerField(verbose_name='作者年龄')

class AuthorDetail(models.Model):
    phone = models.BigAutoField(verbose_name='手机号码')
    addr = models.CharField(max_length=128, verbose_name='居住地址')
1.2 创建表关系
1.2.1 一对多

图书表和出版社表是一对多的关系,外键字段建在多的一方,即图书表上。

models.ForeignKey(to='关联表名')
class Book(models.Model):
    title = models.CharField(max_length=32, verbose_name='书名')
    price = models.DecimalField(max_length=8, max_digits=2, verbose_name='价格')
    public = models.ForeignKey(to='Public')  # 默认是与出版社表的主键字段做关联。
1.2.2 多对多

图书表和作者表是多对多的关系,不需要手动创建第三张关系表;
需要外键字段,外键字段建在任意一方均可,推荐建在查询频率较高的一方;
外键字段只是一个虚拟字段,不会真正地在表中展示出来,只是用来表明当前表和关联表是多对多的关系,ORM会自动创建第三张关系表。

models.ManyToManyField(to='关联表名')
class Book(models.Model):
    title = models.CharField(max_length=32, verbose_name='书名')
    price = models.DecimalField(max_length=8, max_digits=2, verbose_name='价格')
    public = models.ForeignKey(to='Public')
    authors = models.ManyToManyField(to='Author')
    # authors是一个虚拟字段,表明图书表和作者表是多对多的关系。
1.2.3 一对一

作者表与作者详情表是一对一的关系,外键字段推荐建在查询频率较高的一方,即作者表上。

models.OneToOneField(to='关联表名')
class Author(models.Model):
    name = models.CharField(max_length=32, verbose_name='作者姓名')
    age = models.IntegerField(verbose_name='作者年龄')
    author_detail = models.OneToOneField(to='AuthorDetail')
1.3 结果
app02_author
app02_authordetail
app02_book
app02_book_authors
app02_publish
auth_group
auth_group_permissions
auth_permission
auth_user
auth_user_groups
auth_user_user_permissions
django_admin_log
django_content_type
django_migrations
django_session

在这里插入图片描述

1.4 总结
  1. ORM中如何定义三种关系
# 图书表和出版社表是一对多的关系,外键字段建在多的一方,即图书表上。
publish = models.ForeignKey(to='Publish')

# 图书表和作者表是多对多的关系,ORM会自动创建第三张表,外键字段推荐建在查询频率较高的一方,即图书表上。
authors = models.ManyToManyField(to='Author')

# 作者表与作者详情表是一对一的关系,外键字段推荐建在查询频率较高的一方,即作者表上。
author_detail = models.OneToOneField(to='AuthorDetail')
  1. 如果字段对应的是ForeignKey,ORM会自动在字段名后面添加后缀_id;
  2. 在django 1.X版本中,外键默认是级联更新级联删除的。

2 Django请求生命周期流程图

web服务网关接口
Django使用自带的wsgiref模块
作用:

  1. 收到请求时,对http协议格式的请求数据进行解析,并封装成字典格式;
  2. 发送响应时,将响应数据封装成符合http协议格式的数据。

补充:

  1. wsgiref模块支持的并发量不大,最大并发量不超过1000;
  2. 项目上线后一般会换成uwsgi来提高最大并发量,前面还会加nginx进行反向代理;
  3. WSGI,wsgiref 和 uwsgi 是什么关系?
    WSGI是协议,wsgiref和uwsgi是实现该协议的功能模块。
    在这里插入图片描述

3 路由层

3.1 路由匹配

urls.py

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'test', views.test),
    url(r'test123', views.test123),
]

url函数中第一个参数是正则表达式。
一旦请求的url与正则表达式匹配成功,立即停止继续匹配,并执行相应的视图函数。

当访问 http://127.0.0.1:8000/test123 时,test123中包含test,匹配成功,
只要正则表达式能够匹配到内容,就会停止向下继续匹配,执行相应的视图函数test。
这意味着视图函数test123永远无法执行。

3.2 路由结尾添加正斜杠/
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'test/', views.test),
    url(r'test123/', views.test123),
]

结尾没有正斜杠/的匹配流程
当访问 http://127.0.0.1:8000/test123 时,其结尾没有正斜杠,不满足任何url函数的正则匹配条件。
django会自动在url后面添加正斜杠,并让浏览器重定向到新url: http://127.0.0.1:8000/test123/
django对新的url重新进行匹配,最后找到 url(r'test123/', views.test123)
在这里插入图片描述
可以让django取消为url自动添加正斜杠功能。

settings.py

APPEND_SLASH = False
3.3 严格匹配
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^test/$', views.test),
    url(r'^test123/$', views.test123),
]

主页匹配

urlpatterns = [
	url(r'^admin/', admin.site.urls),
	url(r'^$', views.home),
]
3.4 无名分组 有名分组

分组,就是将某一段正则表达式用小括号包起来。

3.4.1 无名分组

无名分组,就是将括号内正则表达式匹配到的内容当作位置参数传递给后面的视图函数。

urls.py

url(r'^test/(\d+)/', views.test)

访问 http://127.0.0.1:8000/test/123456/ 时,会将匹配到的内容123456传递给后面的视图函数。

views.py

def test(request, arg1):
    print(arg1)  # 123456
    return HttpResponse('test')
3.4.2 有名分组

可以给正则表达式起一个别名。
有名分组,就是将括号内正则表达式匹配到的内容当作关键字参数传递给后面的视图函数。

urls.py

url(r'^testadd/(?P<year>\d+)', views.test)

访问 http://127.0.0.1:8000/test/2020/

views.py

def test(request, year):
    print(year)  # 2020
    return HttpResponse('test')
3.4.3 总结
  1. 无名分组和有名分组不可以混合使用;
  2. 同一种分组可以使用多次。

urls.py

url(r'^index1/(\d+)/(\d+)/(\d+)/', views.index1),
url(r'^index2/(?P<year>\d+)/(?P<month>\d+)/(?P<date>\d+)/', views.index2),

views.py

def index1(request, *args, **kwargs):
    return HttpResponse('index1')

def index2(request, *args, **kwargs):
    return HttpResponse('index2')
3.5 反向解析
3.5.1 介绍

路由层中如果修改了用于匹配url的正则表达式,前端模板中的超链接和后端视图中的重定向都要随之发生变化。
希望让超链接和重定向根据路由层中的正则表达式反向地动态地获取,即反向解析。

反向解析的本质:通过一些方法得到一个结果,该结果可以访问到对应的url,从而去触发对应的视图函数。

3.5.2 基本操作流程
  1. 先给路由与视图函数的关系起一个别名

urls.py

url(r'^test/', views.func_test, name='test_name')

别名不能出现重复。

  1. 反向解析

前端反向解析

<!-- 模板中的超链接 -->
<a href="{% url 'test_name' %}">链接</a>
<!-- http://127.0.0.1:8000/test/ -->

后端反向解析

views.py

from django.shortcuts import redirect, reverse

print(reverse('test_name'))  # /test/

# 视图中的重定向
return redirect(reverse('test_name'))
3.5.3 无名分组/有名分组反向解析
3.5.3.1 无名分组反向解析

urls.py

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^test/(\d+)', views.test, name='test_name'),
]

后端
views.py

def test(request):
    print(reverse('test_name', args=(1,)))  # /test/1
    return render(request, 'test.html')

函数reverse中需要提供参数args,用于匹配路由的正则表达式,否则会报错。

NoReverseMatch at /test/
Reverse for 'test_name' with no arguments not found. 1 pattern(s) tried: ['test/(\\d+)']

前端
test.html

<a href="{% url 'test_name' 123 %}">链接</a>
<!-- http://127.0.0.1:8000/test/123 -->

这个数字一般是数据的主键值,便于定位数据,进行数据获取、编辑和删除等操作。

urls.py

url(r'^edit/(\d+)/', views.edit, name='edit_url')

views.py

def edit(request, user_id):
    reverse('edit_url', args=(user_id,))

test.html

{% for user_obj in user_queryset %}
    <a href="{% url 'edit_url' user_obj.id %}">编辑</a>
{% endfor %}
3.5.3.2 有名分组反向解析

urls.py

url(r'^edit/(?P<user_id>\d+)/', views.edit, name='edit_url')

views.py

def edit(request, user_id):
	# 正式写法
    reverse('edit_url', kwargs={'user_id': user_id})  
def edit(request, user_id):
	# 简便写法 与无名分组一样
    reverse('edit_url', args=(user_id,))  

test.html

{% for user_obj in user_queryset %}
	<!-- 正式写法 -->
    <a href="{% url 'edit_url' edit_url=user_obj.id %}">编辑</a>
    
    <!-- 简便写法 与无名分组一样 -->
    <a href="{% url 'edit_url' user_obj.id %}">编辑</a>
{% endfor %}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值