django
django学习
初识Django
- Python知识点:函数、面向对象。
- 前端开发:HTML、CSS、JavaScript、jQuery、BootStrap。
- MySQL数据库。
- Python的Web框架:
- Flask,自身短小精悍 + 第三方组件。
- Django,内部已集成了很多组件 + 第三方组件。【主要】
1.安装django
pip install django
c:\python39
- python.exe
- Scripts
- pip.exe
- django-admin.exe 【工具,创建django项目中的文件和文件夹】
- Lib
- 内置模块
- site-packages
- openpyxl
- python-docx
- flask
- django 【框架的源码】
2.创建项目
django中项目会有一些默认的文件和默认的文件夹。
2.1 在终端
-
打开终端。
-
进入某个目录(项目放在哪里)。
/Users/wupeiqi/PycharmProjects/gx
-
执行命令创建项目
"c:\python39\Scripts\django-admin.exe" startproject 项目名称
# 如果 c:\python39\Scripts 已加入环境系统环境变量。 django-admin startproject 项目名称
# 我自己的电脑 /Library/Frameworks/Python.framework/Versions/3.9/bin/django-admin startproject mysite
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g95O9Kfj-1690794616337)(assets/image-20211124085229322.png)]
2.2 Pycharm
注意:
- Python解释器安装目录:C:\python39\python.exe lib....
/Library/Frameworks/Python.framework/Versions/3.9/
- F:\pycode\ (基于Django创建的项目)
/Users/wupeiqi/PycharmProjects
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UuMcjNLT-1690794616338)(assets/image-20211124090749083.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VyBLyXk9-1690794616338)(assets/image-20211124090818003.png)]
特殊说明:
-
命令行,创建的项目是标准的。
-
pycharm,在标准的基础上默认给咱们加了点东西。
-
创建了一个templates目录【删除】
-
settings.py中【删除】
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dft4zbqz-1690794616339)(assets/image-20211124091443354.png)]
-
默认项目的文件介绍:
mysite
├── manage.py 【项目的管理,启动项目、创建app、数据管理】【不要动】【***常常用***】
└── mysite
├── __init__.py
├── settings.py 【项目配置】 【***常常修改***】
├── urls.py 【URL和函数的对应关系】【***常常修改***】
├── asgi.py 【接收网络请求】【不要动】
└── wsgi.py 【接收网络请求】【不要动】
3. 创建app
- 项目
- app,用户管理【表结构、函数、HTML模板、CSS】
- app,订单管理【表结构、函数、HTML模板、CSS】
- app,后台管理【表结构、函数、HTML模板、CSS】
- app,网站 【表结构、函数、HTML模板、CSS】
- app,API 【表结构、函数、HTML模板、CSS】
..
注意:我们开发比较简洁,用不到多app,一般情况下,项目下创建1个app即可。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vKyPqzgm-1690794616340)(assets/image-20211124094508905.png)]
├── app01
│ ├── __init__.py
│ ├── admin.py 【固定,不用动】django默认提供了admin后台管理。
│ ├── apps.py 【固定,不用动】app启动类
│ ├── migrations 【固定,不用动】数据库变更记录
│ │ └── __init__.py
│ ├── models.py 【**重要**】,对数据库操作。
│ ├── tests.py 【固定,不用动】单元测试
│ └── views.py 【**重要**】,函数。
├── manage.py
└── mysite2
├── __init__.py
├── asgi.py
├── settings.py
├── urls.py 【URL->函数】
└── wsgi.py
4.快速上手
-
确保app已注册 【settings.py】
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gKW2Umzj-1690794616340)(assets/image-20211124095619097.png)] -
编写URL和视图函数对应关系 【urls.py】
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vT7Xxumk-1690794616341)(assets/image-20211124095850778.png)] -
编写视图函数 【views.py】
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IqyFM6Bd-1690794616341)(assets/image-20211124100027337.png)] -
启动django项目
-
命令行启动
python manage.py runserver
-
Pycharm启动
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mt4BoYNP-1690794616342)(assets/image-20211124100320461.png)]
-
4.1 再写一个页面
- url -> 函数
- 函数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jHhyQD9f-1690794616342)(assets/image-20211124101708419.png)]
4.2 templates模板
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zScWppLG-1690794616342)(assets/image-20211124102815510.png)]
4.3 静态文件
在开发过程中一般将:
- 图片
- CSS
- js
都会当做静态文件处理。
4.3.1 static目录
在app目录下创建static文件夹。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-foitRgki-1690794616343)(assets/image-20211124103828667.png)]
4.3.2 引用静态文件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fGwOHmCj-1690794616343)(assets/image-20211124103947169.png)]
5.模板语法
本质上:在HTML中写一些占位符,由数据对这些占位符进行替换和处理。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JwPcg4Ob-1690794616343)(assets/image-20211124113409740.png)]
案例:伪联通新闻中心
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-35s5sJro-1690794616344)(assets/image-20211124115145293.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mBv931Sa-1690794616344)(assets/image-20211124115155394.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CaOfYvt9-1690794616344)(assets/image-20211124115209067.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-42DnrY5R-1690794616345)(assets/image-20211124115218937.png)]
6.请求和响应
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WK5oRO2G-1690794616345)(assets/image-20211124142250396.png)]
关于重定向:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tgHRG1oa-1690794616345)(assets/image-20211124142033257.png)]
案例:用户登录
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zlFmHVRB-1690794616346)(assets/image-20211124151119553.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pU24JgTm-1690794616346)(assets/image-20211124151127364.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SQE1ILmA-1690794616346)(assets/image-20211124151135563.png)]
7.数据库操作
-
MySQL数据库 + pymysql
import pymysql # 1.连接MySQL conn = pymysql.connect(host="127.0.0.1", port=3306, user='root', passwd="root123", charset='utf8', db='unicom') cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 2.发送指令 cursor.execute("insert into admin(username,password,mobile) values('wupeiqi','qwe123','15155555555')") conn.commit() # 3.关闭 cursor.close() conn.close()
-
Django开发操作数据库更简单,内部提供了ORM框架。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tJYs4lPR-1690794616347)(assets/image-20211124151748712.png)]
7.1 安装第三方模块
pip install mysqlclient
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JbJLTE3e-1690794616347)(assets/image-20211124152339567.png)]
7.2 ORM
ORM可以帮助我们做两件事:
-
创建、修改、删除数据库中的表(不用你写SQL语句)。 【无法创建数据库】
-
操作表中的数据(不用写SQL语句)。
1. 自己创建数据库
-
启动MySQL服务
-
自带工具创建数据库
create database gx_day15 DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KrvrYMM0-1690794616347)(assets/image-20211124153042996.png)]
2. django连接数据库
在settings.py文件中进行配置和修改。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'gx_day15', # 数据库名字
'USER': 'root',
'PASSWORD': 'root123',
'HOST': '127.0.0.1', # 那台机器安装了MySQL
'PORT': 3306,
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lRCwHknH-1690794616348)(assets/image-20211124154030823.png)]
3.django操作表
- 创建表
- 删除表
- 修改表
创建表:在models.py文件中
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X78iOQAG-1690794616348)(assets/image-20211124154658774.png)]
create table app01_userinfo(
id bigint auto_increment primary key,
name varchar(32),
password varchar(64),
age int
)
执行命令:
python3.9 manage.py makemigrations
python3.9 manage.py migrate
注意:app需要提前注册。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-La5e9anw-1690794616349)(assets/image-20211124155407018.png)]
在表中新增列时,由于已存在列中可能已有数据,所以新增列必须要指定新增列对应的数据:
-
1,手动输入一个值。
-
设置默认值
age = models.IntegerField(default=2)
-
允许为空
data = models.IntegerField(null=True, blank=True)
以后在开发中如果想要对表结构进行调整:
-
在models.py文件中操作类即可。
-
命令
python3.9 manage.py makemigrations python3.9 manage.py migrate
4.表中的数据
# #### 1.新建 ####
# Department.objects.create(title="销售部")
# Department.objects.create(title="IT部")
# Department.objects.create(title="运营部")
# UserInfo.objects.create(name="武沛齐", password="123", age=19)
# UserInfo.objects.create(name="朱虎飞", password="666", age=29)
# UserInfo.objects.create(name="吴阳军", password="666")
# #### 2.删除 ####
# UserInfo.objects.filter(id=3).delete()
# Department.objects.all().delete()
# #### 3.获取数据 ####
# 3.1 获取符合条件的所有数据
# data_list = [对象,对象,对象] QuerySet类型
# data_list = UserInfo.objects.all()
# for obj in data_list:
# print(obj.id, obj.name, obj.password, obj.age)
# data_list = [对象,]
# data_list = UserInfo.objects.filter(id=1)
# print(data_list)
# 3.1 获取第一条数据【对象】
# row_obj = UserInfo.objects.filter(id=1).first()
# print(row_obj.id, row_obj.name, row_obj.password, row_obj.age)
# #### 4.更新数据 ####
# UserInfo.objects.all().update(password=999)
# UserInfo.objects.filter(id=2).update(age=999)
# UserInfo.objects.filter(name="朱虎飞").update(age=999)
案例:用户管理
1. 展示用户列表
- url
- 函数
- 获取所有用户信息
- HTML渲染
2.添加用户
- url
- 函数
- GET,看到页面,输入内容。
- POST,提交 -> 写入到数据库。
3.删除用户
- url
- 函数
http://127.0.0.1:8000/info/delete/?nid=1
http://127.0.0.1:8000/info/delete/?nid=2
http://127.0.0.1:8000/info/delete/?nid=3
def 函数(request):
nid = reuqest.GET.get("nid")
UserInfo.objects.filter(id=nid).delete()
return HttpResponse("删除成功")
Django开发(一)
主题:员工管理系统
1.新建项目
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WCXbc0sm-1690794616349)(E:\django\day15.assets\image-20211125083543235.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SuC8AlHQ-1690794616349)(E:\django\day15.assets\image-20211125083701911.png)]
2.创建app
python manage.py startapp app01
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9SBwoWDe-1690794616350)(E:\django\day15.assets\image-20211125084115717.png)]
注册app:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i34CygP6-1690794616350)(E:\django\day15.assets\image-20211125084246174.png)]
3.设计表结构(django)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-URNp4SqY-1690794616350)(E:\django\day15.assets\image-20211125092320247.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kztMSnQ0-1690794616351)(E:\django\day15.assets\image-20211125092904544.png)]
from django.db import models
class Department(models.Model):
""" 部门表 """
title = models.CharField(verbose_name='标题', max_length=32)
class UserInfo(models.Model):
""" 员工表 """
name = models.CharField(verbose_name="姓名", max_length=16)
password = models.CharField(verbose_name="密码", max_length=64)
age = models.IntegerField(verbose_name="年龄")
account = models.DecimalField(verbose_name="账户余额", max_digits=10, decimal_places=2, default=0)
create_time = models.DateTimeField(verbose_name="入职时间")
# 无约束
# depart_id = models.BigIntegerField(verbose_name="部门ID")
# 1.有约束
# - to,与那张表关联
# - to_field,表中的那一列关联
# 2.django自动
# - 写的depart
# - 生成数据列 depart_id
# 3.部门表被删除
# ### 3.1 级联删除
depart = models.ForeignKey(to="Department", to_field="id", on_delete=models.CASCADE)
# ### 3.2 置空
# depart = models.ForeignKey(to="Department", to_field="id", null=True, blank=True, on_delete=models.SET_NULL)
# 在django中做的约束
gender_choices = (
(1, "男"),
(2, "女"),
)
gender = models.SmallIntegerField(verbose_name="性别", choices=gender_choices)
4.在MySQL中生成表
-
工具连接MySQL生成数据库。
create database gx_day16 DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
-
修改配置文件,连接MySQL
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'gx_day16', # 数据库名字 'USER': 'root', 'PASSWORD': 'root123', 'HOST': '127.0.0.1', # 那台机器安装了MySQL 'PORT': 3306, } }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LEIeauus-1690794616351)(E:\django\day15.assets\image-20211125093556582.png)]
-
django命令生成数据库表
python manage.py makemigrations python manage.py migrate
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HxSGeTHd-1690794616351)(E:\django\day15.assets\image-20211125093805549.png)]
表结构创建成功:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KXnfuumV-1690794616352)(E:\django\day15.assets\image-20211125093859327.png)]
5.静态文件管理
static目录
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RA2prnAB-1690794616352)(E:\django\day15.assets\image-20211125095750076.png)]
6.部门管理
体验,最原始方法来做。
Django中提供Form和ModelForm组件(方便)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9BHHWnAm-1690794616352)(E:\django\day15.assets\image-20211125100519237.png)]
7.模板的继承
- 部门列表
- 添加部门
- 编辑部门
定义目版:layout.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{% static 'plugin...min.css' %}">
{% block css %}{% endblock %}
</head>
<body>
<h1>标题</h1>
<div>
{% block content %}{% endblock %}
</div>
<h1>底部</h1>
<script src="{% static 'js/jquery-3.6.0.min.js' %}"></script>
{% block js %}{% endblock %}
</body>
</html>
继承母版:
{% extends 'layout.html' %}
{% block css %}
<link rel="stylesheet" href="{% static 'pluxxx.css' %}">
<style>
...
</style>
{% endblock %}
{% block content %}
<h1>首页</h1>
{% endblock %}
{% block js %}
<script src="{% static 'js/jqxxxin.js' %}"></script>
{% endblock %}
8.用户管理
insert into app01_userinfo(name,password,age,account,create_time,gender,depart_id) values("韩超","666",23,100.68,"2020-01-11",2,1);
insert into app01_userinfo(name,password,age,account,create_time,gender,depart_id) values("刘东","123",23,100.68,"2010-11-11",1,4);
insert into app01_userinfo(name,password,age,account,create_time,gender,depart_id) values("朱虎飞","999",33,9900.68,"2021-05-11",1,1);
+-------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+---------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| name | varchar(16) | NO | | NULL | |
| password | varchar(64) | NO | | NULL | |
| age | int(11) | NO | | NULL | |
| account | decimal(10,2) | NO | | NULL | |
| create_time | datetime(6) | NO | | NULL | |
| gender | smallint(6) | NO | | NULL | |
| depart_id | bigint(20) | NO | MUL | NULL | |
+-------------+---------------+------+-----+---------+----------------+
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HO5efwGQ-1690794616353)(E:\django\day15.assets\image-20211125144436879.png)]
新建用户:
-
原始方式理思路:不会采用(本质)【麻烦】
- 用户提交数据没有校验。 - 错误,页面上应该有错误提示。 - 页面上,没一个字段都需要我们重新写一遍。 [OK] - 关联的数据,手动去获取并展示循环展示在页面。 [OK]
-
Django组件
- Form组件(小简便)
- ModelForm组件(最简便)
8.1 初识Form
1. views.py
class MyForm(Form):
user = forms.CharField(widget=forms.Input)
pwd = form.CharFiled(widget=forms.Input)
email = form.CharFiled(widget=forms.Input)
account = form.CharFiled(widget=forms.Input)
create_time = form.CharFiled(widget=forms.Input)
depart = form.CharFiled(widget=forms.Input)
gender = form.CharFiled(widget=forms.Input)
def user_add(request):
if request.method == "GET":
form = MyForm()
return render(request, 'user_add.html',{"form":form})
2.user_add.html
<form method="post">
{% for field in form%}
{{ field }}
{% endfor %}
<!-- <input type="text" placeholder="姓名" name="user" /> -->
</form>
<form method="post">
{{ form.user }}
{{ form.pwd }}
{{ form.email }}
<!-- <input type="text" placeholder="姓名" name="user" /> -->
</form>
8.3 ModelForm(推荐)
0. models.py
class UserInfo(models.Model):
""" 员工表 """
name = models.CharField(verbose_name="姓名", max_length=16)
password = models.CharField(verbose_name="密码", max_length=64)
age = models.IntegerField(verbose_name="年龄")
account = models.DecimalField(verbose_name="账户余额", max_digits=10, decimal_places=2, default=0)
create_time = models.DateTimeField(verbose_name="入职时间")
depart = models.ForeignKey(to="Department", to_field="id", on_delete=models.CASCADE)
gender_choices = (
(1, "男"),
(2, "女"),
)
gender = models.SmallIntegerField(verbose_name="性别", choices=gender_choices)
1. views.py
class MyForm(ModelForm):
xx = form.CharField*("...")
class Meta:
model = UserInfo
fields = ["name","password","age","xx"]
def user_add(request):
if request.method == "GET":
form = MyForm()
return render(request, 'user_add.html',{"form":form})
2.user_add.html
<form method="post">
{% for field in form%}
{{ field }}
{% endfor %}
<!-- <input type="text" placeholder="姓名" name="user" /> -->
</form>
<form method="post">
{{ form.user }}
{{ form.pwd }}
{{ form.email }}
<!-- <input type="text" placeholder="姓名" name="user" /> -->
</form>
Django开发(二)
-
部门管理
-
用户管理
-
用户列表
-
新建用户
- ModelForm,针对数据库中的某个表。 - Form。
-
8.4 编辑用户
-
点击编辑,跳转到编辑页面(将编辑行的ID携带过去)。
-
编辑页面(默认数据,根据ID获取并设置到页面中)
-
提交:
-
错误提示
-
数据校验
-
在数据库更新
models.UserInfo.filter(id=4).update(...)
-
8.5 删除
见代码。
9.靓号管理
9.1 表结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NuYRP5xz-1690794616353)(E:\django\day15.assets\image-20211126094318872.png)]
根据表结构的需求,在models.py中创建类(由类生成数据库中的表)。
class PrettyNum(models.Model):
""" 靓号表 """
mobile = models.CharField(verbose_name="手机号", max_length=11)
# 想要允许为空 null=True, blank=True
price = models.IntegerField(verbose_name="价格", default=0)
level_choices = (
(1, "1级"),
(2, "2级"),
(3, "3级"),
(4, "4级"),
)
level = models.SmallIntegerField(verbose_name="级别", choices=level_choices, default=1)
status_choices = (
(1, "已占用"),
(2, "未使用")
)
status = models.SmallIntegerField(verbose_name="状态", choices=status_choices, default=2)
自己在数据模拟创建一些数据:
insert into app01_prettynum(mobile,price,level,status)values("111111111",19,1,1);
mysql> select * from app01_prettynum;
+----+-----------+-------+-------+--------+
| id | mobile | price | level | status |
+----+-----------+-------+-------+--------+
| 1 | 111111111 | 19 | 1 | 1 |
| 2 | 111111111 | 19 | 1 | 1 |
| 3 | 111111111 | 19 | 1 | 1 |
| 4 | 111111111 | 19 | 1 | 1 |
+----+-----------+-------+-------+--------+
4 rows in set (0.01 sec)
9.2 靓号列表
-
URL
-
函数
-
获取所有的靓号
-
结合html+render将靓号罗列出来
id 号码 价格 级别(中文) 状态(中文)
-
9.3 新建靓号
-
列表点击跳转:
/pretty/add/
-
URL
-
ModelForm类
from django import forms class PrettyModelForm(forms.ModelForm): ...
-
函数
- 实例化类的对象
- 通过render将对象传入到HTML中。
- 模板的循环展示所有的字段。
-
点击提交
- 数据校验
- 保存到数据库
- 跳转回靓号列表
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iBAgglFl-1690794616353)(E:\django\day15.assets\image-20211126111252278.png)]
9.4 编辑靓号
- 列表页面:
/pretty/数字/edit/
- URL
- 函数
- 根据ID获取当前编辑的对象
- ModelForm配合,默认显示数据。
- 提交修改。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lsJ9Gpxx-1690794616354)(E:\django\day15.assets\image-20211126112848435.png)]
不允许手机号重复。
-
添加:【正则表达式】【手机号不能存在】
# [obj,obj,obj] queryset = models.PrettyNum.objects.filter(mobile="1888888888") obj = models.PrettyNum.objects.filter(mobile="1888888888").first() # True/False exists = models.PrettyNum.objects.filter(mobile="1888888888").exists()
-
编辑:【正则表达式】【手机号不能存在】
排除自己以外,其他的数据是否手机号是否重复? # id!=2 and mobile='1888888888' models.PrettyNum.objects.filter(mobile="1888888888").exclude(id=2)
9.5 搜索手机号
models.PrettyNum.objects.filter(mobile="19999999991",id=12)
data_dict = {"mobile":"19999999991","id":123}
models.PrettyNum.objects.filter(**data_dict)
models.PrettyNum.objects.filter(id=12) # 等于12
models.PrettyNum.objects.filter(id__gt=12) # 大于12
models.PrettyNum.objects.filter(id__gte=12) # 大于等于12
models.PrettyNum.objects.filter(id__lt=12) # 小于12
models.PrettyNum.objects.filter(id__lte=12) # 小于等于12
data_dict = {"id__lte":12}
models.PrettyNum.objects.filter(**data_dict)
models.PrettyNum.objects.filter(mobile="999") # 等于
models.PrettyNum.objects.filter(mobile__startswith="1999") # 筛选出以1999开头
models.PrettyNum.objects.filter(mobile__endswith="999") # 筛选出以999结尾
models.PrettyNum.objects.filter(mobile__contains="999") # 筛选出包含999
data_dict = {"mobile__contains":"999"}
models.PrettyNum.objects.filter(**data_dict)
9.6 分页
queryset = models.PrettyNum.objects.all()
queryset = models.PrettyNum.objects.filter(id=1)[0:10]
# 第1页
queryset = models.PrettyNum.objects.all()[0:10]
# 第2页
queryset = models.PrettyNum.objects.all()[10:20]
# 第3页
queryset = models.PrettyNum.objects.all()[20:30]
data = models.PrettyNum.objects.all().count()
data = models.PrettyNum.objects.filter(id=1).count()
-
分页的逻辑和处理规则
-
封装分页类
- 从头到尾开发
- 写项目用【pagination.py】公共组件。
-
小Bug,搜索 + 分页情况下。
分页时候,保留原来的搜索条件 http://127.0.0.1:8000/pretty/list/?q=888 http://127.0.0.1:8000/pretty/list/?page=1 http://127.0.0.1:8000/pretty/list/?q=888&page=23
10.时间插件
<link rel="stylesheet" href="static/plugins/bootstrap-3.4.1/css/bootstrap.css">
<link rel="stylesheet" href="static/plugins/bootstrap-datepicker/css/bootstrap-datepicker.css">
<input type="text" id="dt" class="form-control" placeholder="入职日期">
<script src="static/js/jquery-3.6.0.min.js"></script>
<script src="static/plugins/bootstrap-3.4.1/js/bootstrap.js"></script>
<script src="static/plugins/bootstrap-datepicker/js/bootstrap-datepicker.js"></script>
<script src="static/plugins/bootstrap-datepicker/locales/bootstrap-datepicker.zh-CN.min.js"></script>
<script>
$(function () {
$('#dt').datepicker({
format: 'yyyy-mm-dd',
startDate: '0',
language: "zh-CN",
autoclose: true
});
})
</script>
11.ModelForm和BootStrap
-
ModelForm可以帮助我们生成HTML标签。
class UserModelForm(forms.ModelForm): class Meta: model = models.UserInfo fields = ["name", "password",] form = UserModelForm()
{{form.name}} 普通的input框 {{form.password}} 普通的input框
-
定义插件
class UserModelForm(forms.ModelForm): class Meta: model = models.UserInfo fields = ["name", "password",] widgets = { "name": forms.TextInput(attrs={"class": "form-control"}), "password": forms.PasswordInput(attrs={"class": "form-control"}), "age": forms.TextInput(attrs={"class": "form-control"}), }
class UserModelForm(forms.ModelForm): name = forms.CharField( min_length=3, label="用户名", widget=forms.TextInput(attrs={"class": "form-control"}) ) class Meta: model = models.UserInfo fields = ["name", "password", "age"]
{{form.name}} BootStrap的input框 {{form.password}} BootStrap的input框
-
重新定义的init方法,批量设置
class UserModelForm(forms.ModelForm): class Meta: model = models.UserInfo fields = ["name", "password", "age",] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 循环ModelForm中的所有字段,给每个字段的插件设置 for name, field in self.fields.items(): field.widget.attrs = { "class": "form-control", "placeholder": field.label }
class UserModelForm(forms.ModelForm): class Meta: model = models.UserInfo fields = ["name", "password", "age",] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 循环ModelForm中的所有字段,给每个字段的插件设置 for name, field in self.fields.items(): # 字段中有属性,保留原来的属性,没有属性,才增加。 if field.widget.attrs: field.widget.attrs["class"] = "form-control" field.widget.attrs["placeholder"] = field.label else: field.widget.attrs = { "class": "form-control", "placeholder": field.label }
class UserEditModelForm(forms.ModelForm): class Meta: model = models.UserInfo fields = ["name", "password", "age",] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 循环ModelForm中的所有字段,给每个字段的插件设置 for name, field in self.fields.items(): # 字段中有属性,保留原来的属性,没有属性,才增加。 if field.widget.attrs: field.widget.attrs["class"] = "form-control" field.widget.attrs["placeholder"] = field.label else: field.widget.attrs = { "class": "form-control", "placeholder": field.label }
-
自定义类
class BootStrapModelForm(forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 循环ModelForm中的所有字段,给每个字段的插件设置 for name, field in self.fields.items(): # 字段中有属性,保留原来的属性,没有属性,才增加。 if field.widget.attrs: field.widget.attrs["class"] = "form-control" field.widget.attrs["placeholder"] = field.label else: field.widget.attrs = { "class": "form-control", "placeholder": field.label }
class UserEditModelForm(BootStrapModelForm): class Meta: model = models.UserInfo fields = ["name", "password", "age",]
操作
-
提取公共的类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TajQ5Ki0-1690794616354)(E:\django\day15.assets\image-20211126175803303.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BK4Gnv1I-1690794616354)(E:\django\day15.assets\image-20211126175826579.png)] -
ModelForm拆分出来
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A82Ti9tw-1690794616355)(E:\django\day15.assets\image-20211126175852716.png)] -
视图函数的归类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4lh1fBWi-1690794616355)(E:\django\day15.assets\image-20211126175927378.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7NqtwfX2-1690794616355)(E:\django\day15.assets\image-20211126175946996.png)]
Django开发(三)
知识点的回顾:
-
安装Django
pip install django
-
创建Django项目
>>> django-admin startproject mysite
注意:Pycharm可以创建。如果用Pycharm创建,记得settings.py中的DIR templates 删除。
-
创建app & 注册
>>>python manage.py startapp app01 >>>python manage.py startapp app02 >>>python manage.py startapp app03
INSTALLED_APPS = [ ... 'app01.apps.App01Config' ]
注意:否则app下的models.py写类时,无法在数据库中创建表。
-
配置 静态文件路径 & 模板的路径(放在app目录下)。
-
配置数据库相关操作(MySQL)
-
第三方模块(django3版本)
pip install mysqlclient
-
自己先去MySQL创建一个数据库。
-
配置数据库连接settings.py
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'gx_day16', # 数据库名字 'USER': 'root', 'PASSWORD': 'root123', 'HOST': '127.0.0.1', # 那台机器安装了MySQL 'PORT': 3306, } }
-
在app下的models.py中编写
from django.db import models class Admin(models.Model): """ 管理员 """ username = models.CharField(verbose_name="用户名", max_length=32) password = models.CharField(verbose_name="密码", max_length=64) def __str__(self): return self.username class Department(models.Model): """ 部门表 """ title = models.CharField(verbose_name='标题', max_length=32) def __str__(self): return self.title
-
执行两个命令:
>>>python manange.py makemigrations >>>python manange.py migrate
-
-
在 urls.py ,路由 ( URL 和 函数的对应关系)。
-
在views.py,视图函数,编写业务逻辑。
-
templates目录,编写HTML模板(含有模板语法、继承、
{% static 'xx'%}
) -
ModelForm & Form组件,在我们开发增删改查功能。
- 生成HTML标签(生成默认值)
- 请求数据进行校验。
- 保存到数据库(ModelForm)
- 获取错误信息。
-
Cookie和Session,用户登录信息保存起来。
-
中间件,基于中间件实现用户认证 ,基于:
process_request
。 -
ORM操作
models.User.objects.filter(id="xxx") models.User.objects.filter(id="xxx").order_by("-id")
-
分页组件。
1.Ajax请求
2.订单
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mOa4MvUm-1690794616356)(E:\django\day15.assets\image-20211129092011994.png)]
class Order(models.Model):
""" 订单 """
oid = models.CharField(verbose_name="订单号", max_length=64)
title = models.CharField(verbose_name="名称", max_length=32)
price = models.IntegerField(verbose_name="价格")
status_choices = (
(1, "待支付"),
(2, "已支付"),
)
status = models.SmallIntegerField(verbose_name="状态", choices=status_choices, default=1)
admin = models.ForeignKey(verbose_name="管理员", to="Admin", on_delete=models.CASCADE)
想要去数据库中获取数据时:对象/字典
# 对象,当前行的所有数据。
row_object = models.Order.objects.filter(id=uid).first()
row_object.id
row_object.title
# 字典,{"id":1,"title":"xx"}
row_dict = models.Order.objects.filter(id=uid).values("id","title").first()
# queryset = [obj,obj,obj,]
queryset = models.Order.objects.all()
# queryset = [ {'id':1,'title':"xx"},{'id':2,'title':"xx"}, ]
queryset = models.Order.objects.all().values("id","title")
# queryset = [ (1,"xx"),(2,"xxx"), ]
queryset = models.Order.objects.all().values_list("id","title")
小结
至此,基于Ajax + 对话框的形式实现的页面的增删改查。
- 表单,实现增删改查。
- Ajax,实现增删改查。
3.图表
- highchart,国外。
- echarts,国内。
更多参考文档:https://echarts.apache.org/handbook/zh/get-started
Django开发(四)
1.知识点复习
1.1 基础入门
-
编码
编码基础知识点:utf-8、unicode、gbk、ascii 默认解释器编码: - Python2:ascii( # -*- coding:utf-8 -*- ) - Python3:utf-8(重要)
-
输入和输出
print input,用户输入的永远是字符串类型。 data = input("请输入序号:") # 1 print(data) # "1"
-
变量
规范:字母、数字、下划线;数字不能开头;不能是py内置关键字。 建议: - 见名知意 - 多个单词,用下划线连接。 - 全局变量用大写( DATA_LIST、USER_INFO );局部变量小写(user_age)。 注意: 全局变量 GET_INFO 局部变量 get_info 函数名 get_info 类名 GetInfo 文件名 get_info 包名称 get_info
-
异常处理【补充】
data = input("请输入:") # 你好 res = int(data) print(res) # 这个代码是有风险,可能会报错。
print("开始") try: data = input("请输入:") # 123 / 你好 res = int(data) print(res) except Exception as e: print("出错了") print("结束")
-
循环中for/while内部都可以用 break、continue
-
字符串格式化
data = "我是{},姓名是{},年龄是{}".format("xx",123,999) data = "我是{0},姓名是{1},年龄是{2}".format("xx",123,999) data = "我是{0},姓名是{0},年龄是{2}".format("xx",123)
-
运算符
- 传统的运算符 - 逻辑运算符 - 常见操作,最终的到的结果:True/False if 1>10 and 9<8: pass else: pass - 非传统,最终的结果是:第一个或第二个值。 data = 值1 and 值2 v1 = 5 and 9 # 9 v2 = 0 and 10 # 0
1.2 数据类型
-
字符串类型
- 不可变类型; - 常见方法:strip/split/replace/join v1 = "root" data = v1.upper() print(v1) # root print(data) # ROOT - 公共:索引、切片、循环 v1 = "root" v1[1] = "X" # 报错,不可变
-
列表类型
- 可变类型 - 常见方法:append/insert/pop/remove - 公共:索引、切片、循环 v1 = [11,22,33,44,55] v1[0] v1[1:3] - 前取后不取 v1[1:-1] - 列表的推导式 data = [ i for i in range(10)] data = [ i for i in range(10) if i<5]
-
字典类型
- 可变类型 - 字典的键是有要求:可哈希类型,目前不可哈希:list/dict/set。 - 扩展:python3.6+字典有序。 - 常见的功能:keys、values、items、get data = {} v1 = data.get("k1")
-
关于元组
v1 = (11,) v2 = (11) # 11 v3 = 11
-
其他数据类型
其他类型转布尔类型时,哪些为False: 空、0、None 其他类型转自己类型时,自己的类名() int("123")
1.3 函数
-
定义
def func(): pass func()
-
参数
def func(v1,v2): pass def func(v1, v2=None): pass def func(*args,**kwargs): pass
-
返回值
- 没有返回值,默认返回None def func(v1,v2): print(999) - 一个返回值 def func(v1,v2): return 123 res = func(1,2) print(res) # 123 - 多个返回值 def func(v1,v2): return 123,999,123 res = func(1,2) print(res) # (123,999,123) def func(v1,v2): return 123,999,123 d1,d2,c3 = func(1,2)
v1,v2 = [11,22] v1,v2,v3 = (11,22,999)
-
lambda表达式(匿名函数)
def func(arg): return arg + 100 func = lambda arg:arg+100 v1 = func(100) print(v1) # 200
-
内置函数
max/min/all/any/help/hex/oct/bin.. open,文件操作。 f = open("xx.log",mode='r') data = f.read() f.close()
-
文件操作
- 模式:r/w/a ; rb/wb/ab - 打开 & 关闭 with open("xx.log",mode='r') as f: f.read()
1.4 模块
-
分类
- 自定义模块:自己写文件/文件夹 - 内置模块:time/datetime/json/hashlib/random/re等 - 第三方模块:openpyxl/requests/bs4/flask/django等
-
自定义模块
- sys.path,Python内部导入模块时,根据目录去寻找。 - 一定不要让自己写的模块名和内置的模块名重复(***) - 导入模块: import xxx from xxx import xxx
-
内置模块
- 时间部分:time/datetime/字符串类型。 - random:随机生成数字。 - hashlib:加密(md5加密、md5加密+加盐) 防止被撞库。 - json: - JSON格式的字符串: 内部字符串双引号、内部[] - json.dumps - json.loads - re和正则 - 正则:\d \w ; 贪婪匹配。 - re.search/re.match/ re.findall
-
第三方模块
- 安装第三方模块:pip、源码、wheel - 常见第三方模块: - requests - bs4 - openpyxl - python-docx - flask/django (flask简洁(轻量级);django功能强大)
1.5 面向对象
- 面向对象的三大特性:封装、继承、多态。
- 理解,读懂源码和代码。
1.6 MySQL数据库
- 数据库
- 表
- 数据行
更多知识:https://www.bilibili.com/video/BV15R4y1b7y9
show databases;
use 数据库;
show tables;
desc 表名;
select * from 表;
insert into 表(列,列,列)values(...)
update 表 set 列=值;
delete from 表 where 条件;
Python连接并操作MySQL:
-
pymysql 【自己原生写】
pip install pymysql
-
mysqlclient 【django内部】
pip install mysqlclient
-
MySQLdb (默认不支持python3)
pip intall MySQLdb
当使用Python代码去操作MySQL时,一定要防止SQL注入的问题。
# SQL语句不要用字符串格式化去拼接。
import pymysql
# 1.连接MySQL
conn = pymysql.connect(host="127.0.0.1", port=3306, user='root', passwd="root123", charset='utf8', db='unicom')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 【错误】不要这么写
sql = "select * from admin where id > %s".format(2)
cursor.execute(sql)
# 【正确】这么写
cursor.execute("select * from admin where id > %s", [2, ])
# 获取符合条件的第一条数据,字典 None
res = cursor.fetchone()
print(res) # {'id': 3, 'username': '集宁', 'password': 'qwe123', 'mobile': '1999999999'}
# 3.关闭连接
cursor.close()
conn.close()
1.7 前端开发
-
HTML
- 块级和行内标签(div、span) 块级:div/h系列 行内:span/a (设置高度、宽度、边距无效) - Form表单 <form method="post" action="地址"> <input .... <input type='submit' ... /> </form> - 关于a标签 <a href="www.baidu.com">百度</a> 超链接去跳转。 做锚点 <a href="#m1">第一章</a> <a href="#m2">第二章</a> <div id="m1" style="height: 1000px;">第一章 谢新雪</div> <div id="m2" style="height: 1000px;">第二章 单独的</div>
-
CSS
- 位置 - 标签 <div style="xxx"> - style代码块 <style> div { } #v1 { } .v2 {} </style> - 文件中 - 选择器 div { } #v1 { } .v2 { } div[xx='11'] { } - 样式 color;fonts-ize; background-color; padding; margin; float:left; ,脱离文档流。 clear:both; :after
-
JavaScript & jQuery
- 本质上:找到标签;操作标签。 - 找标签 $("#x1") $(".x1") $("div") $("input[type='text']") 找到 input 标签且 type='text' - 操作标签 $("#x1").text() <div id='x1'>dd</div> $("#x1").text("xxx") <div id='x1'>xxx</div> $("#x1").val() <input id='x1' /> $("#x1").val("xxx") <input id='x1' /> $("#x1").attr("uu") <div id='x1' uu="123">dd</div> $("#x1").attr("uu","999") <div id='x1' uu="999">dd</div> $("#x1").empty() <div id='x1'>dd</div> - 清空内容 $("#x1").remove() <div id='x1'>dd</div> - 整个标签删除
-
BootStrap
- 支持响应式布局,根据屏幕的宽度调整布局。 - 栅格,12份。 - 常见的样式: - container / container-fluid - 面板 - 按钮 - 表单 - 表格 - 对话框
-
第三方插件
- 插件一般都包含:CSS、JavaScript,开发使用时候 - 引入css、js(依赖jQuery) - 使用
-
关于注释
- Python语言 # 注释 """ 注释 """ - HTML <!-- --> - CSS注释 /* 注释 */ - JavaScript // 注释 /* 注释 */
1.8 Django
-
安装
pip install django
python安装目录下: - lib/site-packages/django源码包 - Scripts/django-admin.exe 文件
-
创建Django项目
>>>django-admin startproject 项目名
-
创建APP
>>>cd 项目目录 >>>python manange.py startapp app名称
-
注册app
- 不注册,models.py生成数据库表行为不执行。 - 不注册,模板文件、静态文件,不回去app目录下找。
-
static目录,静态文件目录
-
templates目录,模板文件目录(HTML)
-
表结构设计 app01/modes.py下执行
from django.db import models class UserInfo(models.Model): v1 = models.CharField(max_length=32) ... ..
>>>python manage.py makemigrations >>>python manage.py migrate
-
urls.py 中编写路由。
from django.urls import path,re_path from app01 import admin urlpatterns = [ path('admin/list/', admin.admin_list), path('admin/<int:nid>/delete/', admin.admin_delete), re_path('admin/(?P<nid>\d+)/delete/', admin.admin_delete) ]
-
视图函数
def admin_list(request): k1 = request.POST.get("k1") ... 业务处理 return 数据 - 默认参数request,包含请求相关的所有数据。 request.method request.GET request.POST request.FILES,上传文件。 request.path_info,获取当前请求的URL http://127.0.0.1:8000/depart/add/ -> /depart/add/ - 返回值 return HttpResponse("字符串") return JSONResponse( {"status":123,"data":[456,55,66,22,]} ) return JSONResponse( [11,22,33,44] ,safe=False) return render(request,"xxx.html",{值}) return redirect("http://127.0.0.1:8000/depart/add/") return redirect("/depart/add/")
-
数据库的ORM操作
# 增加 models.类.objects.create(name="武沛齐",age=19) models.类.objects.create(**{"name":"武沛齐","age":19}) obj = models.类(name="武沛齐",age=19) obj.save() obj_list = [ models.类(name="武沛齐",age=19), models.类(name="武沛齐",age=19), models.类(name="武沛齐",age=19), models.类(name="武沛齐",age=19), models.类(name="武沛齐",age=19) 。。。 ] models.类.objects.bulk_create(obj_list,batch_size=10)
# 查询 queyrset = models.类.objects.filter(name="武沛齐",age=19) # [obj,obj,] queyrset = models.类.objects.filter(**{"name":"武沛齐","age":19}) # [] obj = models.类.objects.filter(name="武沛齐",age=19).first() # obj / None queyrset = models.类.objects.filter(age=19) queyrset = models.类.objects.filter(age__gt=19) queyrset = models.类.objects.filter(age__gte=19) queyrset = models.类.objects.filter(age__lt=19) queyrset = models.类.objects.filter(age__lte=19) queyrset = models.类.objects.filter(age__gt=19, name="武沛齐") queyrset = models.类.objects.filter(name__contains="中国") queyrset = models.类.objects.exclude(id=9) # id !=9 queyrset = models.类.objects.filter(age=19).order_by("id") queyrset = models.类.objects.filter(age=19).order_by("-id") queyrset = models.类.objects.filter(age=19).order_by("-id","name") queyrset = models.类.objects.filter(age=19)[0:10]
# 更新 queyrset = models.类.objects.filter(id=2).update(age=19,name="武沛齐") queyrset = models.类.objects.filter(id=2).update(**{"name":"武沛齐","age":19}) obj = models.类.objects.filter(id=2).first() obj.name = "武沛齐" obj.age = 19 obj.save()
# 删除 models.类.objects.filter(id=2).delete()
整理的所有ORM操作: https://www.cnblogs.com/wupeiqi/articles/6216618.html
-
Form和ModelForm组件
- 自动生成HTML标签 - 对用户请求的数据进行校验 - 自动保存到数据库(ModelForm) - 错误信息
from django import forms class UserForm(forms.Form): xx = forms.CharField(...) class UserModelForm(forms.ModelForm): class Meta: model = models.类 fields = "__all__"
form = UserModelForm(data=request.POST,instance=对象) if form.is_valid(): form.cleaned_data else: form.errors
-
关于POST提交CSRF认证
<form method='post'> {% csrf_token %} ... </form>
如果想要免除csrf认证。
from django.views.decorators.csrf import csrf_exempt @csrf_exempt def order_add(request): pass
-
Cookie和Session
cookie,本质上保存在浏览器端的键值对。 session,保存服务器端(django是将session默认存储在数据库中) def order_add(request): request.session['xx'] = 123 def logout(request): request.session.clear()
-
中间件
- 类 process_request / process_response - 注册中间件类 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', 'app01.middleware.auth.AuthMiddleware', ] - django请求到达之后,自动会执行相应的方法。 - process_request - 没有返回值或返回None,继续向后执行。 - 返回redirect/render/HttpResponse/JsonReponse,拦截请求不再继续向后之后。
-
图片验证码
pip install pillow
- 创建图片并在图片上写文字 - 字体文件 - 自定义模块 check_code
-
分页组件
开发时候会用。
2.关于文件上传
2.1 基本操作
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="text" name="username">
<input type="file" name="avatar">
<input type="submit" value="提交">
</form>
from django.shortcuts import render, HttpResponse
def upload_list(request):
if request.method == "GET":
return render(request, 'upload_list.html')
# # 'username': ['big666']
# print(request.POST) # 请求体中数据
# # {'avatar': [<InMemoryUploadedFile: 图片 1.png (image/png)>]}>
# print(request.FILES) # 请求发过来的文件 {}
file_object = request.FILES.get("avatar")
# print(file_object.name) # 文件名:WX20211117-222041@2x.png
f = open(file_object.name, mode='wb')
for chunk in file_object.chunks():
f.write(chunk)
f.close()
return HttpResponse("...")
案例:批量上传数据
<form method="post" enctype="multipart/form-data" action="/depart/multi/">
{% csrf_token %}
<div class="form-group">
<input type="file" name="exc">
</div>
<input type="submit" value="上传" class="btn btn-info btn-sm">
</form>
def depart_multi(request):
""" 批量删除(Excel文件)"""
from openpyxl import load_workbook
# 1.获取用户上传的文件对象
file_object = request.FILES.get("exc")
# 2.对象传递给openpyxl,由openpyxl读取文件的内容
wb = load_workbook(file_object)
sheet = wb.worksheets[0]
# 3.循环获取每一行数据
for row in sheet.iter_rows(min_row=2):
text = row[0].value
exists = models.Department.objects.filter(title=text).exists()
if not exists:
models.Department.objects.create(title=text)
return redirect('/depart/list/')
案例:混合数据(Form)
提交页面时:用户输入数据 + 文件(输入不能为空、报错)。
- Form生成HTML标签:type=file
- 表单的验证
- form.cleaned_data 获取 数据 + 文件对象
{% extends 'layout.html' %}
{% block content %}
<div class="container">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"> {{ title }} </h3>
</div>
<div class="panel-body">
<form method="post" enctype="multipart/form-data" novalidate >
{% csrf_token %}
{% for field in form %}
<div class="form-group">
<label>{{ field.label }}</label>
{{ field }}
<span style="color: red;">{{ field.errors.0 }}</span>
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">提 交</button>
</form>
</div>
</div>
</div>
{% endblock %}
from django import forms
from app01.utils.bootstrap import BootStrapForm
class UpForm(BootStrapForm):
bootstrap_exclude_fields = ['img']
name = forms.CharField(label="姓名")
age = forms.IntegerField(label="年龄")
img = forms.FileField(label="头像")
def upload_form(request):
title = "Form上传"
if request.method == "GET":
form = UpForm()
return render(request, 'upload_form.html', {"form": form, "title": title})
form = UpForm(data=request.POST, files=request.FILES)
if form.is_valid():
# {'name': '武沛齐', 'age': 123, 'img': <InMemoryUploadedFile: 图片 1.png (image/png)>}
# 1.读取图片内容,写入到文件夹中并获取文件的路径。
image_object = form.cleaned_data.get("img")
# file_path = "app01/static/img/{}".format(image_object.name)
db_file_path = os.path.join("static", "img", image_object.name)
file_path = os.path.join("app01", db_file_path)
f = open(file_path, mode='wb')
for chunk in image_object.chunks():
f.write(chunk)
f.close()
# 2.将图片文件路径写入到数据库
models.Boss.objects.create(
name=form.cleaned_data['name'],
age=form.cleaned_data['age'],
img=db_file_path,
)
return HttpResponse("...")
return render(request, 'upload_form.html', {"form": form, "title": title})
注意:就目前而言,所有的静态文件都只能放在static目录。
在django的开发过程中两个特殊的文件夹:
- static,存放静态文件的路径,包括:CSS、JS、项目图片。
- media,用户上传的数据的目录。
2.2 启用media
在urls.py中进行配置:
from django.urls import path, re_path
from django.views.static import serve
from django.conf import settings
urlpatterns = [
re_path(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}, name='media'),
]
在settings.py中进行配置:
import os
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
MEDIA_URL = "/media/"
在浏览器上访问这个地址:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KwRwSO5N-1690794616357)(E:\django\day15.assets\image-20211130170639048.png)]
案例:混合数据(form)
from django import forms
from app01.utils.bootstrap import BootStrapForm
class UpForm(BootStrapForm):
bootstrap_exclude_fields = ['img']
name = forms.CharField(label="姓名")
age = forms.IntegerField(label="年龄")
img = forms.FileField(label="头像")
def upload_form(request):
title = "Form上传"
if request.method == "GET":
form = UpForm()
return render(request, 'upload_form.html', {"form": form, "title": title})
form = UpForm(data=request.POST, files=request.FILES)
if form.is_valid():
# {'name': '武沛齐', 'age': 123, 'img': <InMemoryUploadedFile: 图片 1.png (image/png)>}
# 1.读取图片内容,写入到文件夹中并获取文件的路径。
image_object = form.cleaned_data.get("img")
# media_path = os.path.join(settings.MEDIA_ROOT, image_object.name)
media_path = os.path.join("media", image_object.name)
f = open(media_path, mode='wb')
for chunk in image_object.chunks():
f.write(chunk)
f.close()
# 2.将图片文件路径写入到数据库
models.Boss.objects.create(
name=form.cleaned_data['name'],
age=form.cleaned_data['age'],
img=media_path,
)
return HttpResponse("...")
return render(request, 'upload_form.html', {"form": form, "title": title})
案例:混合数据(ModalForm)
models.py
class City(models.Model):
""" 城市 """
name = models.CharField(verbose_name="名称", max_length=32)
count = models.IntegerField(verbose_name="人口")
# 本质上数据库也是CharField,自动保存数据。
img = models.FileField(verbose_name="Logo", max_length=128, upload_to='city/')
定义ModelForm
from app01.utils.bootstrap import BootStrapModelForm
class UpModelForm(BootStrapModelForm):
bootstrap_exclude_fields = ['img']
class Meta:
model = models.City
fields = "__all__"
视图
def upload_modal_form(request):
""" 上传文件和数据(modelForm)"""
title = "ModelForm上传文件"
if request.method == "GET":
form = UpModelForm()
return render(request, 'upload_form.html', {"form": form, 'title': title})
form = UpModelForm(data=request.POST, files=request.FILES)
if form.is_valid():
# 对于文件:自动保存;
# 字段 + 上传路径写入到数据库
form.save()
return HttpResponse("成功")
return render(request, 'upload_form.html', {"form": form, 'title': title})
小结
-
自己手动去写
file_object = request.FILES.get("exc") ...
-
Form组件(表单验证)
request.POST file_object = request.FILES.get("exc") 具体文件操作还是手动自己做。
-
ModelForm(表单验证 + 自动保存数据库 + 自动保存文件)
- Media文件夹 - Models.py定义类文件要 img = models.FileField(verbose_name="Logo", max_length=128, upload_to='city/')
总结
关于django的开发知识点,更多的案例:
-
Python基础(课件 https://gitee.com/wupeiqi/python_course)
https://www.bilibili.com/video/BV1m54y1r7zE
-
并发编程(进程线程协程)
https://www.bilibili.com/video/BV1Ev411G7i3?spm_id_from=333.999.0.0 # 不建议小白学(协程) https://www.bilibili.com/video/BV1NA411g7yf?spm_id_from=333.999.0.0
-
MySQL数据库
# 2021最新推荐 https://www.bilibili.com/video/BV15R4y1b7y9?spm_id_from=333.999.0.0 # 2017年 https://www.bilibili.com/video/BV1DE411n7fU?
-
前端开发
https://www.bilibili.com/video/BV1QE411j7bV?spm_id_from=333.999.0.0
-
django开发知识点
https://www.bilibili.com/video/BV1zE411x7LG https://www.bilibili.com/video/BV1JE411V7xk
-
项目开发
任务管理平台:https://www.bilibili.com/video/BV1uA411b77M
-
进阶项目(增删改查、权限)
https://space.bilibili.com/283478842/channel/detail?cid=91596&ctype=0
-
前后端分离的项目: django + drf框架 + vue.js
- Django - drf框架 - https://www.bilibili.com/video/BV1ZE411j7RK
-
git 版本控制和协同开发 + 任务管理平台
https://www.bilibili.com/video/BV19E411f76x?spm_id_from=333.999.0.0
-
微信小程序 + Django + drf框架编写
https://www.bilibili.com/video/BV1jC4y1s7QD?spm_id_from=333.999.0.0