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 安装版本
https://www.django.cn/
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 |
1.计算机的名称不能有中文
2.一个pycharm窗口只开一个项目
3.项目里面所有的文件也尽量不要出现中文
4.python解释器尽量使用3.4~3.6之间的版本
(如果你的项目报错 你点击最后一个报错信息
去源码中把逗号删掉)
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
pip3 install django==11.11.11
如果已经安装了其他版本 无需自己卸载
直接重新装 会自动卸载安装新的
如果报错 看看是不是timeout 如果是 那么只是网速波动
重新安装即可
验证是否安装成功的方式1
终端输入django-admin看看有没有反应
1.3 启动的两种方式
1)命令行创建
"""
你可以先切换到对应的D盘 然后再创建
"""
django-admin startproject mysite
mysite文件夹
manage.py
mysite文件夹
__init__.py
settings.py
urls.py
wsgi.py
"""
一定要先切换到项目目录下
cd /mysite
"""
python3 manage.py runserver
"""
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创建
1.还是用命令行启动
2.点击绿色小箭头即可
1.pycharm提供的终端直接输入完整命令
2.pycharm
tools
run manage.py task提示(前期不要用 给我背完整命令)
edit confi....
3)两种方式的区别
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 创建应用
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
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开头
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文件
网站用到的图片文件
第三方前端框架
...
拿来就可以直接使用的
"""
一般情况下我们在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请求设置
http://127.0.0.1:8000/login/?username=cdscsd&password=cdscdsc
"""
form表单action参数
1.不写 默认朝当前所在的url提交数据
2.全写 指名道姓
3.只写后缀 /login/
"""
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'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对象方法初识
request.method
1)获取用户post请求提交的普通数据不包含文件
request.POST
2)只获取列表最后一个元素
request.POST.get()
3)直接将列表取出
request.POST.getlist()
1)获取用户提交的get请求数据
request.GET
2)只获取列表最后一个元素
request.GET.get()
3)直接将列表取出
request.GET.getlist()
-代码
from django.shortcuts import render,HttpResponse
def login(request):
"""
get和post 请求不同机制处理
:param request:
:return:
"""
if request.method == "POST":
print('post',request.POST)
print(request.POST.get('username'))
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连接数据库
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'note',
'USER': 'root',
'PASSWORD': '0x00NF2001',
'HOST': '192.168.5.9',
'PORT': 3306,
'CHARSET': 'utf8'
}
}
django默认用的是mysqldb模块链接MySQL
但是该模块的兼容性不好 需要手动改为用pymysql链接
你需要告诉django不要用默认的mysqldb还是用pymysql
import pymysql
pymysql.install_as_MySQLdb()
3.3 创建表结构
"""
ORM. 对象关系映射
作用:能够让一个不用sql语句的小白也能够通过python 面向对象的代码简单快捷的操作数据库
不足之处:封装程度太高 有时候sql语句的效率偏低 需要你自己写SQL语句
类 表
对象 记录
对象属性 记录某个字段对应的值
应用下面的models.py文件
python3 manage.py makemigrations
python3 manage.py migrate
"""
class User(models.Model):
"""
CharField必须要指定max_length参数 不指定会直接报错
verbose_name该参数是所有字段都有的 就是用来对字段的解释
"""
id = models.AutoField(primary_key=True,validators='主键')
username = models.CharField(max_length=32,validators='用户名')
password = models.IntegerField(validators='密码')
1)将操作记录记录到小本本上(migrations文件夹)
python3 manage.py makemigrations
2)将操作真正的同步到数据库中
python3 manage.py migrate
class Author(models.Model):
"""
由于一张表中必须要有一个主键字段 并且一般情况下都叫id字段
所以orm当你不定义主键字段的时候 orm会自动帮你创建一个名为id主键字段
也就意味着 后续我们在创建模型表的时候如果主键字段名没有额外的叫法 那么主键字段可以省略不写
"""
username = models.CharField(max_length=32,validators='用户名')
password = models.IntegerField(validators='密码')


3.4 字段增删改
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)
1)直接在代码内修改即可
原
error = models.CharField(max_length=32, validators='null', null=True)
修改为:
er = models.CharField(max_length=32, validators='null', null=True)
makemigrations
直接注释对应的字段然后执行数据库迁移的两条命令即可!
执行完毕之后字段对应的数据也都没有了
"""
在操作models.py的时候一定要细心
千万不要注释一些字段
执行迁移命令之前最好先检查一下自己写的代码
"""
3.5 数据的查询
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>
def login(request):
"""
get和post 请求不同机制处理
:param request:
:return:
"""
if request.method == "POST":
username = request.POST.get('username')
password = int(request.POST.get('password'))
user_obj = models.User.objects.filter(username=username).first()
if user_obj:
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
1)返回值就是当前被创建的对象本身
res = models.User.objects.create(username=username,password=password)
2) 第二种增加
user_obj = models.User(username=username,password=password)
user_obj.save()
代码
def register(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user_obj = models.User.objects.create(username=username,password=password)
return HttpResponse('保存成功')
return render(request,'register.html')
3.7 数据的更新
"""
语法:
方式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()
"""
def edit_user(request):
user_id = request.GET.get('user_id')
edit_obj = models.User.objects.filter(id=user_id).first()
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
models.User.objects.filter(id=user_id).update(username=username, password=password)
return redirect('/userlist/')
return render(request, 'edit_user.html', locals())
<!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()
"""
def delete_user(request):
delete_id = request.GET.get('user_id')
models.User.objects.filter(id=delete_id).delete()
return redirect('/userlist/')

3.9 orm创建表关系
from django.db import models
"""
orm中如何定义三种关系
#01 一对多
publish = models.ForeignKey(to='Publish') # 默认就是与出版社表的主键字段做外键关联
#02 多对多
authors = models.ManyToManyField(to='Author')
#03 一对一
author_detail = models.OneToOneField(to='AuthorDetail')
ForeignKey
OneToOneField
会自动在字段后面加_id后缀
"""
class Book(models.Model):
title =models.CharField(max_length=32,validators='名称')
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")
class Publish(models.Model):
name = models.CharField(max_length=32,validators='出版社名称')
addr = models.CharField(max_length=50,validators='出版社地址')
class Author(models.Model):
name = models.CharField(max_length=32,validators='作者名称')
age = models.IntegerField(validators='年龄')
"""
作者与作者详情是一对一的关系 外键字段建在任意一方都可以 但是推荐你建在查询频率较高的表中
OneToOneField也会自动给字段加_id后缀
"""
author_detail = models.OneToOneField(to="AuthorDetail")
class AuthorDetail(models.Model):
phone = models.BigIntegerField()
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 路由匹配
url(r'test',views.test),
url(r'testadd',views.testadd)
"""
url方法第一个参数是正则表达式
只要第一个参数正则表达式能够匹配到内容 那么就会立刻停止往下匹配
直接执行对应的视图函数
你在输入url的时候会默认加斜杠
django内部帮你做到重定向
一次匹配不行
url后面加斜杠再来一次
"""
APPEND_SLASH = False/True
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.index),
url(r'^test/$',views.test),
url(r'^testadd/$',views.testadd),
url(r'', views.error),
]
5.2 无名分组
"""
分组:就是给某一段正则表达式用小括号扩起来
分组是 路由层用来传参数给视图层
"""
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 有名分组
"""
可以给正则表达式起一个别名
"""
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(r'^func_ccccccccc/', views.func,name='xxx'),
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%}
"""
案例--
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$',views.home),
url(r'^index/(\d+)/',views.index,name='xxx'),
]
from django.shortcuts import render,HttpResponse,reverse
def index(request,args):
return HttpResponse('index')
def home(request):
print(reverse('xxx',args=(10,)))
return render(request,'home.html')
<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是属于哪个应用下的 直接分发给对应的应用去处理
"""
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))
url(r'^app01/',include('app01.urls')),
url(r'^app02/',include('app02.urls'))
]
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'))
urlpatterns = [
url(r'^reg/',views.reg,name='reg')
]
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...)
"""
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~