pip install django
c:\python39
- python.exe
- Scripts
- pip.exe
- django-admin.exe 【工具,创建django项目中的文件和文件夹】
- Lib
- 内置模块
- site-packages
- openpyxl
- python-docx
- flask
- django 【框架的源码】
django中项目会有一些默认的文件和默认的文件夹。
打开终端。
进入某个目录(项目放在哪里)。
/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)]
注意:
- 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 【接收网络请求】【不要动】
- 项目
- 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
确保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)]
- url -> 函数
- 函数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jHhyQD9f-1690794616342)(assets/image-20211124101708419.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zScWppLG-1690794616342)(assets/image-20211124102815510.png)]
在开发过程中一般将:
都会当做静态文件处理。
在app目录下创建static文件夹。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-foitRgki-1690794616343)(assets/image-20211124103828667.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fGwOHmCj-1690794616343)(assets/image-20211124103947169.png)]
本质上:在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)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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)]
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)]
pip install mysqlclient
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JbJLTE3e-1690794616347)(assets/image-20211124152339567.png)]
ORM可以帮助我们做两件事:
创建、修改、删除数据库中的表(不用你写SQL语句)。 【无法创建数据库】
操作表中的数据(不用写SQL语句)。
启动MySQL服务
自带工具创建数据库
create database gx_day15 DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KrvrYMM0-1690794616347)(assets/image-20211124153042996.png)]
在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)]
创建表:在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
# #### 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)
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("删除成功")
主题:员工管理系统
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WCXbc0sm-1690794616349)(E:\django\day15.assets\image-20211125083543235.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SuC8AlHQ-1690794616349)(E:\django\day15.assets\image-20211125083701911.png)]
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)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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)
工具连接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)]
static目录
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RA2prnAB-1690794616352)(E:\django\day15.assets\image-20211125095750076.png)]
体验,最原始方法来做。
Django中提供Form和ModelForm组件(方便)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9BHHWnAm-1690794616352)(E:\django\day15.assets\image-20211125100519237.png)]
定义目版:layout.html
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<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 %}
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组件
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})
<form method="post">
{% for field in form%}
{{ field }}
{% endfor %}
form>
<form method="post">
{{ form.user }}
{{ form.pwd }}
{{ form.email }}
form>
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)
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})
<form method="post">
{% for field in form%}
{{ field }}
{% endfor %}
form>
<form method="post">
{{ form.user }}
{{ form.pwd }}
{{ form.email }}
form>
部门管理
用户管理
用户列表
新建用户
- ModelForm,针对数据库中的某个表。
- Form。
点击编辑,跳转到编辑页面(将编辑行的ID携带过去)。
编辑页面(默认数据,根据ID获取并设置到页面中)
提交:
错误提示
数据校验
在数据库更新
models.UserInfo.filter(id=4).update(...)
见代码。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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)
URL
函数
获取所有的靓号
结合html+render将靓号罗列出来
id 号码 价格 级别(中文) 状态(中文)
列表点击跳转:/pretty/add/
URL
ModelForm类
from django import forms
class PrettyModelForm(forms.ModelForm):
...
函数
点击提交
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iBAgglFl-1690794616353)(E:\django\day15.assets\image-20211126111252278.png)]
/pretty/数字/edit/
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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)
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)
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()
分页的逻辑和处理规则
封装分页类
小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
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
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组件,在我们开发增删改查功能。
Cookie和Session,用户登录信息保存起来。
中间件,基于中间件实现用户认证 ,基于:process_request
。
ORM操作
models.User.objects.filter(id="xxx")
models.User.objects.filter(id="xxx").order_by("-id")
分页组件。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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 + 对话框的形式实现的页面的增删改查。
更多参考文档:https://echarts.apache.org/handbook/zh/get-started
编码
编码基础知识点: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
字符串类型
- 不可变类型;
- 常见方法: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")
定义
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()
分类
- 自定义模块:自己写文件/文件夹
- 内置模块: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功能强大)
- 面向对象的三大特性:封装、继承、多态。
- 理解,读懂源码和代码。
- 数据库
- 表
- 数据行
更多知识: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()
HTML
- 块级和行内标签(div、span)
块级:div/h系列
行内:span/a (设置高度、宽度、边距无效)
- Form表单
- 关于a标签
百度 超链接去跳转。
做锚点
第一章
第二章
第一章 谢新雪
第二章 单独的
CSS
- 位置
- 标签
- 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() dd
$("#x1").text("xxx") xxx
$("#x1").val()
$("#x1").val("xxx")
$("#x1").attr("uu") dd
$("#x1").attr("uu","999") dd
$("#x1").empty() dd - 清空内容
$("#x1").remove() dd - 整个标签删除
-
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//delete/' , admin.admin_delete),
re_path('admin/(?P\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': []}>
# print(request.FILES) # 请求发过来的文件 {}
file_object = request.FILES.get("avatar")
# print(file_object.name) # 文件名:[email protected]
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': }
# 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.*)$', 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': }
# 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