Django 框架系列
目录一. 安装启用
1.1 主流web框架概述
https://www.django.cn/
"""
django
特点:大而全 自带的功能特别特别特别的多 类似于航空母舰
不足之处:
有时候过于笨重
flask
特点:小而精 自带的功能特别特别特别的少 类似于游骑兵
第三方的模块特别特别特别的多,如果将flask第三方的模块加起来完全可以盖过django
并且也越来越像django
不足之处:
比较依赖于第三方的开发者
tornado
特点:异步非阻塞 支持高并发
牛逼到甚至可以开发游戏服务器
不足之处:
暂时你不会
"""
A:socket部分
B:路由与视图函数对应关系(路由匹配)
C:模版语法
django
A用的是别人的 wsgiref模块
B用的是自己的
C用的是自己的(没有jinja2好用 但是也很方便)
flask
A用的是别人的 werkzeug(内部还是wsgiref模块)
B自己写的
C用的别人的(jinja2)
tornado
A,B,C都是自己写的
1.2 安装版本
Django 版本 | Python 版本 |
---|---|
2.2 | 3.5,3.6,3.7,3.8(2.2.8 添加),3.9(2.2.17 添加) |
3.0 | 3.6,3.7,3.8,3.9 (3.0.11 添加) |
3.1 | 3.6,3.7,3.8,3.9(3.1.3 添加) |
3.2 | 3.6, 3.7, 3.8, 3.9, 3.10 (在 3.2.9 中就已经加入了) |
4.0 | 3.8,3.9,3.10 |
#01 如何让你的计算机能够正常的启动django项目
1.计算机的名称不能有中文
2.一个pycharm窗口只开一个项目
3.项目里面所有的文件也尽量不要出现中文
4.python解释器尽量使用3.4~3.6之间的版本
(如果你的项目报错 你点击最后一个报错信息
去源码中把逗号删掉)
#02 django版本问题
python3.6版本
wget https://www.python.org/ftp/python/3.6.8/python-3.6.8-macosx10.9.pkg
pip3 install django==11.11.11
python 3.6
# django安装
pip3 install django==11.11.11
如果已经安装了其他版本 无需自己卸载
直接重新装 会自动卸载安装新的
如果报错 看看是不是timeout 如果是 那么只是网速波动
重新安装即可
验证是否安装成功的方式1
终端输入django-admin看看有没有反应
1.3 启动的两种方式
1)命令行创建
# 命令行操作
# 1.创建django项目
"""
你可以先切换到对应的D盘 然后再创建
"""
django-admin startproject mysite
mysite文件夹
manage.py
mysite文件夹
__init__.py
settings.py
urls.py
wsgi.py
# 2.启动django项目
"""
一定要先切换到项目目录下
cd /mysite
"""
python3 manage.py runserver
# http://127.0.0.1:8000/
# 3.创建应用
"""
Next, start your first app by running python manage.py startapp [app_label].
"""
python manage.py startapp app01
应用名应该做到见名知意
user
order
web
...
但是我们教学统一就用app01/02/03/04
有很多文件
2)pycharm创建
# pycharm操作
# 1 new project 选择左侧第二个django即可
# 2 启动
1.还是用命令行启动
2.点击绿色小箭头即可
# 3 创建应用
1.pycharm提供的终端直接输入完整命令
2.pycharm
tools
run manage.py task提示(前期不要用 给我背完整命令)
# 4 修改端口号以及创建server
edit confi....
3)两种方式的区别
# 1 命令行创建不会自动有templatew文件夹 需要你自己手动创建而pycharm会自动帮你创建并且还会自动在配置文件中配置对应的路径
# pycharm创建
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
]
# 命令行创建
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
]
"""
也就意味着你在用命令创建django项目的时候不单单需要创建templates文件夹还需要去配置文件中配置路径
'DIRS': [os.path.join(BASE_DIR, 'templates')],
"""
1.4 配置文件介绍
-mysite项目文件夹
--mysite文件夹
---settings.py 配置文件
---urls.py 路由与视图函数对应关系(路由层)
---wsgi.py wsgiref模块(不考虑)
--manage.py django的入口文件
--db.sqlite3 django自带的sqlite3数据库(小型数据库 功能不是很多还有bug)
--app01文件夹
---admin.py django后台管理
---apps.py 注册使用
---migrations文件夹 数据库迁移记录
---models.py 数据库相关的 模型类(orm)
---tests.py 测试文件
---views.py 视图函数(视图层)
1.5 创建应用
#01 创建
startapp app02
需要替换配置内: 'DIRS': [os.path.join(BASE_DIR, 'templates')],
bash -cl "/usr/local/bin/python3.6 /Applications/PyCharm.app/Contents/plugins/python/helpers/pycharm/django_manage.py startapp app02 /Users/ningcaichen/PycharmProjects/Djinago/day59"
"""
django是一款专门用来开发app的web框架
django框架就类似于是一所大学(空壳子)
app就类似于大学里面各个学院(具体功能的app)
比如开发淘宝
订单相关
用户相关
投诉相关
创建不同的app对应不同的功能
选课系统
学生功能
老师功能
一个app就是一个独立的功能模块
"""
***********************创建的应用一定要去配置文件中注册**********************
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01.apps.App01Config', # 全写
'app01', # 简写
]
# 创建出来的的应用第一步先去配置文件中注册 其他的先不要给我干
ps:你在用pycharm创建项目的时候 pycharm可以帮你创建一个app并且自动注册
***********************************************************************
二. Django 初步使用
2.1 HttpResponse,render,redirect
"""
HttpResponse
返回字符串类型的数据
HttpResponse('xxx')
render
返回html文件的
def login(request):
return render(request,'login.html')
redirect
重定向
return redirect('https://www.mzitu.com/')
return redirect('/home/') #重定向本项目
"""
2.2 配置静态文件
1)添加路由对应关系 views
### 书写一个登入接口
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
# 登入功能
url(r'^login/', views.login),
]
2)写后端函数功能 urls
from django.shortcuts import render,HttpResponse
# Create your views here.
#01 登入接口
def login(request):
#返回一个页面
return render(request,'login.html')
3)书写登入页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<link rel="stylesheet" href="/static/bootstrap-3.4.1-dist/css/bootstrap.min.css">
<script src="/static/bootstrap-3.4.1-dist/js/bootstrap.min.js"></script>
</head>
<body>
<h1 class="text-center">登入界面</h1>
</body>
</html>
4)配置静态文件
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/
"""
如果你想要访问静态文件 你就必须以static开头
STATIC_URL = '/static/'
令牌正确 则才会在 STATICFILES_DIRS
列表内 寻找对应的文件
令牌错误 直接报错
"""
STATIC_URL = '/static/'
# 添加路径变量 并设置路径
STATICFILES_DIRS = [
os.path.join(BASE_DIR,'static'),
]
5)动态解析
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
{# 动态解析#}
{% load static %}
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<h1 class="text-center">登入界面</h1>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<form action="/login/" method="post" >
<p>username:<input class="form-control" type="text" name="username"></p>
<p>password:<input class="form-control" type="password" name="password"></p>
<input type="submit" class="btn btn-success form-control" value="提交">
</form>
</div>
</div>
</div>
</body>
</html>
# 登陆功能
"""
我们将html文件默认都放在templates文件夹下
我们将网站所使用的静态文件默认都放在static文件夹下
静态文件
前端已经写好了的 能够直接调用使用的文件
网站写好的js文件
网站写好的css文件
网站用到的图片文件
第三方前端框架
...
拿来就可以直接使用的
"""
# django默认是不会自动帮你创建static文件夹 需要你自己手动创建
一般情况下我们在static文件夹内还会做进一步的划分处理
-static
--js
--css
--img
其他第三方文件
"""
在浏览器中输入url能够看到对应的资源
是因为后端提前开设了该资源的借口
如果访问不到资源 说明后端没有开设该资源的借口
http://127.0.0.1:8000/static/bootstrap-3.3.7-dist/css/bootstrap.min.css
"""
# 静态文件配置
"""
****************************************************************
当你在写django项目的时候 可能会出现后端代码修改了但是前端页面没有变化的情况
1.你在同一个端口开了好几个django项目
一直在跑的其实是第一个django项目
2.浏览器缓存的问题
settings
network
disable cache 勾选上
*****************************************************************
"""
STATIC_URL = '/static/' # 类似于访问静态文件的令牌 并非路径
"""如果你想要访问静态文件 你就必须以static开头"""
"""
/static/bootstrap-3.3.7-dist/js/bootstrap.min.js
/static/令牌
取列表里面从上往下依次查找
bootstrap-3.3.7-dist/js/bootstrap.min.js
都没有才会报错
"""
# 静态文件配置
STATICFILES_DIRS = [
os.path.join(BASE_DIR,'static'),
os.path.join(BASE_DIR,'static1'),
os.path.join(BASE_DIR,'static2'),
]
# 静态文件动态解析
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script>
2.3 form表单设置 post请求设置
- form表单默认是get 请求提交
# form表单默认是get请求数据
http://127.0.0.1:8000/login/?username=cdscsd&password=cdscdsc
"""
form表单action参数
1.不写 默认朝当前所在的url提交数据
2.全写 指名道姓
3.只写后缀 /login/
"""
# 在前期我们使用django提交post请求的时候 需要取配置文件中注释掉一行代码
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
- 代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
{# 动态解析#}
{% load static %}
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<h1 class="text-center">登入界面</h1>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<form action="" method="post">
<p>username:<input class="form-control" type="text" name="username"></p>
<p>password:<input class="form-control" type="password" name="password"></p>
<input type="submit" class="btn btn-success form-control" value="提交">
</form>
</div>
</div>
</div>
</body>
</html>
2.4 request对象方法初识
#01 判断请求方式 并且是全大写的字符串形式 <class 'str'>
request.method
#02 POST请求
1)获取用户post请求提交的普通数据不包含文件
request.POST
2)只获取列表最后一个元素
request.POST.get()
3)直接将列表取出
request.POST.getlist()
#03 GET请求
1)获取用户提交的get请求数据
request.GET
2)只获取列表最后一个元素
request.GET.get()
3)直接将列表取出
request.GET.getlist()
-代码
from django.shortcuts import render,HttpResponse
# Create your views here.
#01 登入接口
def login(request):
"""
get和post 请求不同机制处理
:param request:
:return:
"""
if request.method == "POST":
print('post',request.POST)
# 根据字典取值
print(request.POST.get('username'))
# 如果是列表 会取出整个列表,如果是get则会取列表的最后一个值
print(request.POST.getlist)
print(request.POST.getlist('boy'))
return HttpResponse('已经收到了')
return render(request,'login.html')
print(request.POST.getlist)结果:
<QueryDict: {'username': ['zhang'], 'password': ['123'], 'boy': ['111', '222', '333']}>>
print(request.POST.getlist('boy'))结果:
['111', '222', '333']
三. Django ORM数据库操作
3.1 pycharm链接数据库
"""
三个位置查找数据库相关
右侧上方database
左下方database
配置里面的plugins插件搜索安装
再没有卸载pycharm重新装
pycharm可以充当很多款数据库软件的客户端
参考截图和视频操作即可
需要提前创建好库
"""
3.2 Django连接数据库
#01 修改配置文件内数据库连接配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'note',
'USER': 'root',
'PASSWORD': '0x00NF2001',
'HOST': '192.168.5.9',
'PORT': 3306,
'CHARSET': 'utf8'
}
}
#02 代码声明
django默认用的是mysqldb模块链接MySQL
但是该模块的兼容性不好 需要手动改为用pymysql链接
你需要告诉django不要用默认的mysqldb还是用pymysql
# 在项目名下的init或者任意的应用名下的init文件中书写以下代码都可以
import pymysql
pymysql.install_as_MySQLdb()
3.3 创建表结构
"""
ORM. 对象关系映射
作用:能够让一个不用sql语句的小白也能够通过python 面向对象的代码简单快捷的操作数据库
不足之处:封装程度太高 有时候sql语句的效率偏低 需要你自己写SQL语句
类 表
对象 记录
对象属性 记录某个字段对应的值
应用下面的models.py文件
python3 manage.py makemigrations
python3 manage.py migrate
"""
#01 创建表 User表 包括三个字段
class User(models.Model):
"""
CharField必须要指定max_length参数 不指定会直接报错
verbose_name该参数是所有字段都有的 就是用来对字段的解释
"""
# id int primary_key auto_increment
id = models.AutoField(primary_key=True,validators='主键')
# username varchar(32)
username = models.CharField(max_length=32,validators='用户名')
# username int(16)
password = models.IntegerField(validators='密码')
#02 执行数据库迁移命令
1)将操作记录记录到小本本上(migrations文件夹)
python3 manage.py makemigrations
2)将操作真正的同步到数据库中
python3 manage.py migrate
#03 创建author 表,不设置主键 使用ORM 自动添加主键
class Author(models.Model):
"""
由于一张表中必须要有一个主键字段 并且一般情况下都叫id字段
所以orm当你不定义主键字段的时候 orm会自动帮你创建一个名为id主键字段
也就意味着 后续我们在创建模型表的时候如果主键字段名没有额外的叫法 那么主键字段可以省略不写
"""
# username varchar(32)
username = models.CharField(max_length=32,validators='用户名')
# username int(16)
password = models.IntegerField(validators='密码')
- 自动创建主键
- 图示
3.4 字段增删改
#01 字段增加
1) 新增字段 并设置默认值是:default='fufu',也可以设置为空
hobby = models.CharField(max_length=32,validators='测试',default='fufu')
info = models.CharField(max_length=32, validators='测试', default='')
2) 新增字段 并声明该字段可以为 null
error = models.CharField(max_length=32, validators='null', null=True)
#02 字段修改
1)直接在代码内修改即可
原
error = models.CharField(max_length=32, validators='null', null=True)
修改为:
er = models.CharField(max_length=32, validators='null', null=True)
makemigrations
#03 字段删除
直接注释对应的字段然后执行数据库迁移的两条命令即可!
执行完毕之后字段对应的数据也都没有了
"""
在操作models.py的时候一定要细心
千万不要注释一些字段
执行迁移命令之前最好先检查一下自己写的代码
"""
3.5 数据的查询
#01 查询数据
1)引用模块
from app01 import models
2)返回列表套数据对象的格式 这里取索引0 .first()也就是第一个值 filter(username=username)放查询条件
user_obj = models.User.objects.filter(username=username).first()
"""
filter括号内可以携带多个参数 参数与参数之间默认是and关系
"""
3)查看数据,以点索引的方式取值
user_obj.username
user_obj.password
- 用户列表展示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
{# 动态解析#}
{% load static %}
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<h2 class="text-center">用户管理</h2>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<table class="table table-striped table-hover">
<thead >
<tr>
<th>id</th>
<th>username</th>
<th>password</th>
<th>action</th>
</tr>
</thead>
<tbody>
{% for user_obj in user_queryset %}
<tr>
<td>{{ user_obj.id }}</td>
<td>{{ user_obj.username }}</td>
<td>{{ user_obj.password }}</td>
<td>
{# 同网站跳转不需要加http参数,并且问好后面不参与 路径匹配 这里把修改的id 主键添加到参数里##}
<a href="/edit_user/?user_id={{ user_obj.id }}" class="btn btn-primary btn-xs">编辑</a>
<a href="/delete_user/?user_id={{ user_obj.id }}" class="btn btn-danger btn-xs">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="container">
<div class="row"></div>
<div class="col-md-6">
<a href="/create_user/" class="btn btn-success btn-xs pull-right ">新增用户</a>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
- 登入接口代码
#01 登入接口
def login(request):
"""
get和post 请求不同机制处理
:param request:
:return:
"""
#01 POST 进行数据校验
if request.method == "POST":
#01 收到用户提交数据后 开始校验数据
username = request.POST.get('username')
#注意返回值是字符串
password = int(request.POST.get('password'))
#02 从数据库里获取数据,返回一个列表对象,索引0是数据对象
user_obj = models.User.objects.filter(username=username).first()
if user_obj:
#2.1 判断密码是否正确
if user_obj.password == password:
return HttpResponse('登入成功')
else:
return HttpResponse('密码错误 请重新输入')
else:
return HttpResponse('用户名不存在')
return render(request,'login.html')
3.6 数据的增加
"""
user_obj = models.User.objects.create(username=username,password=password)
"""
from app01 import models
#01 增加数据
1)返回值就是当前被创建的对象本身
res = models.User.objects.create(username=username,password=password)
2) 第二种增加
user_obj = models.User(username=username,password=password)
user_obj.save()
代码
#02 注册接口
def register(request):
if request.method == 'POST':
#01 获取用户输入数据
username = request.POST.get('username')
password = request.POST.get('password')
#02 保存到数据库,方式一 推荐方式一
user_obj = models.User.objects.create(username=username,password=password)
#方式2 增加
#user_obj = models.User(username=username,password=password)
#user_obj.save()
return HttpResponse('保存成功')
return render(request,'register.html')
3.7 数据的更新
- views后端功能
"""
语法:
方式1 调用对象的方法修改 推荐
models.User.objects.filter(id=user_id).update(username=username, password=password)
方式2 使用对象变量重新赋值 不推荐 效率慢
edit_obj.username = username
edit_obj.password = password
edit_obj.save()
"""
# 04 编辑用户数据
def edit_user(request):
# 01 获取用户GET方法的数据
user_id = request.GET.get('user_id')
# 02 获取当前查询的对象 往后传参数
edit_obj = models.User.objects.filter(id=user_id).first()
# 03 判断用户的方法是 POST 则获取用户上传数据,并更新到数据库
if request.method == 'POST':
# 2.1 获取用户上传的数据
username = request.POST.get('username')
password = request.POST.get('password')
# 2.2 更新到数据库 (方式一 推荐)
models.User.objects.filter(id=user_id).update(username=username, password=password)
#方式2 对象方式 重新赋值
# edit_obj.username = username
# edit_obj.password = password
# edit_obj.save()
# 2.3 保存完毕后 跳转到展示页面 用户列表
return redirect('/userlist/')
# 数据展示在也页面上 并且将该函数内 所有值打包传入
return render(request, 'edit_user.html', locals())
- html页面 edit_user.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
{# 动态解析#}
{% load static %}
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<h1 class="text-center">修改用户信息</h1>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<form action="" method="post">
#获取对象内的值
<p>username:<input class="form-control" type="text" name="username" value="{{ edit_obj.username }}"></p>
<p>password:<input class="form-control" type="password" name="password" value="{{ edit_obj.password }}"></p>
<input type="submit" class="btn btn-info form-control" value="点击修改">
</form>
</div>
</div>
</div>
</body>
</html>
3.8 删除数据
"""
基本删除语法:
models.User.objects.filter(id=delete_id).delete()
"""
#05 删除用户数据
def delete_user(request):
#01 获取用户ID
delete_id = request.GET.get('user_id')
#02 从数据库里删除
models.User.objects.filter(id=delete_id).delete()
#03 跳转到展示页面
return redirect('/userlist/')
3.9 orm创建表关系
from django.db import models
# Create your models here.
"""
orm中如何定义三种关系
#01 一对多
publish = models.ForeignKey(to='Publish') # 默认就是与出版社表的主键字段做外键关联
#02 多对多
authors = models.ManyToManyField(to='Author')
#03 一对一
author_detail = models.OneToOneField(to='AuthorDetail')
ForeignKey
OneToOneField
会自动在字段后面加_id后缀
"""
#01 出品书籍表
class Book(models.Model):
title =models.CharField(max_length=32,validators='名称')
# 总共8位数 其中小数点后面占2位
price = models.DecimalField(max_digits=8,decimal_places=2,validators='价格')
"""
图书和出版社是一对多 并且书是多的一方 所以外键字段放在书表里面
默认就是与出版社表的主键字段做外键关联 Publish_id -->> Publish 表
"""
publish = models.ForeignKey(to="Publish")
"""
图书和作者是多对多的关系 外键字段建在任意一方均可 但是推荐你建在查询频率较高的一方
authors是一个虚拟字段 主要是用来告诉orm 书籍表和作者表是多对多关系
让orm自动帮你创建第三张关系表
"""
authors = models.ManyToManyField(to="Author")
#02 出版社表
class Publish(models.Model):
name = models.CharField(max_length=32,validators='出版社名称')
addr = models.CharField(max_length=50,validators='出版社地址')
#03 作者表
class Author(models.Model):
name = models.CharField(max_length=32,validators='作者名称')
age = models.IntegerField(validators='年龄')
"""
作者与作者详情是一对一的关系 外键字段建在任意一方都可以 但是推荐你建在查询频率较高的表中
OneToOneField也会自动给字段加_id后缀
"""
author_detail = models.OneToOneField(to="AuthorDetail")
#04 作者详情表
class AuthorDetail(models.Model):
phone = models.BigIntegerField() #存储11位int
addr = models.CharField(max_length=50,validators='作者地址')
四. Django 请求生命周期
"""
用户访问浏览器
1. 首先经过 wsgi web服务网关接口
2. 经过中间件,看是否有数据 没有数据继续往路由层发起请求
3. urls.py 路由层根据url进行匹配 继续找到视图功能层
4. 视图层 views.py 根据路由处理逻辑 返回对应的 ?html页面 templates,获取通过 models.py连接数据库
"""
五. Djiango 路由层
5.1 路由匹配
#01 路由匹配
url(r'test',views.test),
url(r'testadd',views.testadd)
"""
url方法第一个参数是正则表达式
只要第一个参数正则表达式能够匹配到内容 那么就会立刻停止往下匹配
直接执行对应的视图函数
你在输入url的时候会默认加斜杠
django内部帮你做到重定向
一次匹配不行
url后面加斜杠再来一次
"""
#02 取消自动加斜杠
APPEND_SLASH = False/True # 默认是自动加斜杠的
#03 代码
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
#01 首页 url后面无内容 会匹配以下内容
url(r'^$', views.index),
#02 相同的前缀匹配 固定前缀和后缀
url(r'^test/$',views.test),
url(r'^testadd/$',views.testadd),
#03 什么都没有匹配到 默认走这个 由于从上而下匹配 所以放在最下面
url(r'', views.error),
]
5.2 无名分组
- 分组是 路由层-->用来传参数--->给视图层
"""
分组:就是给某一段正则表达式用小括号扩起来
分组是 路由层用来传参数给视图层
"""
#01 无名分组可以写多个
url(r'^test/(\d+)/',views.test)
url(r'^unknown/(\d+)/(\d+)/',views.unknown),
1)单个分组
def test(request,xx):
print(xx)
return HttpResponse('test')
2)多个分组
def unknown(request,*args):
print(args)
return HttpResponse(f'无名分组{args}')
# 无名分组就是将括号内正则表达式匹配到的内容当作位置参数传递给后面的视图函数
('123', '32343')
5.3 有名分组
- 分组是 路由层-->用来传参数--->给视图层
"""
可以给正则表达式起一个别名
"""
#01 有名分组 (可以多个有名分组)
url(r'^testadd/(?P<year>\d+)',views.testadd)
url(r'^name/(?P<year>\d+)/(?P<year1>\d+)/(?P<year2>\d+)/',views.name),
1) 单个分组
def testadd(request,year):
print(year)
return HttpResponse('testadd')
2)多个分组
def name(request,**kwargs):
print(kwargs)
return HttpResponse(f'有名分组{kwargs}')
结果:
{'year': '123'}
{'year': '123', 'year1': '32343', 'year2': '34'}
# 有名分组就是将括号内正则表达式匹配到的内容当作关键字参数传递给后面的视图函数
5.4 反向解析
- 给路由层 URL 起个别名 ---视图层和前端页面可以获取
# 通过一些方法得到一个结果 该结果可以直接访问对应的url触发视图函数
# 先给路由与视图函数起一个别名
#01 视图
url(r'^func_ccccccccc/', views.func,name='xxx'),
#02 反向解析
1)后端反向解析
from django.shortcuts import render,HttpResponse,redirect,reverse
reverse('ooo')
2)前端反向解析
<a href="{% url 'xxx' %}">111</a>
根据url名称 动态解析
5.5 无名分组有名分组->反向解析
1)无名分组反向解析
"""
通过别名方式 让视图层和前端获取该url名称+参数
无名分组反向解析
url(r'^index/(\d+)/',views.index,name='xxx')
前端
{% url 'xxx' 123 %}
后端
reverse('xxx', args=(1,))
这个数字写代码的时候应该放什么
数字一般情况下放的是数据的主键值 数据的编辑和删除
url(r'^edit/(\d+)/',views.edit,name='xxx')
def edit(request,edit_id):
reverse('xxx',args=(edit_id,))
{%for user_obj in user_queryset%}
<a href="{% url 'xxx' user_obj.id %}">编辑</a>
{%endfor%}
"""
案例--
#01 路由层
urlpatterns = [
url(r'^admin/', admin.site.urls),
#首页
url(r'^$',views.home),
# 无名分组反向解析
url(r'^index/(\d+)/',views.index,name='xxx'),
]
#02 视图层
from django.shortcuts import render,HttpResponse,reverse
def index(request,args):
return HttpResponse('index')
def home(request):
# args=(10,) 这里一般放修改数据的 主键值
print(reverse('xxx',args=(10,)))
return render(request,'home.html')
#03 前端页面获取反向解析
<a href="{% url 'xxx' 1 %}">111</a>
2)有名分组反向解析
"""
# 有名分组反向解析
url(r'^func/(?P<year>\d+)/',views.func,name='ooo')
# 前端
<a href="{% url 'ooo' year=123 %}">111</a> 了解
<a href="{% url 'ooo' 123 %}">222</a> 记忆
# 后端
# 有名分组反向解析 写法1 了解
print(reverse('ooo',kwargs={'year':123}))
# 简便的写法 减少你的脑容量消耗 记跟无名一样的操作即可
print(reverse('ooo',args=(111,)))
"""
5.6 路由分发
"""
django的每一个应用都可以有自己的templates文件夹 urls.py static文件夹
正是基于上述的特点 django能够非常好的做到分组开发(每个人只写自己的app)
作为组长 只需要将手下书写的app全部拷贝到一个新的django项目中 然后在配置文件里面注册所有的app再利用路由分发的特点将所有的app整合起来
当一个django项目中的url特别多的时候 总路由urls.py代码非常冗余不好维护
这个时候也可以利用路由分发来减轻总路由的压力
利用路由分发之后 总路由不再干路由与视图函数的直接对应关系
而是做一个分发处理
识别当前url是属于哪个应用下的 直接分发给对应的应用去处理
"""
#01 总路由
from app01 import urls as app01_urls
from app02 import urls as app02_urls
urlpatterns = [
url(r'^admin/', admin.site.urls),
# 1.路由分发
url(r'^app01/',include(app01_urls)), # 只要url前缀是app01开头 全部交给app01处理
url(r'^app02/',include(app02_urls)) # 只要url前缀是app02开头 全部交给app02处理
# 2.终极写法 推荐使用 这种写法上方的 as app01_urls 不需要的
url(r'^app01/',include('app01.urls')),
url(r'^app02/',include('app02.urls'))
# 注意事项:总路由里面的url千万不能加$结尾
]
#02 字路由
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^reg/', views.reg)
]
from django.conf.urls import url
from app02 import views
urlpatterns = [
url(r'^reg/', views.reg)
]
5.7 名称空间
# 当多个应用出现了相同的别名 我们研究反向解析会不会自动识别应用前缀
"""
正常情况下的反向解析是没有办法自动识别前缀的
"""
# 名称空间
# 总路由
url(r'^app01/',include('app01.urls',namespace='app01')),
url(r'^app02/',include('app02.urls',namespace='app02'))
# 解析的时候
# app01
urlpatterns = [
url(r'^reg/',views.reg,name='reg')
]
# app02
urlpatterns = [
url(r'^reg/',views.reg,name='reg')
]
reverse('app01:reg')
reverse('app02:reg')
{% url 'app01:reg' %}
{% url 'app02:reg' %}
# 其实只要保证名字不冲突 就没有必要使用名称空间
"""
一般情况下 有多个app的时候我们在起别名的时候会加上app的前缀
这样的话就能够确保多个app之间名字不冲突的问题
"""
urlpatterns = [
url(r'^reg/',views.reg,name='app01_reg')
]
urlpatterns = [
url(r'^reg/',views.reg,name='app02_reg')
]
5.8 伪静态
"""
静态网页
数据是写死的 万年不变
伪静态
将一个动态网页伪装成静态网页
为什么要伪装呢?
https://www.cnblogs.com/Dominic-Ji/p/9234099.html
伪装的目的在于增大本网站的seo查询力度
并且增加搜索引擎收藏本网上的概率
搜索引擎本质上就是一个巨大的爬虫程序
总结:
无论你怎么优化 怎么处理
始终还是干不过RMB玩家
"""
urlpatterns = [
url(r'^reg.html',views.reg,name='app02_reg')
]
5.9 虚拟环境
"""
在正常开发中 我们会给每一个项目配备一个该项目独有的解释器环境
该环境内只有该项目用到的模块 用不到一概不装
linux:缺什么才装什么
虚拟环境
你每创建一个虚拟环境就类似于重新下载了一个纯净的python解释器
但是虚拟环境不要创建太多,是需要消耗硬盘空间的
扩展:
每一个项目都需要用到很多模块 并且每个模块版本可能还不一样
那我该如何安装呢? 一个个看一个个装???
开发当中我们会给每一个项目配备一个requirements.txt文件
里面书写了该项目所有的模块即版本
你只需要直接输入一条命令即可一键安装所有模块即版本
"""
六. django版本区别
"""
1.django1.X路由层使用的是url方法
而在django2.Xhe3.X版本中路由层使用的是path方法
url()第一个参数支持正则
path()第一个参数是不支持正则的 写什么就匹配什么
如果你习惯使用path那么也给你提供了另外一个方法
from django.urls import path, re_path
from django.conf.urls import url
re_path(r'^index/',index),
url(r'^login/',login)
2.X和3.X里面的re_path就等价于1.X里面的url
2.虽然path不支持正则 但是它的内部支持五种转换器
path('index/<int:id>/',index)
# 将第二个路由里面的内容先转成整型然后以关键字的形式传递给后面的视图函数
def index(request,id):
print(id,type(id))
return HttpResponse('index')
str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
int,匹配正整数,包含0。
slug,匹配字母、数字以及横杠、下划线组成的字符串。
uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
path,匹配任何非空字符串,包含了路径分隔符(/)(不能用?)
3.除了有默认的五个转换器之外 还支持自定义转换器(了解)
class MonthConverter:
regex='\d{2}' # 属性名必须为regex
def to_python(self, value):
return int(value)
def to_url(self, value):
return value # 匹配的regex是两个数字,返回的结果也必须是两个数字
from django.urls import path,register_converter
from app01.path_converts import MonthConverter
# 先注册转换器
register_converter(MonthConverter,'mon')
from app01 import views
urlpatterns = [
path('articles/<int:year>/<mon:month>/<slug:other>/', views.article_detail, name='aaa'),
]
4.模型层里面1.X外键默认都是级联更新删除的
但是到了2.X和3.X中需要你自己手动配置参数
models.ForeignKey(to='Publish')
models.ForeignKey(to='Publish',on_delete=models.CASCADE...)
"""
标签:username,views,models,request,django,初步,url,使用,Django
From: https://www.cnblogs.com/saas-open/p/17986477