1 2 3 4

django - 路由层

django 基础三

一.表关系的建立

一对多: 出版社出的书 ,一个出版社可以出几本书,一本书只能由一个出版社出版。
多对多:一本书可以由几个作者著作,,一个作者可以写几本书。
一对一:作者的姓名 电话的列表,和关于每个作者的性别 年龄 爱好等简介的表是一对一的关系。

# 如何判断  换位思考 
	以图书管理管理系统
		图书表
			图书和出版社是一对多的外键关系
			一对多外键关系 外键字段建在多的那一方
			
			
		出版社
		
		作者表
			图书与作者是多对多外键关系
			多对多外键关系 外键字段无论建在哪张表里面都可以
			但是推荐你建在查询频率较高的那种表中
			
			作者与作者详情是一对一的外键关系
			一对一外键关系 外键字段建在哪张表里面都可以
			但是推荐你建在查询频率较高的那种表中
			
			
			# 方便我们后面的基于orm查询
			
			
	"""
	
from django.db import models

# Create your models here.
class Book(models.Model):
    # id是自动创建的 我们就不写了
    title = models.CharField(max_length=64)
    # price为小数字段 总共8位小数位占2位
    price = models.DecimalField(max_digits=8,decimal_places=2)

    # 书籍与出版社 是一对多外键关系
    publish = models.ForeignKey(to='Publish')  # 默认关联字段就是出版社表的主键字段
    # publish = models.ForeignKey(to=Publish)  # to后面也可以直接写表的变量名 但是需要保证该变量名在当前位置的上方出现

    # 书籍与作者   是多对多外键关系
    authors = models.ManyToManyField(to='Author')  # 书籍和作者是多对多关系
    """
    authors字段是一个虚拟字段 不会真正的在表中创建出来
    只是用来告诉django orm 需要创建书籍和作者的第三张关系表
    """

class Publish(models.Model):
    name = models.CharField(max_length=64)
    addr = models.CharField(max_length=64)


class Author(models.Model):
    name = models.CharField(max_length=32)
    phone = models.BigIntegerField()
    # 一对一外键关系建立
    author_detail = models.OneToOneField(to='AuthorDetail')


class AuthorDetail(models.Model):
    age = models.IntegerField()
    addr = models.CharField(max_length=255)

在书写表关系的时候 要先把基表全部写出来 之后再考虑外键字段

ForeignKey字段以及OneToOneField字段 在创建表的时候orm都会自动给该字段加_id的后缀
无论自己有没有加

路由层

一.路由的匹配

首页可以这么来写

url(r'^$', views.home),

def home(request):
    return HttpResponse('欢迎光临')
	urlpatterns = [
			url(r'^admin/', admin.site.urls), ^正则表达  是以什么开头
			url(r'test',views.test),  ###在浏览器端的输入testadd ,只会执行test的
            函数 不会执行testadd  因为这个是正则,在你输入testadd时,正好于test匹配上了就不会往下执行了
			url(r'testadd',views.testadd)
		]
        
	url方法第一个参数是一个正则表达式
	路由匹配按照正则匹配 一旦正则能够匹配到内容 会立刻执行对应的视图函数
	不会再继续匹配了
	
	
	用户输入url不加最后的斜杠 django会默认自动加上 ,正常的执行test 和 testadd    
	你可以在配置文件中指定是否开启该功能
	APPEND_SLASH = True/False  默认的是True  如果改为False 就会出现这个不加/ 出现404
    
  

二.无名分组和有名分组

分组就是给一段正则表达式加括号

无名分组

		在路由匹配的时候给某段正则表达式加了括号
		匹配的时候会将括号内正则表达式匹配到的内容当做位置参数传递给对应的视图函数
		# 无名分组
		url(r'^test/([0-9]{4})/',views.test) ##([0-9]{4}) 正则 代表的是0-9之间任意取4个数字
		# 视图函数
		def index(request,args):
            print(args)
			return HttpResponse('11111')
        >>>>>>>>>>>>>>>>>>>>>>>>
        如果浏览器的提交数据是http://127.0.0.1:8000/loginadd/1232/
                打印的结果是1232

有名分组

给一段正则表达式起一个别名
		匹配的时候会将括号内正则表达式匹配到的内容当做关键字参数传递给对应的视图函数
		# 有名分组
		url(r'^test/(?P<year>\d+)/',views.test) #(?P<year>\d+) ?P<year>起的别名叫year   \d+匹配一个或者多个数字
		# 视图函数
		def index(request,year):
            print(year)
			return HttpResponse('22222')
        >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        http://127.0.0.1:8000/loginadd/123/
                打印的结果是123
      
    补充:	
		# 无名有名能否混合使用   >>>    不能!!!
		# url(r'^test/(\d+)/(?P<year>\d+)/', views.test),
		# 虽然不能混合使用 但是同一种命名方式 可以使用多个
		# url(r'^test/(\d+)/(\d+)/',views.test),
		url(r'^test/(?P<xxx>\d+)/(?P<year>\d+)/',views.test),
	

三.反向解析

通过一些方法 能够得到一个结果 该结果可以访问到对应的url

urls

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^$', views.home),
    url(r'^login/([0-9]{4})/', views.login),
    # url(r'^loginadd/', views.loginadd,name='add'),#这个是起了起了一个名
    这个名字 来访问对应的url
    url(r'^dsggewehhjhg/', views.loginadd,name='add'), #这样做的目的是 路由的名字可以改变,随意变 只要别名add不变 这个访问的对应的url 就不会改变
]

views

from django.shortcuts import render,HttpResponse,redirect,reverse


def login(request,x):
    print(x)
    return HttpResponse('login收到了')

def loginadd(request):

    return HttpResponse('loginadd收到了')

def home(request):
    _url= reverse('add')  ###这个是后端通过这个reverse来访问对应的url
    return render(request,'home.html')

home.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.js"></script>
</head>
<body>
{#<a href="loginadd">111</a>#}#不用别名的访问
{#<a href="loginadd">111</a>#}
{#<a href="loginadd">111</a>#}
<a href="{% url 'add' %}">111</a> ##起了别名的访问
<a href="{% url 'add' %}">111</a>
<a href="{% url 'add' %}">111</a>
</body>
</html>
使用方式 
			先给路由与视图函数对应关系 起一个名字
				url(r'^testadd/',views.testadd,name='add')
			前端解析
				{% url 'add' %}
			后端解析
				from django.shortcuts import render,HttpResponse,redirect,reverse
				reverse('add')
			
无名分组反向解析
			# 无名分组反向解析
				url(r'^testadd/(\d+)/',views.testadd,name='add')
			前端解析
				{% url 'add' 1 %}
			后端解析
				reverse('add',args=(12,)) #通常是数据的主键值
	
	有名分组反向解析
			# 有名分组反向解析
				url(r'^testadd/(?P<year>\d+)/',views.testadd,name='add')
			前端解析
				{% url 'add' 1 %}  # 推荐使用
				{% url 'add' year= 1 %}  # 标准的
			后端解析
				reverse('add',args=(12,))
				reverse('add',kwargs={'year':12})
	
	伪代码诠释
		"""
		url(r'^edit_user/(\d+)/',views.edit_user,names='edit')
		
		
		{% for user_obj in user_queryset %}
			<a href="edit_user/{{ user_obj.id }}/">编辑</a>
			<a href="{% url 'edit' user_obj.id %}">编辑</a>
		{% endfor %}
		
		
		def edit_user(request,edit_id):
			reverse('edit',args=(edit_id,))
    
		"""

四.路由分发

总路由不再干路由与视图函数对应关系 而只是做任务的分发(下发给不同的app)
每个app都可以有自己的urls.py static文件夹 templates模板文件夹

当django项目比较庞大的时候 路由与视图函数对应关系较多
总路由代码太多冗长
考虑到总路由代码不好维护 django支持每个app都可以有自己的urls.py
并且总路由不再做路由与视图函数的对应关系 而仅仅只做一个分发任务的操作
需要 一个分发的模块 include

	根据请求的不同 识别出当前请求需要访问的功能属于哪个app然后自动
	下发到对应app里面的urls.py中 然后由app里面的urls.py做路由与视图函数的匹配
	
	不仅如此每个app除了可以有自己的urls.py之外 还可以有自己的static文件夹 templates模板文件
	基于上面的特点 基于django分小组开发 会变得额外的简单
	每个人只需要开发自己的app即可 之后只需要创建一个空的django项目
	将多个人的app全部拷贝项目下 配置文件注册
	总路由分发一次 
1.总路由
		from django.conf.urls import url,include
		
		# from app01 import urls as app01_urls
		# from app02 import urls as app02_urls
		# 路由分发  注意事项应用名后面千万不能加$
		# from app01 import urls as app01_urls
		# from app02 import urls as app02_urls
		# url(r'^app01/',include(app01_urls)),
		# url(r'^app02/',include(app02_urls))
		
		# 简写(上面的导入起别名的模块可以省略)
		url(r'^app01/',include('app01.urls')),
		url(r'^app02/',include('app02.urls'))
		
		2.子路由
			from django.conf.urls import url
			from app01 import views

			urlpatterns = [
				url(r'^index/',views.index)
			]
			
			from django.conf.urls import url
			from app02 import views

			urlpatterns = [
				url(r'^index/',views.index)
			]
	
五.名称空间

当多个app中出现路由与视图函数对应关系起名字冲突的情况

如果总路由下面的分路由,在起一样的别名时,前端或者后端解析会出现冲突错误,所以需要名词空间。

 用了名称空间
    在总的urls
		url(r'^app01/',include('app01.urls',namespace='app01'))
        url(r'^app02/',include('app02.urls',namespace='app02'))
     在单独的分路由的加起别名
     from app01 import views
    urlpatterns = [
    url(r'^loginadd/',views.loginadd,name='111')

]
    from app02 import views
urlpatterns = [
    url(r'^loginadd/',views.loginadd,name='111')
]
		后端解析
		reverse('app01:index')
		reverse('app02:index')
		前端解析
		{% url 'app01:index' %}
		{% url 'app02:index' %}
		# 在给路由与视图函数起别名的时候只需要保证永远不出现冲突的情况即可
		# 通常情况下我们推荐期别名的时候加上当前应用的应用名前缀
		
		url(r'^index/',views.index,name='app01_index')
		url(r'^index/',views.index,name='app02_index')

六.虚拟空间

虚拟环境
我们想做到针对不同的项目 只安装项目所需要的功能模块
项目用不到的一概不装 来避免加载资源时的消耗

	如何创建虚拟环境
	
	虚拟环境就类似于一个纯净的python解释器环境
	大白话 没创建一个虚拟幻境就类似于你重新下载一个python解释器
	
	虚拟环境不推荐你使用太多
	学习阶段我们还是用本机的环境即可 将所有模块全部装到本机环境下

七.django的区别

路由层
				1.X用的是url
				2.X、3.X用的是path
			
			url第一个参数是一个正则表达式
			而path第一个参数不支持正则表达式 写什么就匹配什么
			如果你觉得path不好用 2.x、3.x给你提供了一个跟url一样的功能
			re_path 等价于1.x里面的url功能
			
			虽然path不支持正则表达式 但是它给你提供了五种默认的转换器
			str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
			int,匹配正整数,包含0。
			slug,匹配字母、数字以及横杠、下划线组成的字符串。
			uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
			path,匹配任何非空字符串,包含了路径分隔符(/)(不能用?)
			
			path('login/<int:year>/',login)
            
            下面是举例:
            浏览器输入数据:
            http://127.0.0.1:8000/test/sjjgj--ffe、、、、dvdsk/
                    
            url.py层
            urlpatterns = [
            path('admin/', admin.site.urls),
            path('test/<path:year>/', views.test),
            ] 
            
            views.py层
            def test(request,year):
                print(year,type(year))
                return HttpResponse('你好')
			
            >>>>>>>>>>>>>>>>>>>>>>>>>>>>
            sjjgj--ffe、、、、dvdsk <class 'str'>
            
            
			除了默认的五种转换器之外 还支持你自定义转换器
			class MonthConverter:
			regex='\d{2}' # 属性名必须为regex

			def to_python(self, value):
				return int(value)

			def to_url(self, value):
				return value # 匹配的regex是两个数字,返回的结果也必须是两个数字

八.伪静态

伪静态
url以.html结尾 给人的感觉好像是这个文件是写死的 内容不会轻易的改变
伪静态
为了提高你的网站被搜索引擎收藏的力度 提供网站的SEO查询效率

但是 无论你怎么做优化 都抗不过RMB玩家

urls.py 层
urlpatterns = [
    path('admin/', admin.site.urls),
    path('test1.html/', views.test1),
]

views.py层
def test1(request):
    return HttpResponse('充满男子汉气概!')

浏览器页面:
http://127.0.0.1:8000/test1.html/

django的请求生命周期流程图

posted @ 2020-01-07 16:17  ^更上一层楼$  阅读(395)  评论(1编辑  收藏  举报