day51 django路由层

orm表关系如何建立

多对多
一对多
一对一
换位思考,先站在一张表上面分析,然后在站在另一张表上分析

图书管理系统
一对多:外键字段健在 多的哪一方
多对多:多对多的外键关系需要建立在第三张表来专门处理
图书表 出版社表 作者表

from django.db import models

# Create your models here.
# 先不要考虑外键关系 先创基表
class Book(models.Model):
    title=models.CharField(max_length=32)
    #小数总共8位,小数占2位
    price=models.DecimalField(max_digits=8,decimal_places=2)
    #书跟出版社是一对多,并且书是多的一方,所以外键字段在书表中
    publish=models.ForeignKey(to='Publish')# to 用来指代跟那张表有关系,默认关联的就是表的主键字段
    '''
    一对多 一对一 外键字段,创建的时候会同步到数据中,表字段会自动加_id后缀
    如果自己加了 还是会加的'''
    #书跟作者是多对多的关系,外键字段在任意一方都可以,但是建议你健在查询频率较高的哪一方
    author=models.ManyToManyField(to='Author')# django orm会自动帮你创建书籍和作者的第三张关系表
    #author这个字段是一个虚拟字段,不能在表中展示出来,仅仅只是起到一个高速orm 键第三张表的关系的作用

class Publish(models.Model):
    title=models.CharField(max_length=32)
    email=models.EmailField()

class Author(models.Model):
    name=models.CharField(max_length=32)
    age=models.IntegerField()
    #一对一的表关系  外键字段健在任意一方都有可以,但是建议键在查询频率较高的哪一方
    author_detail=models.OneToOneField(to='Author_detail')

class Author_detail(models.Model):
    phone=models.BigIntegerField()
    addr=models.CharField(max_length=32)

django请求生命周期流程图

流程图

urls.py路由层

url第一个参数是一个正则表达式,只要该正则表达式能够匹配到内容,就会立刻执行后面的视图函数,而不再往下继续匹配了

路由匹配

urlpatterns = [
    url(r'^admin/', admin.site.urls),#url第一个参数是正则表达式
    url(r'^test/', views.test),#一旦正则表达式能够匹配到内容,会立刻结束匹配关系,直接直接执行后面对应的函数
]# ^限制正则表达式以什么开头
 # $限制正则表达式以什么结尾
'''
django 匹配路由的规律
不加斜杠,先匹配依次试试,如果匹配不上,就会让浏览器加上斜杠再试一次
取消django自动让浏览器加斜杠的功能
APPEND_SLASH=False 该参数默认是True
路由匹配只匹配url部分,不匹配?携带的参数'''

无名分组

将分组内正则表达式匹配到的内容当做位置参数传递给视图函数

当你的路由中有分组的正则表达式,那么在匹配到内容。
执行视图函数的时候,会将分组内正则表达式匹配到的内容当做位置参数传递给视图函数 test(request,分组内正则表达式匹配到的内容)

url(r'^test/(d+)/',views.test)
def test(request,args):
    print('多余的参数:',args)
    return HttpResponse('来啦')

有名分组

将分组内正则表达式匹配到的内容当做位置参数传递给视图函数

当你的路由中有分组 并给分组起了别名,那么在匹配内容的时候,
会将分组内的正则表达式匹配到的内容当做关键字参数传递给视图函数 testadd(request,别名=分组内正则表达式匹配到的内容).

url(r'^testadd/(?P<year>d+)/',views.testadd),
def testadd(request,year):
    print('多余的关键字参数:',year)
    return HttpResponse('又来啦')

利用有名和无名分组,就可以在调用书函数之前给函数传递额外的参数

疑问:无名和有名能否混合使用?
不能,但是同一种分组的情况下,可以使用多次。无名可以有多个,有名可以有多个,但就是不能混合使用。

url(r'^index/(d+)/(d+)/', views.index),
def index(request,args,yesr):
    print('多余的参数:',args,yesr)
    return HttpResponse('还来~~~')

url(r'^index/(?P<args>d+)/(?P<year>d+)/', views.index),
def index(request,args,year):
    print('多余的参数:',args,year)
    return HttpResponse('还来~~~')

反向解析

根据一个别名,动态解析出一个结果,该结果可以直接访问对应的url

第一种情况:
路由中没有正则表达式,是直接写死的

url(r'^index/', views.index),
url(r'^home/', views.home,name='xxx'),#给路由与视图函数对应关系起别名
url(r'^get_url/', views.get_url),

​ 前端反向解析

<p><a href="{% url 'xxx' %}">11111111</a></p>

​ 后端反向解析

def get_url(request):
    url=reverse('xxx')
    return HttpResponse(url)

第二种情况:
路由中有正则表达式,无名分组的反向解析,在解析的时候,需要手动指定正则匹配的

url(r'^index/', views.index),
url(r'^home/(d+)/', views.home,name='xxx'),#给路由与视图函数对应关系起别名
url(r'^get_url/', views.get_url),

前端反向解析

<p><a href="{% url 'xxx' 12355 %}">11111111</a></p>
#手动传入的参数,只需要满足能够被正则表达式匹配到即可

后端反向解析

def get_url(request):
    url=reverse('xxx',args=(41555,))#手动传入的参数,只需要满足能够被正则表达式匹配到即可
    return HttpResponse(url)

第三种情况:
路由中有正则表达式,有名分组的反向解析,在解析的时候,需要手动指定正则匹配的。有名分组的反向解析可以跟无名分组一样。
但是最正规的自而发

 url(r'^index/', views.index),
 url(r'^home/(?P<years>d+)/', views.home,name='xxx'),#给路由与视图函数对应关系起别名
 url(r'^get_url/', views.get_url),

前端反向解析

可以直接用无名分组
<p><a href="{% url 'xxx' 12355 %}">11111111</a></p>
#手动传入的参数,只需要满足能够被正则表达式匹配到即可
规范写法
<p><a href="{% url 'xxx' years=12355 %}">11111111</a></p>

后端反向解析

可以直接用无名分组
def get_url(request):
    url=reverse('xxx',args=(41555,))#手动传入的参数,只需要满足能够被正则表达式匹配到即可
    return HttpResponse(url)
规范写法
def get_url(request):
    url=reverse('xxx',kwargs={'years':4155})
    return HttpResponse(url)

路由分发

前提:
在django中所有的app都可以有自己独立的urls.py templates static 正是由于上面的特点,用django开发项目就可以完全做到多人分组开发,互相不干扰。每个人只开发自己的app。小组长只需要将所有人开发的app整合到一个空的django项目里面,然后在settings配置文件注册,再利用分发将多个app整合到一起即可完成大项目的拼接。

路由分发解决的及时项目的总路由匹配关系过多的情况
使用路由分发,会将总路由不再做匹配的活,而仅仅是做任务分发(请求来了之后,总路由不做对应关系,值询问你要访问那个app的功能,然后将请求转发给对应的app去处理)

#总路由
from django.conf.urls import url,include
from app01 import urls as app01_urls
from app02 import urls as app02_urls
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^app01/',include(app01_urls)),#路由分发需要注意的就是总路由里面不能以$结尾
    url(r'^app02/',include(app02_urls))
]

#子路由
from django.conf.urls import url
from app01 import views
urlpatterns = [
    url('^reg',views.reg)
]
from django.conf.urls import url
from app02 import views

urlpatterns = [
    url('^reg',views.reg)
]

最省事的写法

 url(r'^app01/',include('app01.urls')),
 url(r'^app02/',include('app02.urls'))

名称空间

当多个app中出现了别名冲突的情况,在做路由分发的时候,可以给每个app创建一个名称空间。然后在反向解析的时候,可以选择到底去哪个名称空间中查找别名

 url(r'^app01/',include('app01.urls',namespace='app01')),
 url(r'^app02/',include('app02.urls',namespace='app02'))
#后端
print(reverse('app01:reg'))
print(reverse('app02:reg'))
#前端
<a href="{% url 'app01:reg' %}"></a>
<a href="{% url 'app02:reg' %}"></a>

其实上面的名称空间知识点可以完全不用,只需要保证起别名的时候,在整个django项目中不冲突即可
参考建议:起别名的时候,统一加上应用名前缀

urlpatterns = [
	url(r'^reg/',views.reg,name='app02_reg')
]
					
urlpatterns = [
	 url('^reg/',views.reg,name='app01_reg')
]

伪静态

将一个动态网页伪装成一个静态网页,以此来提高搜索引擎SEO查询频率和收藏力度
所谓的搜索引擎其实就是一个特别巨大的爬虫程序

url('^reg.html',views.reg,name='app01_reg')

虚拟环境

给每个项目 装备该项目所需要的模块 不需要的模块一概不装
每创建一个虚拟环境就类似于你重新下载了一个纯净python解释器
之后该项目用到上面 用什么项目就装什么(虚拟环境一台机器上可以有N多个)
不要在你的机器上无限创建虚拟环境

django版本区别

django1.X django2.X

urls.py路由匹配的方法有区别
django2.x用的是path,
django1.x用的死url

urlpatterns = [
	path('admin/', admin.site.urls),
]
urlpatterns = [
	url(r'^reg.html',views.reg,name='app02_reg')
]

区别:django2.X里面path第一个参数不是正则也不支持正则,写什么就匹配什么
虽然path不支持正则,但django2.X还有一个re_path的方法,该方法就是django1.X里面的url
path提供了五种转换器,能够匹配到数据自动转换成对应的类型
除了有默认五种转换器之外,还支持自定义转换器

urlpatterns = [
    path('admin/', admin.site.urls),
    # re_path(r'^index/$',index),
    path('index/<int:id>/<str:xxx>',index),
]

form表单长传文件 后端如何获取

1.method 必须改成post
2.enctype改成form-data
前期在使用post朝后端发送的时候,需要去settings配置文件中注释掉一个中间件csrf

jsonresponse

原文地址:https://www.cnblogs.com/zqfzqf/p/11932164.html