Django
- Python知识点:函数、面向对象。
- 前端开发:HTML、CSS、JavaScript、jQuery、BootStrap。
- MySQL数据库。
- Python的Web框架:
- Flask,自身短小精悍 + 第三方组件。
- Django,内部已集成了很多组件 + 第三方组件。【主要】
安装django
pip install django |
c:\python39 |
创建项目
django中项目会有一些默认的文件和默认的文件夹。
在终端
打开终端
进入某个目录
cd /Users/jiangangkong/workSpace/pycharmWorkSpace/
执行命令创建项目
/Users/jiangangkong/miniconda3/bin/django-admin startproject 项目名
# 如果 /Users/jiangangkong/miniconda3/bin/ 已加入环境系统环境变量。
django-admin startproject 项目名称
在Pycharm
特殊说明:
命令行,创建的项目是标准的。
pycharm,在标准的基础上默认给咱们加了点东西。【现在删除,以后不一定要删。是关于模版的设置】
- 创建了一个templates目录【删除】
- settings.py中【删除划线处】
项目目录结构
mysite2 |
- 要写的只有
settings.py
和urls.py
加之引用manage.py
APP
- 此APP非彼APP,主要实现功能的划分
- 项目 |
创建app
- 点击项目根目录,调出终端,输入:
python3.9 manage.py startapp app01 |
app目录结构
├── app01 |
- 所以对app的操作只在
models.py
和views.py
中进行
开发流程
- 在项目settings.py中注册创建的app【settings.py】
- 编写url与视图函数的对应关系【urls.py中】
- 编写视图函数【在对应app的 views.py中编写】
启动django项目
命令行启动
python manage.py runserver
pycharm启动
开发流程【补】
在app根目录中添加 templates
文件夹以及static
文件夹
引用静态文件【用之前的写法也可以】
模版语法【重要】
- 本质上:在HTML中写一些占位符,由数据对这些占位符进行替换和处理。
views.py
中要传键值对,html
中要用两对花括号接收- 获取列表元素不用
[]
,而用.
也可以这么写
通过.
获取属性
案例:伪联通新闻中心
- 这里的
requests
是第三方模块,是python专门用来发送请求的 - 而
views.py
中的request
是django的参数。为了不混淆可以写为req
请求和响应【重要】
- request是浏览器向后台发的【请求】
- 使用redirect需要导入redirect包
- 关于重定向【是2号路线】
- 后台让浏览器自己去重定向的网站寻找资源
案例:用户登录(无数据库版)
- 流程梳理
- 首先明确所有发送到/login的页面都会被送到后台views.login处理
- 用户第一次请求访问login页面时,是GET请求,所以后台要返回login.html
- 若用户在login.html中提交form表单则向后台发送POST请求,则验证用户名与密码
{% csrf_token %}
是django用来保证访问的合法性的,若不带,则浏览器会阻止该次请求。(也可以加在html最头部)
数据库操作
原始版采用:MySQL数据库 + pymysql
import pymysql
# 1.连接MySQL
conn = pymysql.connect(host="127.0.0.1", port=3306, user='root', passwd="00000000", charset='utf8', db='库名')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 2.发送指令
cursor.execute("insert into 表名(属性1,属性2,属性3) values('值1','值2','值3')")
conn.commit()
# 3.关闭
cursor.close()
conn.close()Django开发操作数据库更简单,内部提供了ORM框架。(将django简洁的代码翻译成sql语句)
安装第三方模块
- 在pycharm项目终端输入
pip3.9 install mysqlclient
ORM
ORM可以:
创建、修改、删除数据库中的表(不用写SQL语句)。 【无法创建数据库】
操作表中的数据(不用写SQL语句)。
1. 自己建库
2. django连接数据库
- 在
settings.py
中修改DATABASE
字段
DATABASES = { |
3. django操作表
- 创建表
- 创建表:在models.py文件中
- 打开pycharm项目终端执行命令:
# 这里我出了bug,原因是找不到libmysqlclient.21.dylib |
python manage.py makemigrations |
# ORM相当于执行了以下代码 表名为 app名_类名小写 |
其余的表是django内置的app生成的表【暂时不用管它们】
- 删除表
删掉models.py
中的代码并且执行以下命令
python manage.py makemigrations |
- 修改表
在表中新增列时,由于已存在列中可能已有数据,所以新增列必须要指定新增列对应的数据:
终端会提醒你两个解决方法
- 设置默认值
age = models.IntegerField(default=2) |
- 允许为空
data = models.IntegerField(null=True, blank=True) |
4. 增删改查
create
增delete
删update(xx = xx)
改all
查filter(xx = xx)
查
# #### 1.新增表项 #### |
搜索[查]
models.PrettyNum.objects.filter(mobile="19999999991",id=12) |
# 数字 |
# 字符串 |
分页-原理[查]
queryset = models.PrettyNum.objects.all() |
data = models.PrettyNum.objects.all().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
5.表之间的关联关系
from django.db import models |
模板的继承
定义模板:layout.html
|
继承模板:
{% extends 'layout.html' %} |
取关联或特殊数据
<td>{{ item.create_time|date:"Y-m-d" }}</td> <!-- 2022-8-21 --> |
ModelForm【牛逼】
- 解决数据校验和错误提示
- 避免views.py和html页面中有太多冗余代码
- models.py
from django.db import models |
- views.py
class MyForm(forms.ModelForm): |
- useradd.html和useredit.html【useredit.html中post不用填action,填了会出错,bug未知】
{% extends 'layout.html' %} |
{% extends 'layout.html' %} |
ModelForm数据校验
class PrettyModelForm(forms.ModelForm): |
分页
app01/utils/pagination.py
""" |
- 在
views.py
中使用
from app01.utils.pagination import Pagination |
- 在
html
中
<div style="margin-top: 10px " > |
时间选择插件
- 引入
bootstrap-datepicker
- 在应用ModelForm的网页中 id要变化, 具体id要在网页上检查元素
<head> |
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 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",]
让不同的页面输入框使用不同的 class
提取公共的类
ModelForm拆分出来
视图函数的归类
md5密码加密
utils/encrypt.py
from django.conf import settings |
def clean_password(self): |
cookie & session
http://127.0.0.1:8000/admin/list/ |
- http或者https都是无状态的短链接
- 解决方案
- 响应体即是你能看见的内容
- k1是网站发给浏览器某个请求的凭证
使用
def account_login(request): |
info = request.session.get("info") |
中间件
在
app01/Middleware/auth.py
中定义中间件from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
class M1(MiddlewareMixin):
""" 中间件1 """
def process_request(self, request):
# 如果方法中没有返回值(返回None),继续向后走
# 如果有返回值 HttpResponse、render 、redirect
print("M1.process_request")
return HttpResponse("无权访问")
def process_response(self, request, response):
print("M1.process_response")
return response
class M2(MiddlewareMixin):
""" 中间件2 """
def process_request(self, request):
print("M2.process_request")
def process_response(self, request, response):
print("M2.process_response")
return response应用中间件 setings.py
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.M1',
'app01.middleware.auth.M2',
]在中间件的process_request方法
# 如果方法中没有返回值(返回None),继续向后走
# 如果有返回值 HttpResponse、render 、redirect,则不再继续向后执行。
中间件实现登录校验
编写中间件
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse, redirect
class AuthMiddleware(MiddlewareMixin):
def process_request(self, request):
# 0.排除那些不需要登录就能访问的页面
# request.path_info 获取当前用户请求的URL /login/
if request.path_info == "/login/":
return
# 1.读取当前访问的用户的session信息,如果能读到,说明已登陆过,就可以继续向后走。
info_dict = request.session.get("info")
print(info_dict)
if info_dict:
return
# 2.没有登录过,重新回到登录页面
return redirect('/login/')应用中间件(
要在settings.py中注册
)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',
]
注销
def logout(request): |
html中获取已登录用户信息
<li><a href="#">id: {{ request.session.info.id }}</a></li> |
图片验证码
- 在项目根目录下导入
Monaco.ttf
- 在
app01/utils/code.py
中写入下方文件
import random |
login.html
中
<div class="form-group"> |
urls.py
中
path('image/code/', account.image_code) |
app01/views/account.py
def account_login(request): |
- 并且在
AccountModelForm
中新加入code
字段