前言
在我一直以来就认为,相比java spring,django"只"适合搭建一个较小的业务系统、或者功能页面。
并且,目前我做的最多的就是:基于三方鉴权的功能性交互页面、一些展示页面、和较小体量的功能系统(也是可以满足一套基本需求的)。
总体而言,它的优势在于:其凭借python胶水代码特性,能够迅速开发并实现扩展性高、功能小巧的的业务系统或功能页面。
知识点
模块安装
pip install Django
pip install django-cors-headers
pip install PyMySQL
pip install djangorestframework
配置settings.py
...
# 是否以测试环境运行
# 生产环境请更换为True
DEBUG = False
# 访问许可,这里*表示接收一切形式的host访问
# 如果你更换为某个域名,将只允许第三方通过该域名访问本系统
ALLOWED_HOSTS = ['*']
# Application definition
# 辅助系统自动识别应用程序,例如
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'corsheaders', # 添加:跨域组件
'StaicDjangoDemo',
]
# 中间件配置
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware', # 跨域中间件,放首行(放其他行未测试)
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware', # 防止跨站请求伪造 (CSRF) 攻击,有些情况会过敏,我不太喜欢这个
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# 配置数据库连接,这里用的是mysql
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'database',
'USER': 'root',
'PASSWORD': 'xxxxxxx',
'HOST': '127.0.0.1',
'PORT': '3306',
'OPTIONS': {
'charset': 'utf8mb4',
},
}
}
# # 日志
# LOGGING = {
# 'version': 1,
# 'disable_existing_loggers': False,
# 'handlers': {
# 'file': {
# 'level': 'ERROR',
# 'class': 'logging.FileHandler',
# 'filename': 'errors.log',
# 'formatter': 'verbose',
# },
# },
# 'formatters': {
# 'verbose': {
# 'format': '%(asctime)s [%(levelname)s] %(message)s',
# 'datefmt': '%Y-%m-%d %H:%M:%S',
# },
# },
# 'loggers': {
# 'django': {
# 'handlers': ['file'],
# 'level': 'ERROR',
# 'propagate': True,
# },
# },
# }
# 系统时间,这里选用上海时间
TIME_ZONE = 'Asia/Shanghai'
# session设置,存储到database里
SESSION_ENGINE = 'django.contrib.sessions.backends.db'
# 设置每个用户的最大Session数量
MAX_SESSION_PER_USER = 5
# 设置session在浏览器关闭时失效
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
# 设置Session的衰减时间为一天
SESSION_COOKIE_AGE = 86400 # 一天的秒数
# 用户登出跳转的地址
LOGOUT_REDIRECT_URL = '/login' # 用户登出后重定向到登录页面
# 设置静态文件目录,生产环境建议使用nginx来开放静态文件目录
# 使用【python manage.py collectstatic】指令,将可以把STATICFILES_DIRS内所有的静态文件汇总到STATIC_ROOT中
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'), r'C:\Users\HP\Pictures'
)
STATIC_ROOT = 'staticfiles'
# 跨域忽略
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
CORS_ORIGIN_WHITELIST = ()
# 对应的发送的请求的跨域
CORS_ALLOW_METHODS = (
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
'VIEW',
)
CORS_ALLOW_HEADERS = (
'accept',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'x-requested-with',
)
数据库迁移
需要在settings.py同级目录的__init__.py中添加如下代码,使用pymysql来为django提供mysql数据库服务
import pymysql
pymysql.install_as_MySQLdb()
django系统表迁移至数据库:
利用迁移文件(全量)迁移到数据库:python manage.py migrate
只生成迁移session数据表:python manage.py migrate sessions
只生成迁移auth系统用户数据表:python manage.py migrate auth
根据数据库生成django-orm模型:python manage.py inspectdb > models.py
用户管理
至少将session和auth相关数据表迁移到数据库后,你需要以下脚本来管理用户
这个脚本需要在项目根目录下运行
import os
import django
# 设置 Django 项目的环境变量
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myDemo.settings")
django.setup()
from django.contrib.auth.models import User
def create_user(username, email, password):
# 检查用户是否已经存在
if User.objects.filter(username=username).exists():
print(f"用户 '{username}' 已经存在")
return
# 创建新用户
User.objects.create_user(username=username, email=email, password=password)
print(f"用户 '{username}' 创建成功")
def update_user_password(username, old, new):
# 检查用户是否已经存在
user = User.objects.get(username=username)
if user:
# 验证旧密码
if user.check_password(old):
# 旧密码正确,设置新密码
user.set_password(new)
user.save()
print(f"Password for user '{username}' changed successfully.")
else:
print("Old password is incorrect.")
else:
print('username not found')
def delete_user(username):
# 查找用户
try:
user = User.objects.get(username=username)
user.delete()
print(f"User '{username}' deleted successfully.")
except User.DoesNotExist:
print(f"User '{username}' does not exist.")
# 查询用户的所有信息(密文密码)
def check_users():
users = User.objects.all()
for user in users:
print(f"Username: {user.username}, Email: {user.email}, Password: {user.password}")
if __name__ == "__main__":
# 替换为你想要创建的用户信息
# username = "test"
# email = "xxx@qq.com"
# password = "username"
# new_password = 'qnetKPHJ'
# create_user(username, email, password)
# update_user_password(username, password, new_password)
# delete_user('xu')
check_users()
配置路由urls.py
from django.urls import path, re_path
from django.views import static as sta # 新增
from .page.public import success
from .page import room, app, user, welcome
from .api import api_app
from django.contrib.auth import views as auth_views
urlpatterns = [
# 强制开放静态资源,即使在debug为False的情况下,不推荐
re_path(r'^static/(?P<path>.*)$', sta.serve,
{'document_root': 'static'}, name='static'),
# 系统自定义路由,服务页面
path('welcome', welcome.welcome),
path('success/room_add', success.success_room_add),
path('success/app_add', success.success_app_add),
path('success/register', success.success_register_add),
path('room/add', room.add_room),
path('app/add', app.add_app),
path('app/list', app.app_list),
path('register/', user.register, name='register'),
path('login/', user.login_view, name='login'),
# 用户登出,系统自带服务,登出后跳转至setting.py中的LOGOUT_REDIRECT_URL指定url
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
# 这里是restframework api的路由
path('api/app/list', api_app.AppListView.as_view()),
path('api/app/list/state', api_app.AppStateFilterView.as_view()),
path('api/app/detail', api_app.AppAppidFilterView.as_view()),
]
用户权限核验
登录与登出
from django.contrib.auth import authenticate, login, logout
# 登录鉴权验证
user = authenticate(request, username=username, password=password)
if user:
# 赋予用户授权
login(request, user)
# 解除用户授权(登出)
logout(request)
身份核验功能
if request.user.is_authenticated:
# 获取访问者用户名
username = request.user.username
Django-orm
我比较讨厌规定规格的django-orm,并更喜欢原生sql,但这里还是给出orm的一些操作
模型示例
# 在 myapp/models.py 中
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=100)
published_date = models.DateField()
isbn = models.CharField(max_length=13, unique=True)
def __str__(self):
return self.title
增
# 使用 .create() 方法
Book.objects.create(
title="Django for Beginners",
author="William S. Vincent",
published_date="2024-01-01",
isbn="978-0-1234-5678-9"
)
# 或者先创建实例再保存
book = Book(
title="Django for Experts",
author="John Doe",
published_date="2024-02-01",
isbn="978-1-2345-6789-0"
)
book.save()
查
# 获取所有 Book 实例
all_books = Book.objects.all()
# 根据条件获取 Book 实例
book_by_title = Book.objects.get(title="Django for Beginners")
# 使用 .filter() 方法
books_by_author = Book.objects.filter(author="William S. Vincent")
# 获取前两个 Book 实例
first_two_books = Book.objects.all()[:2]
# 使用 .exists() 检查某个条件是否存在
exists = Book.objects.filter(title="Django for Beginners").exists()
改
# 获取要更新的 Book 实例
book = Book.objects.get(title="Django for Beginners")
# 修改字段
book.published_date = "2024-01-15"
book.save()
删
# 获取要删除的 Book 实例
book = Book.objects.get(title="Django for Beginners")
# 删除实例
book.delete()
# 或者批量删除符合条件的实例
Book.objects.filter(author="John Doe").delete()
自定义sql查询
实用于复杂的查询功能
from django.db import connection
def raw_sql_select(sql, input):
with connection.cursor() as cursor:
cursor.execute(sql, input)
# 获取字段名称
columns = [col[0] for col in cursor.description]
# 获取所有行
rows = cursor.fetchall()
# 将结果转换为字典列表
results = [dict(zip(columns, row)) for row in rows]
return results
# 查询执行进程
processes = raw_sql_select("""
SELECT
e.dict_value as state,
c.result as res_text,
c.appendix as appendix,
date_format(c.end_time, '%%Y-%%m-%%d %%H:%%i') as process_time
FROM
tb_task_process c
JOIN
tb_dict e ON c.state = e.dict_id AND e.dict_type = 'process_state'
WHERE
c.order_id = %s
""", [order_id])
print(processes)