文章目录
1 项目初始化
1.1 项目结构
D:.
│ manage.py 【项目管理、启动项目、创建app、数据管理、不要动】
├─djangoProject1
│ asgi.py 【接收网络请求、不要动】
│ settings.py 【项目配置、==常常操作==】
│ urls.py 【URL和函数的对应关系、==常常操作==】
│ wsgi.py 【接收网络请求、不要动】
│ __init__.py
│
└─templates 【pycharm启动项目自动,实际项目一般不需要】
1.2 取消csrf验证
如果觉得默认的crsf繁琐的话可以取消:
- 在settings.py 文件中找到这一行注释掉
-
也可以不取消,可以在不需要csrf验证的函数上加上
@csrf_exempt
1.3 解决前端出现跨域问题-cors
- 首先在setting.py 找到这两个列表,在列表末尾添加,如图所示:
"corsheaders"
"corsheaders.middleware.CorsMiddleware",
- 在setting.py文件文末添加这些话
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
# CORS_ORIGIN_WHITELIST = (
# 'http://127.0.0.1:8080',
# )
CORS_ALLOWED_ORIGINS_REGEXES = [
r'^http://.*?$',
]
# CORS_ORIGIN_REGEXES_WHITELIST = (
# r'^http://.*?$',
# )
CORS_ALLOW_METHODS = (
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
'VIEW',
)
CORS_ALLOW_HEADERS = (
'XMLHttpRequest',
'X_FILENAME',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'x-requested-with',
'Pragma',
)
ALLOWED_HOSTS = ['*']
1.4 设置默认浏览器报错信息为中文
在setting.py文件中找到LANGUAGE_CODE,将其值改为zh-hans
# LANGUAGE_CODE = 'en-us'
LANGUAGE_CODE = 'zh-hans'
1.5 修改数据库默认配置
同样在setting.py文件中找到默认的注释掉
# Database
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases
# 默认是sqllite3
# DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': BASE_DIR / 'db.sqlite3',
# }
# }
# 改成mysql
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'django_project1',
'USER': 'root', # 账号
'PASSWORD': 'root', # 你的密码
'HOST': '127.0.0.1',
'PORT': '3306',
}
}
1.6 配置上传文件保存目录
如果项目涉及到上传文件可能要配置media
- 创建media文件夹
在项目根目录下创建,如图:
- 修改setting.py
- 在文件中加上这几行
# 文件上传
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
- 配置urls.py
加上这句话
re_path(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}, name='media'),
- models 示例
-
最后一行的avatar中upload_to,如果使用ModelForm上传则会自动将上传文件保存至项目根路径+‘/media’+‘/image/admin’+文件名
-
这时如果需要更新头像需要再ModelForm实例化是传入files参数,如图
2 常用指令
使用该方法可以简化命令的输入
2.1 生成数据库表
- 安装模块
pip install mysqlclient
在使用manage tools工具后的指令为:
默认如果不指定app名称则生成所有app中models(自动生成或更新数据库表)
-
makemigrations app名称
-
migrate app名称
生成的表:
mysql> show tables;
+---------------------------+
| Tables_in_django_project1 |
+---------------------------+
| app01_department |
| app01_employee |
| django_migrations |
+---------------------------+
2.2 启动Django项目
- 安装Django
pip install django
- 创建Django项目
django-admin startproject 项目名
- 创建APP&注册
python manage.py startapp app名称
例如runserver 8080
3 工具类
3.1 md5加密
哈希化不可逆,比较密码正确性需要先加密为密文再比较
代码:
import hashlib
from djangoProject1 import settings
def md5(password):
#加盐
#django提供了随机的
obj = hashlib.md5(settings.SECRET_KEY.encode('utf-8'))
# 哈希之前需要先转码
obj.update(password.encode('utf-8'))
return obj.hexdigest()
3.2 分页插件
- 代码:
range(page_start,page_end + 1)返回迭代器方便前端{{}}模版进行遍历
import math
class Pagination:
"""
@:var
entities: 为需要分页的所有实体
self.page = page 当前页
self.page_size = page_size 每页展示多少个实体
self.parm_dict = parm_dict 为了后续对字典进行解包,在context中解包
@:def
def is_illegal(self): 如果遇到错误,该函数返回False
def get_illegal_content(self): 返回错误信息
"""
def __init__(self, request, entities):
self.legal = True
page = request.GET.get('page', '1')
page_size = request.GET.get('page_size', '10')
if page and str(page).isdecimal():
page = int(page)
if page_size and str(page_size).isdecimal():
page_size = int(page_size)
page_total = math.ceil(len(entities) / page_size)
if page_total < page or page < 1:
self.legal = False
self.illegal_content = '页数不合理请重新输入!!'
start = (page - 1) * page_size
end = page * page_size
page_entities = entities[start:end]
if page_total >= 10:
page_start = page - 5 if page - 5 >= 5 else 1
page_end = page + 5 if page + 5 <= page_total else page_total
if page_end == page_total:
page_start = page_start - (10 - (page_end - page_start + 1))
if page_start == 1:
page_end = page_end + 10 - (page_end - page_start + 1)
else:
page_start = 1
page_end = page_total
parm_dict = {'pages': range(page_start,
page_end + 1), 'current_page': page,
'page_size': page_size, 'page_total': page_total,
'entities': page_entities}
self.page = page
self.page_size = page_size
self.parm_dict = parm_dict
def page_parm(self):
return self.parm_dict
def is_illegal(self):
return not self.legal
def get_illegal_content(self):
return self.illegal_content
- 使用案例:
应用于后台管理系统返回表格的分页功能
- 后端渲染函数:
def depart_list(request):
query = {'name__contains': request.GET.get('content', '')}
departments = models.Department.objects.filter(**query)
pagination = Pagination(request, entities=departments)
if pagination.is_illegal():
return error(request, pagination.get_illegal_content())
return render(request=request, template_name='depart_manage/depart_list.html',
context={'entities': departments, **pagination.page_parm()}
)
- 前端代码:
<nav aria-label="...">
<ul class="pagination">
<li class="page-item {% if current_page == 1 %}disabled{% endif %}">
<a class="page-link" href="?page={{ current_page|add:-1 }}&content={{ content }}">Prev</a>
</li>
{% for page in pages %}
<li class="page-item {% if page == current_page %}active{% endif %}">
<a class="page-link"
href="?page={{ page }}&content={{ content }}">{{ page }}</a>
</li>
{% endfor %}
<li class="page-item">
<a class="page-link {% if current_page == page_total %}disabled{% endif %}"
href="?page={{ current_page|add:1 }}&content={{ content }}">Next</a>
</li>
<li class="page-item" >
<form class="input-group mb-3" method="get">
<input type="text" class="form-control" placeholder="页码,共:{{ page_total }}页"
name="page" required
aria-label="Recipient's username" aria-describedby="button-addon2">
<button class="btn btn-outline-success" type="submit" id="button-addon2">
跳转
</button>
</form>
</li>
</ul>
</nav>
3.3 Bootstrap样式的modelForm表单:
- 代码
- 后端代码:
from django import forms
class BootstrapModelForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for name, field in self.fields.items():
# 如果是密码框则用passwordinput防止密码直接显示
if str(name).lower().__contains__('password'):
field.widget = forms.PasswordInput(attrs={'class': 'form-control'})
#form-control 为Bootstrap样式类
if not field.widget.attrs.get('class'):
field.widget.attrs['class'] = 'form-control '
elif field.widget.attrs.get('class'):
field.widget.attrs['class'] += ' form-control '
if not field.widget.attrs.get('placeholder'):
field.widget.attrs['placeholder'] = field.label
#防止一个页面多个表单(对话框存在多个)从而出现多个标签具有同一个id的情况
if not field.widget.attrs.get('id'):
field.widget.attrs['id'] = False
- 前端代码
<div class="modal-body">
<form method="post" action="/emp/add" novalidate>
{% csrf_token %}
{% for field in add_form %}
<div class="mb-3">
<label class="col-form-label">{{ field.label }}</label>
{{ field }}
</div>
{% endfor %}
<div class="modal-footer" style="display: flex;justify-content: space-evenly">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭
</button>
<button type="submit" data-bs-dismiss="modal" class="btn btn-primary">添加</button>
</div>
</form>
</div>
- 演示:
3.4 前端生成日期时间选择控件
- 首先引入css:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
- 引入js:
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
- js代码:
// 设置Flatpickr中文语言选项
flatpickr.l10ns.zh = {
weekdays: {
shorthand: ["周日", "周一", "周二", "周三", "周四", "周五", "周六"],
longhand: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"]
},
months: {
shorthand: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
longhand: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"]
},
rangeSeparator: " 至 ",
weekAbbreviation: "周",
scrollTitle: "滚动切换",
toggleTitle: "点击切换 12/24 小时时制"
};
// 使用中文语言选项初始化Flatpickr
flatpickr(".datetime", {
enableTime: true,
dateFormat: "Y-m-d H:i",
defaultDate: new Date(),
locale: "zh",
monthSelectorType: "dropdown", // 使用下拉选择框选择月份
shorthandCurrentMonth: true, // 使用缩写月份
weekdays: {
shorthand: ["日", "一", "二", "三", "四", "五", "六"],
longhand: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"]
}
});
效果演示:
3.5 中间件middleWare
- 使用前需要再setting.py文件中声明:
下面列表的添加最易一行,值为该python文件路径
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 取消掉csrf验证
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
"corsheaders.middleware.CorsMiddleware",
"app01.middleware.auth.AuthMiddleware",
]
- 代码:
from django.utils.deprecation import MiddlewareMixin
from app01.views.common_views import error
class AuthMiddleware(MiddlewareMixin):
"""
Middleware1
中间件1
"""
def process_request(self, request):
if request.path_info in ['/login/', '/register/', '/logout/', '/image/code']:
return
if str(request).split('/')[1] in ['emp', 'depart'] and str(request).split('/')[2].isdecimal():
return
info_dict = request.session.get('info')
print('info_dict==')
print(info_dict)
if info_dict:
return
return error(request=request, content='请先登录账号!!', is_login=False)
"""
def process_request(self, request):
if request.path_info in ['/login/', '/register/', '/logout/', '/image/code']:
return
if str(request).split('/')[1] in ['emp', 'depart'] and str(request).split('/')[2].isdecimal():
return
info_dict = request.session.get('info')
print('info_dict==')
print(info_dict)
if info_dict:
return
return error(request=request, content='请先登录账号!!', is_login=False)