前言
在我一直以来就认为,相比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 Userdef 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_viewsurlpatterns = [# 强制开放静态资源,即使在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指定urlpath('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 modelsclass 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 connectiondef 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)