- Django学习
- 1、项目创建
- 2、默认项目介绍
- 3、app的创建和说明
- 4、启动运行Django
- 4.1**确保app已注册**
- 4.2 **编写URL和视图函数的对应关系【urls.py】**
- 4.3**编写视图函数【views.py】**
- 4.4**启动Django项目**
- 4.5、templates模板
- 4.6、静态文件
- 5、模板语法
- **案例:伪联通新闻中心**
- 6、请求和响应
- 案例:用户登录
- 7、数据库操作
- 7.1、安装mysqlclient
- 7.2、orm创建数据库
- 1、创建数据库
- 2、Django连接数据库
- 3、Django操作表
- 3.1、创建表
- 3.2、执行命令
- 3.3、操作表中的数据
- 案例:用户管理
- 1.、展示用户列表
- 2、添加用户
- 3、删除用户
- 8、员工管理系统
- 8.1、创建项目
- 8.2、创建app,终端运行 **python manage.py startapp xxx**
- 8.3、注册app
- 8.4、设计表结构
- 8.5、配置数据库
- 8.6、生成表
- 8.7、创建静态文件和模板文件
- 8.8、部门管理
- 8.8.1、urls
- 8.8.2、views
- 9、html继承
- 10、用户管理
- 10.2、用户列表
- 10.3、添加用户
- 10.3.1、初识Form
- 1、views.py
- 2、user_add.html
- 10.3.2、ModelForm(最简便)
- 1、models.py
- 2、views.py
- 10.3.3、添加用户
- 1、views.py
- 2、html
- 10.4、编辑用户
- 11、总结-1
- 12、 靓号管理
- 搜索
- 分页
- 13、管理员操作
- 14、用户登录
- 14.1、session登录
- 14.2、Django的中间件
- 14.3、编写登录中间件
- 14.4、注销
- 14.5、模板登录信息
- 14.5、图片验证码
- 5.1、生成图片
- 5.2、函数
- 5.3、urls路径
- 5.4、视图
- 5.5、前端
- 14.6、完整的登录
- 6.1 urls
- 6.2 视图
- 6.3、页面
- 15、Ajax
- 15.1、get请求
- 15.2、post请求
- 15.3、关闭绑定事件
- 15.4、Ajax请求的返回值
- 16、订单
- html
- 视图
- 17、文件上传
- 17.1、基本操作
- 17.2、Excel批量上传
- 17.3、混合数据(form)
- 17.4、启用media,存数据
- 17.5、混合数据(ModelForm)
- Django 函数+知识点
- 分页 --类
- bootstrap样式-父类
- 封装
- md5加密
- 数据库中获取数据
- 柱状图
- 总结
pycharm:
-
新建项目
-
删除templates
-
删除settings里的。。为了不在根目录寻找而是创建的目录下寻找templates目录
-
修改__ init __.py
import pymysql pymysql.install_as_MySQLdb()2、默认项目介绍
djangostudy
manage.py 【项目的管理,启动项目、创建app、数据管理】【不要动】
djangostudy
__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】
。。。
创建:
app01
__init__.py
admin.py 【固定,不用动】Django默认提供了admin后台管理
apps.py 【固定,不用动】app启动类
migrations 【固定,不用动】数据库变更记录
__init__.py
models.py 【**重要**】对数据库操作
tests.py 【固定,不用动】单元测试
views.py 【**重要**】,函数
4、启动运行Django
4.1确保app已注册
4.2 编写URL和视图函数的对应关系【urls.py】
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z8jJ9pAL-1654077355201)(https://gitee.com/cool-dada/blog_img/raw/master/tree/master/img_markdown/202206011745585.png)]
4.3编写视图函数【views.py】[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iR3AT8Nb-1654077355201)(https://gitee.com/cool-dada/blog_img/raw/master/tree/master/img_markdown/202206011745336.png)]
4.4启动Django项目 4.5、templates模板 4.6、静态文件在开发过程中一般将 图片、css、js都会当做静态文件处理
static文件夹下存放静态文件
- plugins:用于存放插件
插件使用+引入
{% static ‘路径’ %}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XXMKjNKJ-1654077355204)(https://gitee.com/cool-dada/blog_img/raw/master/tree/master/img_markdown/202206011746076.png)]
5、模板语法本质上:在html中写一些占位符,由数据对这些占位符进行替换和处理。
views
def tpl(request):
name = '李锦彪'
roles = ['李锦彪', '黄欣宇', '锦欣宇'] # 列表
user_info = {'name': '李锦彪', 'salary': 26000, 'role': 'ceo'} # 字典
data_list = [ # 列表里套字典
{'name': '李锦彪', 'salary': 26000, 'role': 'ceo'},
{'name': '李锦彪', 'salary': 26000, 'role': 'ceo'},
{'name': '李锦彪', 'salary': 26000, 'role': 'ceo'}
]
return render(request,
'tpl.html', # 传入html
{ # 传入一个字典,html通过{{ key }}获取value
'n1': name,
'n2': roles,
'n3': user_info,
'n4': data_list,
}
)
html
{# 获取传入的值 #}
{{ n1 }}
============================================
{# 获取传入的列表值 #}
{# 一个一个拿 #}
{{ n2.0 }}
{{ n2.1 }}
{{ n2.2 }}
{# 循环拿 #}
{% for item in n2 %}
{{ item }}
{% endfor %}
{# 加条线 #}
==============================================
{# 获取字典的值 #}
{{ n3 }}
{# 根据字典的键获取值 #}
{{ n3.name }}
{{ n3.salary }}
{{ n3.role }}
{# 循环获取 #}
{# 第一种 #}
{# {% for item in n3 %}#}
{# {{ item }} #}
{# {% endfor %}#}
{# 第二种 #}
{% for k, v in n3.items %}
{{ k }}={{ v }}
{% endfor %}
===============================================
{% if n1 == '李锦彪' %}
哈哈哈哈
{% else %}
黑恶hi诶嘿二哈IE
{% endif %}
视图函数的render内部:
- 读取含有模板语法的html文件
- 内部进行渲染(模板语法执行并替换数据),最终得到只包含html标签的字符串
- 将渲染(替换)完成的字符串返还给用户浏览器
**第一步:**urls.py中创建路径
第二步:views.py中创建函数news
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tvSZ7kfc-1654077355206)(https://gitee.com/cool-dada/blog_img/raw/master/tree/master/img_markdown/202206011746481.png)]
第三步:编写html文件
联通新闻中心
-
{% for item in news_list %}
- {{ item.news_title }} {% endfor %}
关于重定向:当前的页面请求访问其他的页面。其他的页面不同意并且会返回一个值,告诉当前的页面去访问这个值
# request 是一个对象,封装了用户发送过来的所有请求相关数据
# 1.【请求】获取请求方式 get/post
print(request.method)
# 2.【请求】在URL上传递值 http://127.0.0.1:8000/something/?n=100
print(request.GET) # 拿到传递的值
# 3.【请求】post请求,在请求体中传递数据
print(request.POST)
# 4.【响应】HttpResponse('返回内容'),内容字符串返回给请求者
# return HttpResponse('返回内容')
# 5.【响应】读取html内容 + 渲染(替换) -> 字符串,返回内容给用户浏览器
# return render(request, 'something.html', {'title': '李锦彪'})
# 6.【响应】让浏览器重定向到其他的页面redirect('https://www.baidu.com')
return redirect('https://www.baidu.com')
案例:用户登录
问题:安全机制校验
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cKuj760e-1654077355207)(https://gitee.com/cool-dada/blog_img/raw/master/tree/master/img_markdown/202206011752654.png)]
解决办法:form表单里加 {% csrf_token %}
第一步:views.py
def login(request):
if request.method == 'GET':
return render(request, 'login.html')
# 如果是post请求,获取用户提交的数据
# print(request.POST)
usr = request.POST.get('username')
pwd = request.POST.get('password')
if usr == '15751083927' and pwd == '123':
# return HttpResponse('登录成功')
return redirect('https://www.baidu.com') # 登录成功重定向跳转页面
else:
# return HttpResponse('登录失败')
return render(request, 'login.html', {'error_msg': '登录失败'})
第二步:html
Title
用户登录
7、数据库操作
Django开发操作数据库,内部提供了orm框架
7.1、安装mysqlclient 7.2、orm创建数据库orm可以帮助我们做两件事:
- 创建、修改、删除数据库中的表(不用写SQL语句)(无法创建数据库)
- 操作表中的数据(不用写SQL语句)
- 启动数据库
- 自带工具创建数据库
在setting.py文件中,进行配置和修改
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'ljb', # 数据库名字
'USER': 'root', # 账号
'PASSWORD': '187365', # 密码
'HOST': '127.0.0.1', # 主机
'PORT': 3306, # 端口号
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-18oVfvWK-1654077355208)(https://gitee.com/cool-dada/blog_img/raw/master/tree/master/img_markdown/202206011746040.png)]
3、Django操作表- 创建表
- 修改表
- 删除表
在models.py文件中
# 创建表
class Userinfo(models.Model):
name = models.CharField(max_length=32) # varchar(32)
password = models.CharField(max_length=64)
age = models.IntegerField() # int 类型
==相当于
# create table app01_userinfo( # 表明为:app01+类名首字母小写
# id bigint auto_increment primary key , # Django自动加这一行
# name varchar(32),
# password varchar(64),
# age int
# );
3.2、执行命令
在终端执行:
python manage.py makemigrations python manage.py migrate
注意:app先注册(settings)
新增列的时候,由于已经在列中可能已有数据,所以新增列必须要指定新增列对应的数据
- 手动输入一个值
- 设置默认值
age = models.IntegerField(default=2)
- 允许为空
age = models.IntegerField(null=True, blank=True)
以后在开发中如果想要操作对表结构进行调整
-
在models.py文件中操作即可
-
在终端执行命令
python manage.py makemigrations python manage.py migrate
在views.py中
def orm(request):
from app01 import models # 导入models文件
# 测试orm表操作表中的数据
# #########新建表数据##########
# models.Userinfo.objects.create(name='李锦彪', password='187365', age=18)
# models.Userinfo.objects.create(name='黄欣宇', password='187365', age=18)
# models.Userinfo.objects.create(name='锦欣宇', password='187365', age=18)
# ############删除表数据#############
# 先筛选 filter(xx=xx)
# 再删除 delete()
# models.Userinfo.objects.filter(name='李锦彪').delete()
# all全部删除
# models.Userinfo.objects.all()
# ############获取表数据#############
# data_list = [行,行。。。] QuerySet类型的数据
# 拿到所有数据#############
# data_list = models.Userinfo.objects.all()
# print(data_list)
# for obj in data_list:
# print(obj.name, obj.password, obj.age)
# 筛选数据#############
# data_row = models.Userinfo.objects.filter(name='黄欣宇')[0] # [0]可以改为.first()
# print(data_row.name, data_row.password, data_row.age)
# ############更新表数据#############
models.Userinfo.objects.filter(name='黄欣宇').update(age=28)
return HttpResponse('成功!')
案例:用户管理
1.、展示用户列表
- url
- 函数
- 获取所有用户的信息
- html渲染
def info_list(request):
# 1.获取数据库中所有用户的信息
from app01.models import Userinfo
data_list = Userinfo.objects.all()
print(data_list)
# 2.渲染获取到数据
return render(request, 'info_list.html', {'data_list': data_list})
Title
info_list
| ID | 姓名 | 性别 | 年龄 |
|---|---|---|---|
| {{ obj.id }} | {{ obj.name }} | {{ obj.password }} | {{ obj.age }} |
- url
- 函数
- get ,看到页面,输入内容
- post,提交->写入到数据库
def info_add(request):
if request.method == "GET":
return render(request, 'info_add.html')
# 获取用户提交的数据
user = request.POST.get("user")
pwd = request.POST.get("pwd")
age = request.POST.get("age")
# 加入到数据库
from app01.models import Userinfo
Userinfo.objects.create(name=user, password=pwd, age=age)
# 自动跳转
return redirect('/info/list')
Title
添加用户
3、删除用户
- url
- 函数
def info_delete(request):
nid = request.GET.get('nid')
from app01.models import Userinfo
Userinfo.objects.filter(id=nid).delete()
return redirect('/info/list')
Title
info_list
添加
| ID | 姓名 | 性别 | 年龄 | 操作 |
|---|---|---|---|---|
| {{ obj.id }} | {{ obj.name }} | {{ obj.password }} | {{ obj.age }} | 删除 |
删除templates文件夹,删除
8.2、创建app,终端运行 python manage.py startapp xxx 8.3、注册app 8.4、设计表结构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=32)
password = models.CharField(verbose_name='密码', max_length=64)
age = models.IntegerField(verbose_name='密码')
sex_choice = (
(True, '男'),
(False, '女')
)
sex = models.BooleanField(verbose_name='性别', choices=sex_choice)
account = models.DecimalField(verbose_name='账户余额', max_digits=10, decimal_places=2, default=0)
create_time = models.DateTimeField(verbose_name='入职时间')
# title_id = models.BigIntegerField(verbose_name='部门ID') 无约束
# 1.有约束(外键)
# to:与哪张表关联
# to_field:表中的某一列关联
# 生成列;depart_id
# depart = models.ForeignKey(to="Department", to_field="id")
# 2.部门表被删除
# 2.1 级联删除
# depart = models.ForeignKey(to="Department", to_field="id", on_delete=models.CASCADE)
# 2.2 置空
depart = models.ForeignKey(verbose_name='部门', to="Department", to_field="id",
null=True, blank=True, on_delete=models.CASCADE)
8.5、配置数据库
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'ljb', # 数据库名字
'USER': 'root', # 账号
'PASSWORD': '187365', # 密码
'HOST': '127.0.0.1', # 主机
'PORT': 3306, # 端口号
}
}
8.6、生成表
python manage.py makemigrations python manage.py migrate
注意:
报错:
解决:
原因:PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库,Python2中则使用mysqldb。
MySQLdb并不支持Python3.
urlpatterns = [
# path('admin/', admin.site.urls),
path('depart/list/', views.depart_list),
path('depart/delete/', views.depart_delete),
# http://127.0.0.1:8000/depart/12/edit/
# http://127.0.0.1:8000/depart/1/edit/
# http://127.0.0.1:8000/depart/16/edit/
path('depart//edit/', views.depart_edit),
]
8.8.2、views
重定向:要引入 redirect
from django.shortcuts import render, redirect
from Employee import models
def depart_list(request):
if request.method == "GET":
# 1.去数据库中获得所有的列表
data_list = models.Department.objects.all()
return render(request, 'depart_list.html', {'data_list': data_list})
# 2.添加部门
# 获取对象
data_department = request.POST.get('department')
# 添加对象
models.Department.objects.create(title=data_department)
# 重定向
return redirect('/depart/list/')
def depart_delete(request):
"""删除部门"""
# 获取id
# http://127.0.0.1:8000/depart/delete/?nid=1
nid = request.GET.get('nid')
# 删除id
models.Department.objects.filter(id=nid).delete()
# 重定向返回部门列表
return redirect('/depart/list/')
def depart_edit(request, nid):
"""编辑部门"""
if request.method == "GET":
row_data = models.Department.objects.filter(id=nid).first()
return render(request, 'depart_edit.html', {'row_data': row_data})
# 获取表单内容
title = request.POST.get('department')
# 根据id更新
models.Department.objects.filter(id=nid).update(title=title)
return redirect('/depart/list/')
9、html继承
- 可以有多个block
母版:
{% load static %}
Title
{% block css %}{% endblock %}
{% block content %}{% endblock %}
{% block js %}{% endblock %}
继承母版:
{% extends 'layout.html' %}
{% block css %}
{% endblock %}
{% block content %}
{% endblock %}
{% block js %}
{% endblock %}
10、用户管理
Django中对于一些选项的元组存元组形式获取元组中的值:对象.get_属性_display()
例:
sex_choice = (
(0, '男'),
(1, '女')
)
sex = models.SmallIntegerField(verbose_name='性别', choices=sex_choice)
取法:
obj.get_sex_display()
html中
外键获取另一个表的值
{% for obj in user_lists %}
{{ obj.id }}
{{ obj.name }}
{{ obj.password }}
{{ obj.get_sex_display }}
{{ obj.age }}
{{ obj.depart.title }} # 外键获取另一个表的值
{{ obj.account }}
{{ obj.create_time }}
{% endfor %}
10.2、用户列表
时间输出格式
{% for obj in user_lists %}
{{ obj.id }}
{{ obj.name }}
{{ obj.password }}
{{ obj.get_sex_display }}
{{ obj.age }}
{{ obj.depart.title }}
{{ obj.account }}
{{ obj.create_time|date:"Y-m-d" }} # 时间输出格式
{# 编辑#}
{# 删除#}
{% endfor %}
10.3、添加用户
- 原始方式思路:不会采用(本质)【麻烦】
- 用户提交数据没有校验 - 错误,页面应该有提示 - 页面上每一个字段都需要重新写 - 关联的数据,手动去获取并展示在页面
- Django组件
- Form组件(小简便)
- ModelForm组件(最简便)
class MyForm(Form):
user = forms.CharFiled(widget=forms.Input)
pwd = forms.CharFiled(widget=forms.Input)
email = forms.CharFiled(widget=forms.Input)
def user_list(request):
if request.method == "GET":
form = MyForm() # 实例化
return render(request, 'user_list.html', {'form': form})
2、user_add.html
或:
10.3.2、ModelForm(最简便) 1、models.pyclass Userinfo(models.Model):
"""员工表"""
name = models.CharField(verbose_name='姓名', max_length=32)
password = models.CharField(verbose_name='密码', max_length=64)
age = models.IntegerField(verbose_name='密码')
sex_choice = (
(0, '男'),
(1, '女')
)
sex = models.SmallIntegerField(verbose_name='性别', choices=sex_choice)
account = models.DecimalField(verbose_name='账户余额', max_digits=10, decimal_places=2, default=0)
create_time = models.DateField(verbose_name='入职时间')
# 2.1 级联删除
depart = models.ForeignKey(to="Department", to_field="id", on_delete=models.CASCADE)
2、views.py
class MyForm(ModelForm):
class Meta:
model = UserInfo
fields = ["name", "password", "age"]
def user_list(request):
if request.method == "GET":
form = MyForm() # 实例化
return render(request, 'user_list.html', {'form': form})
10.3.3、添加用户
1、views.py
# ################################### ModelForm 实例 ###############
from django import forms
class UserModelForm(forms.ModelForm):
# 添加其他的判断
name = forms.CharField(min_length=2, max_length=12, label="用户名")
class Meta:
model = models.Userinfo
fields = ["name", "password", "age", "sex", "account", "depart", "create_time"] # 添加表中的字段
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) # 继承
# 循环找到所有,添加样式
for name, field in self.fields.items():
field.widget.attrs = {"class": "form-control", "placeholder": field.label}
def user_add(request):
"""添加用户 ModelForm版本"""
if request.method == "GET":
form = UserModelForm() # 实例化一个对象
return render(request, 'user_modelform.html', {"form": form})
# 用户 post 提交数据,数据校验
form = UserModelForm(data=request.POST)
if form.is_valid(): # 判断数据是否合法
# 如果数据合法,提交数据
form.save() # 自动保存,定义哪个,保存哪个
return redirect('/user/list/')
# 校验失败(在页面上提示信息)
return render(request, 'user_modelform.html', {"form": form})
2、html
10.4、编辑用户
-
点击编辑,跳转到编辑页面(将编辑的id携带过去)
-
编辑页面(默认数据,根据id获取并设置到页面中)
-
提交:
- 错误提示
- 数据校验
- 再数据库更新
def user_edit(request, nid):
"""编辑用户"""
# 根据id获取要编辑的哪一行数据
row_object = models.Userinfo.objects.get(id=nid)
if request.method == 'GET':
form = UserModelForm(instance=row_object)
return render(request, 'user_edit.html', {'form': form})
# 保存数据
form = UserModelForm(data=request.POST, instance=row_object)
if form.is_valid():
form.save()
return redirect('/user/list/')
# 错误信息提示
return render(request, 'user_edit.html', {'form': form})
html和添加一样
11、总结-1ModelForm 针对数据库中的某个表 Form12、 靓号管理 搜索
# 字典
data_dict = {'id': 12}
row_data = models.Mobile.objects.filter(**data_dict)
# 数字
models.Mobile.objects.filter(id=12) # 等于12
models.Mobile.objects.filter(id__gt=12) # 大于12
models.Mobile.objects.filter(id__gte=12) # 大于等于12
models.Mobile.objects.filter(id__lt=12) # 小于12
models.Mobile.objects.filter(id__lte=12) # 小于等于12
data_dict = {'id__lte': 12}
row_data = models.Mobile.objects.filter(**data_dict)
# 字符串
models.Mobile.objects.filter(mobile__startwith='12') # 以 12 开头
models.Mobile.objects.filter(mobile__endwith='12') # 以 12 结尾
models.Mobile.objects.filter(mobile__contains='12') # 包含 12
models.Mobile.objects.filter(mobile='12') # 等于 12
分页
# 分页查询:根据用户想要访问的页码,计算出起始位置
page = int(request.GET.get('page', 1))
page_size = 8 # 每页想显示多少条数据
start = (page - 1) * page_size
end = page * page_size
# 总数据
data_count = models.Mobile.objects.filter(**data_dict).count() # 获得一共有多少条数据
total_page_count, div = divmod(data_count, page_size) # 求总页码数
if div:
total_page_count += 1 # 总页码
# 计算出,显示当前页的前几个,后几个
plus = 2
if total_page_count <= 2 * plus + 1:
# 数据库中的数据比较少
start_page = 1
end_page = total_page_count
else:
# 数据库中的数据比较多 > 5页
if page <= plus: # 当前页 < 2 时(极小值)
start_page = 1
end_page = 2 * plus + 1
else: # 当前页大于 2
if (page + plus) > total_page_count: # 判断最后的极大值
start_page = total_page_count - 2 * plus
end_page = total_page_count
else: # 中间情况
start_page = page - plus
end_page = page + plus
# 页码
page_str_list = [] # 储存html页码数 "admin.py
from django.shortcuts import render, redirect
from Employee import models
from Employee.utils.form import AdminModel, AdminEditModel
from Employee.utils.pagination import Pagination
def admin_list(request):
"""管理员列表"""
# 搜索
data_dict = {}
search_data = request.GET.get('q', "")
if search_data:
data_dict["username__contains"] = search_data
data_list = models.Admin.objects.filter(**data_dict)
queryset_object = Pagination(request, data_list)
dic_context = {
"data_list": queryset_object.page_queryset, # 数据
"page_string": queryset_object.html(), # 页码
"search_data": search_data, # 搜索得数据
}
if search_data and not queryset_object.page_queryset: # 搜索了,但没有符合的
dic_context.update({'error': '对不起,号码不存在'})
return render(request, 'mobile_list.html', dic_context)
return render(request, 'admin_list.html', dic_context)
def admin_add(request):
"""添加管理员"""
title = '新建管理员'
if request.method == 'GET':
form = AdminModel()
dic_context = {
'form': form,
'title': title,
}
return render(request, 'add.html', dic_context)
form = AdminModel(data=request.POST)
if form.is_valid():
# form.cleaned_data 获得所有输入的值
form.save()
return redirect('/admin/list/')
dic_context = {
'form': form,
'title': title,
}
return render(request, 'add.html', dic_context)
def admin_edit(request, nid):
"""编辑管理员"""
# 对象/None
row_data = models.Admin.objects.filter(id=nid).first()
if not row_data: # 判断数据是否存在
# return render(request, 'error.html', {'error': '数据不存在'})
return redirect('/admin/list/')
title = '修改密码' # 标题名
if request.method == "GET": # get请求显示页面
form = AdminEditModel(instance=row_data, pwd=row_data.password)
username = row_data.username
return render(request, "add.html", {'form': form, 'title': title, 'username': username, 'user_name': '用户名:'})
form = AdminEditModel(instance=row_data, data=request.POST, pwd=row_data.password)
if form.is_valid(): # 判断输入是否合理
form.save()
return redirect('/admin/list/')
return render(request, "add.html", {'form': form, 'title': title})
def admin_delete(request):
nid = request.GET.get('nid')
models.Admin.objects.filter(id=nid).delete()
return redirect('/admin/list/')
form.py
class AdminModel(BootStrapModelForm):
confirm_password = forms.CharField(
label="确认密码",
# widget=forms.PasswordInput(render_value=True), # (render_value=True) 密码不同时,不会置空,默认是False置空
widget=forms.PasswordInput
)
class Meta:
model = models.Admin
fields = ["username", "password", "confirm_password"]
widgets = {
# (render_value=True) 密码不同时,不会置空,默认是False置空
# 'password': forms.PasswordInput(render_value=True)
'password': forms.PasswordInput
}
def clean_password(self):
password = self.cleaned_data.get('password') # 获得输入的password
return md5(password) # 返回md5加密后的值
def clean_confirm_password(self):
password = self.cleaned_data.get('password') # 获得的password是 上面 返回的值
confirm_password = self.cleaned_data.get('confirm_password')
if password != md5(confirm_password):
raise ValidationError('密码不一致,请重新输入!')
return confirm_password # return 什么,保存到数据库的值就是什么
class AdminEditModel(AdminModel):
# class AdminEditModel(BootStrapModelForm):
edit_password = forms.CharField(label='新密码', widget=forms.PasswordInput)
class Meta:
model = models.Admin
fields = ["password", 'edit_password', "confirm_password"] # 添加谁出现谁
widgets = {
'password': forms.PasswordInput
}
def clean_password(self):
password = self.cleaned_data.get('password') # 获得输入的password
if self.pwd != md5(password):
raise ValidationError('密码输入错误')
return md5(password) # 返回md5加密后的值
def clean_edit_password(self):
edit_password = self.cleaned_data.get('edit_password') # 获得输入的password
return md5(edit_password)
def clean_confirm_password(self):
edit_password = self.cleaned_data.get('edit_password') # 获得的password是 上面 返回的值
confirm_password = self.cleaned_data.get('confirm_password')
if edit_password != md5(confirm_password):
raise ValidationError('密码不一致,请重新输入!')
return confirm_password # return 什么,保存到数据库的值就是什么
def __init__(self, pwd, *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}
self.pwd = pwd
14、用户登录
什么是cookie和session?
http、https
session存储在数据库或Redis或文件
14.1、session登录在其他需要登录才能访问的页面中,都需要加入:
def index(request):
# 检查用户是否已经登录,已登录继续往下走,没有跳转到登录界面
# 获取请求用户的随机字符串,看看session中有没有
# request.session['info']
info = request.session.get('info')
if not info:
return redirect('/login/')
......
目标:在所有视图前面加上 上面判断
14.2、Django的中间件中间件存方在 django_session 数据库中
- 定义中间件
from django.utils.deprecation import MiddlewareMixin
class M1(MiddlewareMixin):
"""中间件1"""
def process_request(self, request):
# 如果方法中没有返回值(None),意味着可以继续往下走
# 如果有返回值 HttpResponse render redirect
print('m1, 进来了')
def process_response(self, request, response):
print('m1.走了')
return response
class M2(MiddlewareMixin):
"""中间件2"""
def process_request(self, request):
print('m2, 进来了')
def process_response(self, request, response):
print('m2.走了')
return response
- 注册中间件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I6nggq39-1654077355213)(https://gitee.com/cool-dada/blog_img/raw/master/tree/master/img_markdown/202206011747008.png)]
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',
'Employee.middleware.auth.M1',
'Employee.middleware.auth.M2',
]
- 在中间件中的process_request()方法
# 如果方法中没有返回值(None),意味着可以继续往下走 # 如果有返回值 HttpResponse render redirect14.3、编写登录中间件
from django.shortcuts import redirect
from django.utils.deprecation import MiddlewareMixin
class AuthMiddlewareMixin(MiddlewareMixin):
"""登录"""
def process_request(self, request):
# 排除不需要登录,就能访问的页面
# request.path_info 获取用户请求的url /login/
if request.path_info == '/login/':
return
# 1,读取当前访问的用户的session信息,如果能读到,说明已经登录过,就可以继续向后走
info_dict = request.session.get('info')
if info_dict: # 正确继续往后走
return # 返回空就是可以继续往后走
# 2,如果没有登录,回到登录页面
return redirect('/login/')
14.4、注销
def logout(request):
"""注销"""
request.session.clear() # 清除当前的session
return redirect('/login/')
14.5、模板登录信息
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-imF7gHiL-1654077355213)(https://gitee.com/cool-dada/blog_img/raw/master/tree/master/img_markdown/202206011747603.png)]
14.5、图片验证码 5.1、生成图片pip install pillow5.2、函数
from PIL import Image, ImageDraw, ImageFont, ImageFilter
import random
def check_code(width=100, height=32, char_length=5, font_file=r'Employee/static/plugins/font-text/Monaco.ttf', font_size=28):
code = []
img = Image.new(mode='RGB', size=(width, height), color=(255, 255, 255))
draw = ImageDraw.Draw(img, mode='RGB')
def rndChar():
"""
生成随机字母
:return:
"""
return chr(random.randint(65, 90))
def rndColor():
"""
生成随机颜色
:return:
"""
return random.randint(0, 255), random.randint(10, 255), random.randint(64, 255)
# 写文字
font = ImageFont.truetype(font_file, font_size)
for i in range(char_length):
char = rndChar()
code.append(char)
h = random.randint(0, 4)
draw.text([i * width / char_length, h], char, font=font, fill=rndColor())
# 写干扰点
for i in range(30):
draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor())
# 写干扰圆圈
for i in range(30):
draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor())
x = random.randint(0, width)
y = random.randint(0, height)
draw.arc((x, y, x + 4, y + 4), 0, 90, fill=rndColor())
# 画干扰线
for i in range(3):
x1 = random.randint(0, width)
y1 = random.randint(0, height)
x2 = random.randint(0, width)
y2 = random.randint(0, height)
draw.line((x1, y1, x2, y2), fill=rndColor())
img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)
return img, ''.join(code) # 返回图片和验证码
# if __name__ == '__main__':
# img, strs = check_code()
# with open('code.png', 'wb') as f:
# img.save(f, format='png')
# print(strs)
# # 1. 直接打开
# # img,code = check_code()
# # img.show()
# #
# # 2. 写入文件
# # img,code = check_code()
# # with open('code.png','wb') as f:
# # img.save(f,format='png')
# #
# # 3. 写入内存(Python3)
# # from io import BytesIO
# # stream = BytesIO()
# # img.save(stream, 'png')
# # stream.getvalue()
# #
# # 4. 写入内存(Python2)
# # import StringIO
# # stream = StringIO.StringIO()
# # img.save(stream, 'png')
# # stream.getvalue()
5.3、urls路径
path('image/code/', account.image_code),
5.4、视图
BytesIO介绍:https://blog.csdn.net/Victor2code/article/details/105637945
def image_code(request):
"""生成图片验证码"""
# 调用pillow函数,生成图片
img, code_str = check_code()
# 写入到自己的session中(以便后获取验证码再进行校验)
request.session['code_str'] = code_str
# 给session设置60秒超时,后续成功登录后需要重新设置
request.session.set_expiry(60)
# 导入io模块将图片传给前段
from io import BytesIO
stream = BytesIO()
img.save(stream, 'png')
return HttpResponse(stream.getvalue())
5.5、前端
{# 验证码 #}
{{ form.code }}
{{ form.code.errors.0 }}
14.6、完整的登录
6.1 urls
# 登录
path('login/', account.login),
path('logout/', account.logout),
# 图片验证码
path('image/code/', account.image_code),
6.2 视图
from django.shortcuts import render, redirect, HttpResponse
from django import forms
from Employee import models
from Employee.utils.createImg import check_code
from Employee.utils.encrypt import md5
class LoginForm(forms.Form):
username = forms.CharField(label='用户名',
widget=forms.TextInput,
required=True, # 不为空, 默认的
)
password = forms.CharField(label='密码', widget=forms.PasswordInput, required=True)
code = forms.CharField(label='验证码', widget=forms.TextInput, required=True)
def clean_password(self):
password = self.cleaned_data.get('password')
return md5(password) # 返回加密后的值
def login(request):
"""登录"""
if request.method == 'GET':
form = LoginForm()
return render(request, 'login.html', {'form': form})
form = LoginForm(data=request.POST)
if form.is_valid():
# 验证成功,获取到的用户名和密码
# print(form.cleaned_data) 返回的是字典
# 验证码校验
user_input_code = form.cleaned_data.pop('code') # 获取用户输入的code,并且删去;以防占用内存
auth_image_code = request.session.get('code_str', '') # 获取真正的图片验证码
if auth_image_code.upper() != user_input_code.upper(): # 验证码不正确,返回错误数据
form.add_error('code', '验证码错误')
return render(request, 'login.html', {'form': form})
# 去数据库校验
# models.Admin.objects.filter(username=xxx, password=xxx).first()
admin_object = models.Admin.objects.filter(**form.cleaned_data).first() # 传入一个字典
if not admin_object:
form.add_error('password', '用户名或密码错误')
return render(request, 'login.html', {'form': form})
# 登录成功
# session 存储用户名
request.session['info'] = {'id': admin_object.id, 'username': admin_object.username}
request.session.set_expiry(60 * 60 * 24 * 7) # 重新设置登录超时7天;因为在获取验证码时设置了过期时间,所有需要重新设置
return redirect('/admin/list/')
return render(request, 'login.html', {'form': form})
def logout(request):
"""注销"""
request.session.clear() # 清除当前的session
return redirect('/login/')
def image_code(request):
"""生成图片验证码"""
# 调用pillow函数,生成图片
img, code_str = check_code()
# 写入到自己的session中(以便后获取验证码再进行校验)
request.session['code_str'] = code_str
# 给session设置60秒超时,后续成功登录后需要重新设置
request.session.set_expiry(60)
# 导入io模块将图片传给前段
from io import BytesIO
stream = BytesIO()
img.save(stream, 'png')
return HttpResponse(stream.getvalue())
6.3、页面
{% load static%}
login
15、Ajax
浏览器向网站发送请求时:URL和表单的形式提交
- GET
- POST
特点:页面刷新
除此之外,基础Ajax向后台请求
- 依赖jQuery
- 编写jQuery代码
$.ajax({
url:"发送得地址",
type:"get",
data:{
n1:123,
n2:456
},
success:function(res){
console.log(res);
}
})
15.1、get请求
{% extends 'layout.html' %}
{% block content %}
任务管理
实例1
{% endblock %}
{% block js %}
{% endblock %}
from django.http import HttpResponse
from django.shortcuts import render
def task_list(request):
"""任务列表"""
return render(request, 'task_list.html')
def task_ajax(request):
print(request.GET)
return HttpResponse('成功')
# 任务管理
path('task/list/', task.task_list),
path('task/ajax/', task.task_ajax),
15.2、post请求
from django.http import HttpResponse
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
def task_list(request):
"""任务列表"""
return render(request, 'task_list.html')
@csrf_exempt # 免除post请求,就在可以获取Ajax post发送的内容
def task_ajax(request):
print(request.GET)
print(request.POST)
return HttpResponse('成功')
15.3、关闭绑定事件
{% extends 'layout.html' %}
{% block content %}
任务管理
实例1
{% endblock %}
{% block js %}
{% endblock %}
15.4、Ajax请求的返回值
一般都会返回json格式
前端:
{% extends 'layout.html' %}
{% block content %}
任务管理
实例1
实例2
实例3
{% endblock %}
{% block js %}
{% endblock %}
后端:
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
def task_list(request):
"""任务列表"""
return render(request, 'task_list.html')
@csrf_exempt # 免除post请求,就在可以获取Ajax post发送的内容
def task_ajax(request):
print(request.GET)
print(request.POST)
data_dict = {'status': True, 'name': '李锦彪'}
return JsonResponse(data_dict)
16、订单
html
{% extends 'layout.html' %}
{% block content %}
{# 删除对话框 #}
是否确定删除?
删除后,所有关联的数据都会被删除!!!
订单列表
ID
订单号
商品名
价格
状态
用户
操作
{% for obj in queryset %}
{{ obj.id }}
{{ obj.oid }}
{{ obj.title }}
{{ obj.price }}
{{ obj.get_status_display }}
{{ obj.admin }}
{# 编辑#}
{# 删除 #}
{% endfor %}
-
{{ page_string }}
import random
from datetime import datetime
from django.http import JsonResponse
from django.shortcuts import render, redirect
from django.views.decorators.csrf import csrf_exempt
from Employee import models
from Employee.utils.form import OrderModelForm
# 订单号生成
from Employee.utils.pagination import Pagination
random_oid = datetime.now().strftime('%Y%m%d%H%M%S') + str(random.randint(1000, 9999))
def order_list(request):
form = OrderModelForm()
# 1、根据自己的情况去筛选自己的数据
queryset = models.Order.objects.all() # 获得所有数据
# 2,、实例化分页对象
page_object = Pagination(request, queryset)
dic_context = {
'queryset': page_object.page_queryset, # 分完页的数据
'page_string': page_object.html(), # 生成页码
'form': form,
}
return render(request, 'order_list.html', dic_context)
@csrf_exempt
def order_add(request):
"""新建订单(Ajax)"""
form = OrderModelForm(request.POST)
if form.is_valid():
# 创建自定义订单号
form.instance.oid = random_oid
# 创建管理员(登录的是谁就是谁)
form.instance.admin_id = request.session['info']['id']
# 保存到数据库中
form.save()
context = {
'status': True
}
return JsonResponse(context)
# 返回错误信息
return JsonResponse({'status': False, 'error': form.errors})
def order_delete(request):
"""删除订单"""
uid = request.GET.get('uid')
if models.Order.objects.filter(id=uid).exists(): # 判断是否存在
models.Order.objects.filter(id=uid).delete()
return JsonResponse({'status': True})
return JsonResponse({'status': False, 'error': '删除错误,数据不存在'})
@csrf_exempt
def order_edit(request):
if request.method == 'GET':
"""根据id获取订单信息 get 请求"""
eid = request.GET.get('eid')
# row_object = models.Order.objects.filter(id=eid).filter() # 对象
if models.Order.objects.filter(id=eid).filter():
# 获取到的是字典
row_dict = models.Order.objects.filter(id=eid).values('title', 'price', 'status').first()
return JsonResponse({'status': True, 'data': row_dict})
return JsonResponse({'status': False, 'error': '数据不存在'})
"""编辑订单 POST请求"""
eid = request.GET.get('eid')
row_object = models.Order.objects.filter(id=eid).first()
if not models.Order.objects.filter(id=eid).filter():
return JsonResponse({'status': False, 'tips': '数据不存在,请刷新重试'})
form = OrderModelForm(data=request.POST, instance=row_object)
if form.is_valid():
form.save()
return JsonResponse({'status': True})
# 返回错误信息
return JsonResponse({'status': False, 'error': form.errors})
17、文件上传
17.1、基本操作
{# enctype="multipart/form-data" 支持上传文件 #}
from django.shortcuts import render, HttpResponse
def upload_list(request):
if request.method == 'GET':
return render(request, 'upload_list.html')
# # 'username': ['15751083927']
# print(request.POST) # 请求体中的数据
# # {'avater': []}
# print(request.FILES) # 发过来的文件 {}
file_object = request.FILES.get('avater')
print(file_object.name) # 文件名
f = open('a1.png', 'wb')
for chunk in file_object.chunks():
f.write(chunk) # 读一点写入一点
f.close()
return HttpResponse('...')
17.2、Excel批量上传
def depart_multi(request):
"""批量添加"""
from django.core.files.uploadedfile import InMemoryUploadedFile
from openpyxl import load_workbook
# 获取用户上传的文件对象
file_object = request.FILES.get('exc')
# 对象传递给openpyxl
wb = load_workbook(file_object) # 或者是文件路径
sheet = wb.worksheets[0]
# 循环获取每一行数据
for row in sheet.iter_rows(min_row=2):
text = row[0].value
# 添加到数据库
if not models.Department.objects.filter(title=text).exists():
models.Department.objects.create(title=text)
return redirect('/depart/list/')
17.3、混合数据(form)
提交页面时:用户输入的数据+文件(输入不能为空、报错)。
- form生成的html标签:type=file
- 表单的验证
- form.clean_data 获取数据 + 文件对象
{% extends 'layout.html' %}
{% block content %}
{{ title }}
{% endblock %}
后端:
class UpForm(forms.Form):
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': 23, 'img': }
# print(form.cleaned_data)
# 获取到的内容要自己处理
# 1.读取图片内容,写入到文件夹中并获取文件的路径
img_object = form.cleaned_data.get('img')
# file_path = 'Employee/static/img/{}'.format(img_object.name) /格式不同,所以使用os
db_file_path = os.path.join('static', 'img', img_object.name) # 数据库存取地址 方便网页拼接url获取
file_path = os.path.join('Employee', db_file_path)
f = open(file_path, 'wb')
for chunk in img_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 redirect('/upload/form/')
return render(request, 'upload_form.html', {'form': form, 'title': title})
注意:就目前而言,所有的静态文件都只能放在static目录
在Django的开发过程中两个特殊的文件夹
- static。存放静态文件
- media:用户上传的数据目录
存储用户传来的数据
在urls.py中进行配置:
from django.conf import settings
from django.urls import path, re_path
from django.views.static import serve # 加载静态文件
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/'
media目录所在位置:
在浏览器中直接访问:
后端存储
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': 23, 'img': }
# print(form.cleaned_data)
# 获取到的内容要自己处理
# 1.读取图片内容,写入到文件夹中并获取文件的路径
img_object = form.cleaned_data.get('img')
media_path = os.path.join('media', img_object.name) # media/xxxx
f = open(media_path, 'wb')
for chunk in img_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 redirect('/upload/form/')
return render(request, 'upload_form.html', {'form': form, 'title': title})
17.5、混合数据(ModelForm)
models.py
class City(models.Model):
""""城市"""
title = models.CharField(verbose_name='城市', max_length=32)
count = models.IntegerField(verbose_name='人口')
# 本质上数据库也是CharField, 但是自动保存数据 路径 :media/city/xxx
img = models.FileField(verbose_name='logo', max_length=128, upload_to='city/')
定义ModelForm:
class CityModelForm(forms.ModelForm):
class Meta:
model = models.City
fields = '__all__'
视图
def upload_modelform(request):
"""获取混合数据modelform"""
title = 'ModelForm'
if request.method == 'GET':
form = CityModelForm()
queryset = models.City.objects.all()
return render(request, 'upload_modelform.html', {'form': form, 'title': title, 'queryset': queryset})
form = CityModelForm(data=request.POST, files=request.FILES)
if form.is_valid():
# 对于文件:自动保存
# 字段+上传路径写入到数据库
form.save()
return redirect('/upload/modelform/')
return render(request, 'upload_modelform.html', {'form': form, 'title': title})
前段
包括显示内容
{% extends 'layout.html' %}
{% block content %}
{{ title }}
| ID | 城市名 | 人口 | logo |
|---|---|---|---|
| {{ obj.id }} | {{ obj.title }} | {{ obj.count }} |
|
Django转义总结:escape、autoescape、safe、mark_safe https://blog.csdn.net/bbwangj/article/details/79992863分页 --类
"""
自定义分页组件, 以后想使用这个分页组件,做一下几步
后端:
def mobile_list(request):
1、根据自己的情况去筛选自己的数据
queryset = models.Mobile.objects.all() # 获得所有数据
2,、实例化分页对象
page_object = Pagination(request, queryset)
dic_context = {
'data_list': page_object.page_queryset, # 分完页的数据
'page_string': page_object.html(), # 生成页码
}
return render(request, 'mobile_list.html', dic_context)
前段:
靓号列表
| ID | 号码 | 价格 | 等级 | 状态 | 操作 |
|---|---|---|---|---|---|
| {{ obj.id }} | {{ obj.mobile }} | {{ obj.price }} | {{ obj.get_level_display }} | {{ obj.get_status_display }} | {# 编辑#} { obj.id }}/edit/" > {# 删除#} { obj.id }}/delete/" > |
-
{{ page_string }}
from django import forms
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}
封装
md5加密
from django.conf import settings
import hashlib
def md5(data_string): # md5加密
obj = hashlib.md5(settings.SECRET_KEY.encode('utf-8'))
obj.update(data_string.encode('utf-8'))
return obj.hexdigest()
数据库中获取数据
对象/字典
# 对象当前行的所有数据 row_object = models.Order.objects.filter(id=eid).filter()
# 获取到的是字典
row_dict = models.Order.objects.filter(id=eid).values('title', 'price', 'status').first()
# queryset = {obj,obj ..}
queryset = models.Order.objects.all()
# queryset = { {'xx': 'xx', 'xx': 'xxx'}, {'xx': 'xxx', 'xx': 'xxx'} }
queryset = models.Order.objects.all().values('xx', 'xx')
# queryset = {(1, 'xx'), (2, 'xx')....}
queryset = models.Order.objects.all().values_list('id', 'title')
柱状图
{% extends 'layout.html' %}
{% load static %}
{% block content %}
数据统计
柱状图
{% endblock %}
{% block js %}
{% endblock %}
https://echarts.apache.org/zh/index.html
总结- 创建Django项目
- 修改__ init __.py
import pymysql pymysql.install_as_MySQLdb()
- settings.py中的DIR templates删除
- 创建app和注册app
python manage.py startapp xxx
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'Employee.apps.EmployeeConfig', # app注册
]
-
配置静态文件路径 & 模板路径(放在app目录下)
-
配置数据库相关操作
- 第三方模块 mysqlclient
- 自己先去数据库创建一个数据库
- 配置数据库连接settings.py
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'ljb', # 数据库名字 'USER': 'root', # 账号 'PASSWORD': '187365', # 密码 'HOST': '127.0.0.1', # 主机 'PORT': 3306, # 端口号 } }- 在app下的models.py中编写表
from django.db import models class Department(models.Model): """部门表""" title = models.CharField(verbose_name='标题', max_length=32) def __str__(self): return self.title- 执行两个命令
python manage.py makemigrations python manage.py migrate
-
在urls.py,路由(url和函数的对应关系)
-
在views,试图函数,编写业务逻辑
-
templates目录下编写html文件
-
ModelForm & Form组件,在我们开发增删改查功能
- 生成html标签(生成默认值)
- 请求数据进行校验
- 保存到数据库(ModelForm)
- 获取错误信息
-
Cookie和session用户信息保存起来
-
中间件,基于中间件实现用户认证,基于:process_request
-
ORM操作
models.User.objects.filter(id="")
-
分页组件。
{% endblock %}
https://echarts.apache.org/zh/index.html ## 总结 - 创建Django项目 - 修改__ init __.py ```python import pymysql pymysql.install_as_MySQLdb()
- settings.py中的DIR templates删除
- 创建app和注册app
python manage.py startapp xxx
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'Employee.apps.EmployeeConfig', # app注册
]
-
配置静态文件路径 & 模板路径(放在app目录下)
-
配置数据库相关操作
- 第三方模块 mysqlclient
- 自己先去数据库创建一个数据库
- 配置数据库连接settings.py
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'ljb', # 数据库名字 'USER': 'root', # 账号 'PASSWORD': '187365', # 密码 'HOST': '127.0.0.1', # 主机 'PORT': 3306, # 端口号 } }- 在app下的models.py中编写表
from django.db import models class Department(models.Model): """部门表""" title = models.CharField(verbose_name='标题', max_length=32) def __str__(self): return self.title- 执行两个命令
python manage.py makemigrations python manage.py migrate
-
在urls.py,路由(url和函数的对应关系)
-
在views,试图函数,编写业务逻辑
-
templates目录下编写html文件
-
ModelForm & Form组件,在我们开发增删改查功能
- 生成html标签(生成默认值)
- 请求数据进行校验
- 保存到数据库(ModelForm)
- 获取错误信息
-
Cookie和session用户信息保存起来
-
中间件,基于中间件实现用户认证,基于:process_request
-
ORM操作
models.User.objects.filter(id="")
- 分页组件。


