Django03 - 路由控制
一:django连接MySQL与SQLite
连接MySQL
1.安装pymysql
pip3 install pymysql
2.去settings
.py中配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': "django_db01",
"HOST": "127.0.0.1",
"PORT": 3306,
"USER": "root",
"PASSWORD": "123456",
}
}
3.用pymysql
替换原来的mysqldb
到项目/app的__init__.py
中或者settings.py
的DATABASES
后输入
import pymysql
pymysql.install_as_MySQLdb()
4.然后执行数据迁移命令
捷径步骤1:Tools - Run manage.py Task...
捷径步骤2:直接输入下方语句
- makemigrations - 生成数据迁移文件
- migrate - 执行数据迁移,同步到数据库
- showmigrations - 查看哪些记录已经同步到数据库中:
[ ]
- 未同步,[ × ]
- 已同步
连接SQLite
也是一个数据库,文件数据库,一个可以就是一个文件,不需要单独安装
常用于移动开发本地存储数据,存在sqlite中
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
二:pycharm操作sqlite和mysql
JetBrains的全系列产品都内置了Data Grip(类似于Navicat的操作数据库的客户端),PyCharm也不例外。
具体操作:
填入数据进行连接
测试连接成功
鼠标点击即可操作
三:路由层之简单路由配置
1.路由参数
实例:
url(r'^index/', views.index,{'name':'Darker','age':18},name='index'),
① 参数1 - regex
上述的第2个部分r'^index/'
,用于填写正则表达式
此处常用正则:
^
- 以...开头
$
- 以...结尾
如果是
r'^$'
,那么一开始就会进入这个对应的页面
② 参数2 - view
上述的第2个部分views.index
,用于填写对应的视图
③ 参数3 - kwargs
上述的第3个部分是一个字典:{'name':'Darker','age':18}
,用于给对应的视图传参
def index(request,name,age):
...
和之后的反向解析一起用的话,位置参数在前,关键字参数在后。
④ 参数4 - name
述的第4个部分name='index'
,用于反向解析
四:路由层之APPEND_SLASH
1.作用
如果用户忘记加/
,可以给URL自动加上/
后缀进行匹配
APPEND_SLASH
默认开启
2.验证
① APPEND_SLASH
开启的情况下
urls.py
中
url(r'^index/$', views.index),
末尾不加/
- 会发送2次请求,还有1次是重定向
重定向示意图
末尾加/
- 会发送1次请求
② APPEND_SLASH
关闭的情况下
3.关闭APPEND_SLASH
在settings.py
中添加下方代码
APPEND_SLASH = False
五:有名分组 无名分组
1.无名分组
无名分组,把分组分出来的值,当作位置参数传递给视图函数
Python中示例:
import re
res = re.search('([0-9]{4})/([0-9]{2})', '2018/12')
print(res.group(1)) # 2018
print(res.group(2)) # 12
urls.py
url(r'^index/([0-9]{4})/([0-9]{2})', views.index),
views.py
def index(request, a, b):
print(a, b)
return render(request, 'index.html')
2.有名分组
有名分组,把分组出来的值,当作关键字参数传递给视图函数
Python中示例:
import re
res = re.search('(?P<year>[0-9]{4})/(?P<month>[0-9]{2})', '2018/12')
print(res.group('year')) # 2018
print(res.group('month')) # 12
urls.py
url(r'^index/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})', views.index),
views.py
def index(request, a, b):
print(a, b)
return render(request, 'index.html')
3.作用
可以从url地址中解析出参数,传递给视图函数使用
4.案例
以博客园的某篇文章为例:
其中:
https
是协议
www.cnblogs.com
是域名
xuexianqi
是用户名称
p
是页面
12767075
是文章id
.html
代表这篇文章是一个静态的页面(也有可能是伪静态)
无名分组:
url(r'^(.*?)/p/(\d+).html', views.index),
有名分组:
url(r'^(?P<name>.*?)/p/(?P<id>\d+).html', views.index),
有名分组和无名分组不能混合使用
5.伪静态
页面分2种:
1种是动态的:http://www.xuexianqi.top/archives/136 (该地址已失效)
伪静态,就是把动态的页面伪装成一个静态的页面(比如说在结尾加上:.html
),便于SEO优化
我是如何实现伪静态的:http://www.xuexianqi.top/archives/294.html
什么是SEO:http://www.xuexianqi.top/archives/367.html
六:路由分发
1.什么是路由分发?
在django项目中,可以创建许多个app,如果把每个app的路由都写在一个urls.py中,代码的耦合度会很高,如果一个页面中,路由过多,会出现一些混乱。
于是,就出现了路由分发的概念:每个app拥有自己独立的urls.py
,然后在总路由中添加每个app的urls.py
的路径,做一个分发的处理。
这样一来,就会识别当前url属于哪个app,直接分发给对应的app去处理
2.如何使用路由分发?
总路由
from app01 import urls as app01_urls
from app02 import urls as app02_urls
urlpatterns = [
url(r'^admin/', admin.site.urls),
# 1.路由分发 - 方法1
url(r'^app01/',include(app01_urls)), # 只要url前缀是app01开头 全部交给app01处理
url(r'^app02/',include(app02_urls)) # 只要url前缀是app02开头 全部交给app02处理
# 2.路由分发 - 方法2
url(r'^app01/',include('app01.urls')),
url(r'^app02/',include('app02.urls'))
# 注意事项:总路由里面的url千万不能加$结尾
]
子路由
# app01 urls.py
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^reg/',views.reg)
]
# app02 urls.py
from django.conf.urls import url
from app02 import views
urlpatterns = [
url(r'^reg/',views.reg)
]
七:反向解析
1.什么是反向解析?
通过路由的别名,解析出路由的地址
动态根据路由别名获得路径,一旦路径改变,不需要改其他代码
2.如何使用反向解析?
① 在urls.py中
url(r'^index111/',views.index,name='index')
② 在视图函数中 使用反向解析
from django.shortcuts import render,HttpResponse,redirect,reverse
url=reverse('index') # index就是路由的别名
print(url)
③ 在模板文件中 使用反向解析
{% url 'index' %}
八:名称空间
1.有了反向解析,为何还需要名称空间?
路由做反向解析时,如果有同名路由,就会出现问题。
为了解决这里问题,可以在路由分发的时候,给每个app的路径设置一个名称空间
2.如何使用?
① 在总路由中设置
url(r'^app01',include('app01.urls','名称空间的名字') ),
② 用在视图函数中 使用名称空间
url=reverse('a01:index') # index就是路由的别名
print(url)
③ 在模板文件中 使用名称空间
{% url 'a01:index' %}
九:django2.0版的path
在django2.0及以上的path
第一个参数不在是正则表达式了,而是一个具体的地址
1.
2.X
以后,建议使用path,第一个参数是一个准确的路径2.如果要使用正则,推荐使用
re_path
,用法和1.X的url
相同
十:path转化器
在django中,有5个内置转换器
str
匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
int
匹配正整数,包含0
slug
匹配字母、数字以及横杠、下划线组成的字符串
uuid
匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00
path
匹配任何非空字符串,包含了路径分隔符(/
)(不能用?
)
实例
path('login/<int:year>', views.login),
path('login/<str:year>', views.login),
path('login/<path:p>', views.article),
实例 - 进阶
实现匹配这种路径:http://127.0.0.1:8000/xuexianqi/p/123.html
-path('<str:name>/p/<int:id>.html', views.article),
-re_path(r'^(?P<name>.*?)/p/(?P<id>\d+).html$', views.login),
-url(r'^(?P<name>.*?)/p/(?P<id>\d+).html$', views.login), # url在2.x以后不建议使用
注意
转换器 不可以在re_path中使用?
十一:自定义转化器
基本步骤
regex属性:这里写的正则表达式就能匹配
to_python方法
to_url 方法
具体方法
converters.py
- 编写自定义转换器
class MyConver():
regex = '[0-9]{4}' # 正则表达式
# 一旦上面的正则表达式匹配成功,就会当做value的参数 传递进来
def to_python(self, value):
return int(value) # 此处返回的值,会当做参数传递到视图函数
def to_url(self, value): # 反向解析时使用
return '%04d' % value
urls.py - 注册自定义转换器
from .converters import MyConver
register_converter(MyConver, 'mine')
urls.py - 使用自定义转换器
path('<mine:name>/', views.index),