Django
官方文档:https://docs.djangoproject.com/zh-hans/5.0/ref/request-response/#django.http.HttpRequest
安装python
# 安装依赖
yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel libffi-devel gcc
wget https://www.python.org/ftp/python/3.8.15/Python-3.8.15.tgz
tar xf Python-3.8.15.tar.xz
cd Python-3.8.15
./configure --prefix=/usr/local/python3
make && make install
# 删除旧软链接
rm -rf /usr/bin/python3
rm -rf /usr/bin/pip3
# 新添加软链接
ln -s /usr/local/python3/bin/python3.8 /usr/bin/python3
ln -s /usr/local/python3/bin/pip3.8 /usr/bin/pip3
# 修改yum运行环境
vi /usr/bin/yum
vi /usr/libexec/urlgrabber-ext-down
按i进入编辑模式,在第一行
#!/usr/bin/python把修改为#!/usr/bin/python2.7
pip加速
cd ~
mkdir .pip
vi .pip/pip.conf
# 增加如下内容
[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
[install]
trusted-host = pypi.tuna.tsinghua.edu.cn
安装Django
pip3 install django
# 新版跟老版不太一样,需要自己设置软链接
ln -s /usr/local/python3/bin/django-admin /usr/bin/django-admin
# 创建web项目: django-admin startproject 项目名称
django-admin startproject myweb
# Django项目目录
web
├── db.sqlite3
├── manage.py # 项目的管理,包括: 启动项目,创建app, 数据管理
└── web
├── asgi.py # 接收网络请求
├── __init__.py
├── settings.py # 项目配置(模板配置,数据库配置,注册app)
├── urls.py # url和函数的对应关系
└── wsgi.py # 接收网络请求
# 添加新的app
cd myweb;django-admin startapp blog
cd myweb;python manage.py startapp blog
# app目录
blog/
├── admin.py # 映射models中的数据到Django自带的admin后台
├── apps.py # 在新的Django版本中新增,用于应用程序的配置
├── __init__.py
├── migrations # 用于记录models中数据的变更记录
│ └── __init__.py
├── models.py # 创建应用程序数据表模型(对应数据库的相关操作)
├── tests.py # 创建Django测试
└── views.py # 控制向前端显示那些数据
# app注册
vi myweb/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog.apps.BlogConfig', # 或直接appname blog
]
快速上手
- 编辑myweb/blog 下的views.py 视图函数
from django.shortcuts import render from django.http import HttpResponse def index_app(req): return HttpResponse('welcome to Django blog!')
-
编辑myweb/web 下的urls.py 来指定访问路由
from django.contrib import admin from django.urls import path from blog.views import index_app urlpatterns = [ path('admin/', admin.site.urls), path('index_app/', views.index_app), ]
-
命令行启动Django应用
cd myweb/ python manage.py runserver python3 manage.py runserver 0.0.0.0:8888 # windows cd myweb/ python manage.py runserver python.exe manage.py runserver 0.0.0.0:8888 # 报错 You have 18 unapplied migration(s) python.exe manage.py migrate
templates模板
为了使用HTML,这里开始引入templates模板
注意: 可以在app下创建templates目录,也可以在主目录下创建templates目录
如果 setting.py 配置TEMPLATES DIRS: [os.path.join(BASE_DIR, 'templates')] 会从项目根目录templates寻找html
如果没有配置DIRS,则根据app的注册顺序,在每个app下的templates目录中寻找
图片、js、css 静态文件需放在app目录下的static目录,可以修改setting.py里STATIC_URL配置
Django html 静态文件引入:
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>user_list</title>
{% load static %}
<link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1/css/bootstrap.min.css' %}" />
</head>
<body>
<h1>用户列表 new</h1>
<img src="{% static 'img/haha.png' %}" style="height: 200px;" alt="" />
<script src="{% static 'js/jquery-3.7.1.min.js' %}"></script>
<script src="{% static 'plugins/bootstrap-3.4.1/js/bootstrap.min.js' %}"></script>
</body>
</html>
单一变量
def tpl(request):
name = "poker"
return render(request, "tpl.html", {"name":name})
<body>
<h1>templates模板语法</h1>
<li>姓名: {{ name }}</li>
</body>
列表
def tpl(request):
name = "tpl模板语法学习"
my_list = ['好好', '学习', '天天', '向上']
return render(request, "tpl.html", {"name":name, "roles_list":roles_list})
<body>
<h1>templates模板语法</h1>
<h2 class="btn btn-lg">{{ name }}</h2>
<div>
<h3> 列表 my_list </h3>
<li>{{ my_list }}</li>
<li>{{ my_list.0 }}</li>
<li>{{ my_list.1 }}</li>
<li>{{ my_list.2 }}</li>
<li>{{ my_list.3 }}</li>
</div>
</body>
- 循环(列表)
<body>
<div>
{% for item in my_list %}
<span>{{ item }}</span>
{% endfor %}
</div>
</body>
字典
def tpl(req):
name = "tpl模板语法学习"
my_list = ['好好', '学习', '天天', '向上']
my_dict = {"name": "tang", "age": 18}
return render(req, "tpl.html", {"name": name, "my_list": my_list, "my_dict": my_dict})
<div>
<h3> 字典 my_dict </h3>
{{ my_dict.name }}
{{ my_dict.age }}
<h4>字典 for 循环</h4>
{% for k in my_dict.keys %}
<li>{{ k }}</li>
{% endfor %}
{% for v in my_dict.values %}
<li>{{ v }}</li>
{% endfor %}
{% for k,v in my_dict.items %}
<li>{{ k }}: {{ v }}</li>
{% endfor %}
</div>
列表套字典
def tpl(req):
name = "tpl模板语法学习"
my_list = ['好好', '学习', '天天', '向上']
my_dict = {"name": "tang", "age": 18}
data_list = [
{"name": "张三", "age": 25, "sex": "男"},
{"name": "李四", "age": 18, "sex": "男"},
{"name": "王五", "age": 22, "sex": "女"},
]
return render(req, "tpl.html", {"name": name, "my_list": my_list, "my_dict": my_dict, "data_list": data_list})
<div>
<h3>列表套字典</h3>
<div>
{{ data_list.1.name }}
{{ data_list.1.age }}
{{ data_list.1.sex }}
<h3>列表套字典for循环</h3>
{% for item in data_list %}
<div>{{ item.name }} {{ item.age }} {{ item.sex }}</div>
{% endfor %}
</div>
</div>
条件判断
{% if name == "poker" %}
<h3>嘿嘿嘿</h3>
{% elif name == "toker" %}
<h3>哈哈哈</h3>
{% else %}
<h3>呵呵呵</h3>
{% endif %}
templates 模板语法案例
def news(req):
import requests
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0"
}
r = requests.get(
"http://ccdb.hemiola.com/characters/radicals/85", headers=headers)
data_list = r.json()
# print(data_list)
# print(r.status_code)
# print(r.headers['content-type'])
# print(r.text)
return render(req, 'news.html', {"data_list": data_list})
<div class="container-fluid haha">
<hr></hr>
<h3>data_list</h3>
<ul>
{% for items in data_list %}
<li>{{ items.string }}</li>
{% endfor %}
</ul>
</div>
请求、响应、重定向
浏览器向某个网站发送请求,网站返回给浏览器一个新的URL,浏览器去访问这个新的URL地址
def something(req):
# req 是一个对象,封闭了用户发送过来的所有请求相关数据
# 获取用户请求方式
print(req.method)
# 获取URL上传递的值 /something/?n1=888&n2=999
print(req.GET) # <QueryDict: {'n1': ['888'], 'n2': ['999']}>
# 通过请求体中提交数据
print(req.POST)
# [响应] 内容字符串内容返回给请求者
# return HttpResponse("hahaha")
# [响应] 读取HTML的内容 + 渲染(替换) --> 字符串,返回给用户浏览器
# return render(req, 'something.html', {'title': "something"})
# [响应] 让浏览器重定向到其他页面
return redirect("https://baidu.com")
案例: 用户登录
def login(req):
if req.method == "GET":
return render(req, 'login.html')
else:
# 如果是POST请求,获取用户提交的数据
print(req.POST)
data_dict = req.POST
user = data_dict["user"]
password = data_dict["password"]
print(user,password)
if user == "tang" and password == "123":
return HttpResponse("登录成功!")
else:
#return HttpResponse("登录失败")
return render(req, "login.html", {"error_msg": "用户名或密码错误"})
<div class="container-fluid haha">
<hr></hr>
<h1>用户登录</h1>
<form method="post" action="/login/">
<!-- Django访问token校验 -->
{% csrf_token %}
<input type="text" name="user", placeholder="用户名">
<input type="password" name="password", placeholder="密码">
<input type="submit" value="提交">
<span style="color: red;">{{ error_msg }}</span>
</form>
</div>
数据库操作
Django开发操作数据库更简单,内部提供了ORM框架
-
ORM可以帮助我们做两件事:
- 创建/修改/删除数据库中的表(不用写sql语句,但无法创建数据库)
- 操作表中的数据(不用写sql语句)
-
环境:
- yum -y install mysql-devel
- yum -y install python-devel
- pip3 install mysqlclient
- 修改setting.py 配置数据连接参数
DATABASES = {
'default':{
'ENGINE':'django.db.backends.mysql',
'NAME':'py_sql',
'USER':'xxxx',
'PASSWORD':'xxxx',
'HOST':'home.vimll.com',
'PORT':xxxx,
}
}
- 创建表 修改models.py 增加所创建表相关数据
class UserInfo(models.Model):
name = models.CharField(max_length=32)
password = models.CharField(max_length=64)
age = models.IntegerField()
info = models.CharField(max_length=64, default="0")
# test = models.IntegerField(default=0) # 注释后 运行命名后删除该字段
# data = models.IntegerField(null=True,blank=True)
"""上述类会自动生成sql语句
create table blog_UserInfo( # 默认会在表名前面加上app name
id bigint auto_increment primary key,
name varchar(20),
password varchar(20),
age int
)
"""
class UserInfo(models.Model):
class Meta:
db_table = 'UserInfo' # 则表名不加app name 表名为:UserInfo
-
创建库表(进入工程目录):库表名makemigrations
- python manage.py makemigrations
-
执行库表建立(进入工程目录):
- python manage.py migrate
-
修改表的话,如果原表中存有数据,此时如果增加一个新的列,需要设定一个默认值
- 手动设定 age = models.IntegerField(default=2)
- 允许为空 data = models.IntegerField(null=True, blank=True)
-
使用已存在的库表,反向生成models.py
- python manage.py inspectdb [表名] # 不写表名默认生成所有表
Django models 参数
建表字段参数
1、models.AutoField 自增列 = int(11)
如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。
2、models.CharField 字符串字段
必须 max_length 参数
3、models.BooleanField 布尔类型=tinyint(1)
不能为空,Blank=True
4、models.ComaSeparatedIntegerField 用逗号分割的数字=varchar
继承CharField,所以必须 max_lenght 参数
5、models.DateField 日期类型 date
对于参数,auto_now = True 则每次更新都会更新这个时间;auto_now_add 则只是第一次创建添加,之后的更新不再改变。
6、models.DateTimeField 日期类型 datetime
同DateField的参数
7、models.Decimal 十进制小数类型 = decimal
必须指定整数位max_digits和小数位decimal_places
8、models.EmailField 字符串类型(正则表达式邮箱) =varchar
对字符串进行正则表达式
9、models.FloatField 浮点类型 = double
10、models.IntegerField 整形
11、models.BigIntegerField 长整形
integer_field_ranges = {
‘SmallIntegerField‘: (-32768, 32767),
‘IntegerField‘: (-2147483648, 2147483647),
‘BigIntegerField‘: (-9223372036854775808, 9223372036854775807),
‘PositiveSmallIntegerField‘: (0, 32767),
‘PositiveIntegerField‘: (0, 2147483647),
}
12、models.IPAddressField 字符串类型(ip4正则表达式)
13、models.GenericIPAddressField 字符串类型(ip4和ip6是可选的)
参数protocol可以是:both、ipv4、ipv6
验证时,会根据设置报错
14、models.NullBooleanField 允许为空的布尔类型
15、models.PositiveIntegerFiel 正Integer
16、models.PositiveSmallIntegerField 正smallInteger
17、models.SlugField 减号、下划线、字母、数字
18、models.SmallIntegerField 数字
数据库中的字段有:tinyint、smallint、int、bigint
19、models.TextField 字符串=longtext
20、models.TimeField 时间 HH:MM[:ss[.uuuuuu]]
21、models.URLField 字符串,地址正则表达式
22、models.BinaryField 二进制
23、models.ImageField 图片
24、models.FilePathField 文件
字段传参
1、null=True
数据库中字段是否可以为空
2、blank=True
django的 Admin 中添加数据时是否可允许空值
3、primary_key = False
主键,对AutoField设置主键后,就会代替原来的自增 id 列
4、auto_now 和 auto_now_add
auto_now 自动创建---无论添加或修改,都是当前操作的时间
auto_now_add 自动创建---永远是创建时的时间
5、choices
GENDER_CHOICE = (
(u‘M‘, u‘Male‘),
(u‘F‘, u‘Female‘),
)
gender = models.CharField(max_length=2,choices = GENDER_CHOICE)
6、max_length
7、default 默认值
8、verbose_name Admin中字段的显示名称
9、name|db_column 数据库中的字段名称
10、unique=True 不允许重复
11、db_index = True 数据库索引
12、editable=True 在Admin里是否可编辑
13、error_messages=None 错误提示
14、auto_created=False 自动创建
15、help_text 在Admin中提示帮助信息
16、validators=[]
17、upload-to
Django操作表数据
-
添加数据
def orm(req): # 测试ORM操作表中的数据 # 表新建数据 UserInfo.objects.create(name="tang", password="123", age=18, info="haha") UserInfo.objects.create(name="tang2", password="1234", age=18, info="haha2") UserInfo.objects.create(name="tang3", password="1235", age=18, info="haha3") return HttpResponse("哈哈哈")
- 删除数据
# 删除数据 # UserInfo.objects.all().delete() # 清空表 UserInfo.objects.filter(id=3).delete()
-
获取数据
# 获取数据 data_list = UserInfo.objects.all() # print(data_list) # <QuerySet [<UserInfo: UserInfo object (1)>, <UserInfo: UserInfo object (2)>]> for obj in data_list: print(obj.id, obj.name, obj.password, obj.age, obj.info) # 获取一条数据 row_obj = UserInfo.objects.filter(id=2).first() # 拿到一行数据 # print(row_obj) # UserInfo object (2) print(row_obj.id, row_obj.name, row_obj.password, row_obj.age, row_obj.info)
- 更新数据
# 更新数据 UserInfo.objects.all().update(info="哈哈") # 更新所有行数据 # 更新所筛选的数据 UserInfo.objects.filter(id=2).update(info="哈哈哈",password="123456")
案例-用户管理
用户列表
# urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('index_app/', index_app),
path('user_list/', user_list),
path('user_add/', user_add),
path('', tpl),
path('news/', news),
path('something/', something),
path('login/', login),
path('orm/', orm),
# 案例 用户列表
path('info_list/', info_list),
]
# views.py
def info_list(req):
info_list = UserInfo.objects.all()
return render(req,'info_list.html',{"info_list": info_list})
<!-- info_list.html -->
<h3>info_list用户列表</h3>
<table border="1">
<thead>
<tr>
<th>ID</th>
<th>姓名</th>
<th>密码</th>
<th>年龄</th>
<th>备注</th>
</tr>
</thead>
<tbody>
{% for items in info_list %}
<tr>
<td>{{ items.id }}</td>
<td>{{ items.name }}</td>
<td>{{ items.password }}</td>
<td>{{ items.age }}</td>
<td>{{ items.info }}</td>
</tr>
{% endfor %}
</tbody>
</table>
添加用户
def info_add(req):
if req.method == "GET":
return render(req, 'info_add.html')
else:
# 如果是POST请求,获取用户提交的数据
# print(req.POST)
data_dict = req.POST
name = data_dict["name"]
password = data_dict["password"]
age = data_dict["age"]
info = data_dict["info"]
print(name, password, age, info)
UserInfo.objects.create(name=name, password=password, age=age, info=info)
# return redirect("http://127.0.0.1:8000/info_list/")
return redirect("/info_list/")
<h1>info_add添加用户</h1>
<form method="post" action="/info_add/">
{% csrf_token %}
<input type="text" name="name", placeholder="用户名">
<input type="password" name="password", placeholder="密码">
<input type="number" name="age", placeholder="年龄">
<input type="text" name="info", placeholder="备注">
<input type="submit" value="提交">
<span style="color: red;">{{ error_msg }}</span>
</form>
删除用户
def info_del(req):
nid = req.GET.get("nid")
print(nid)
UserInfo.objects.filter(id=nid).delete()
return redirect("/info_list/")
<table border="1" style="margin-top: 20px;">
<thead>
<tr>
<th>ID</th>
<th>姓名</th>
<th>密码</th>
<th>年龄</th>
<th>备注</th>
<th>用户操作</th>
</tr>
</thead>
<tbody>
{% for items in info_list %}
<tr>
<td>{{ items.id }}</td>
<td>{{ items.name }}</td>
<td>{{ items.password }}</td>
<td>{{ items.age }}</td>
<td>{{ items.info }}</td>
<td><a href="/info_del/?nid={{ items.id }}">删除</a></td>
</tr>
{% endfor %}
</tbody>
</table>