觉得文章写的对你有帮助,请点赞、关注、Star。
项目资源的github地址:
https://github.com/qq20004604/Python3_Django_Demo
首先,确保你安装了mysql。
如果没有安装,就只能和sqlite交互了。
安装方法:
可以使用我这里提供的 docker 版 mysql,如果是linux或者MacOS系统,直接运行 sh 文件就能安装了。
https://github.com/qq20004604/docker-learning/tree/master/docker-demo-02-MySQL
可以用安装一个虚拟机,装上centos,然后将文件下载到虚拟机上,运行 create-image-mysql.sh 文件。
装虚拟机的教程参照我这篇文章:
https://blog.csdn.net/qq20004604/article/details/85080666
配置MySQL:(账号密码来自于docker版的配置)
diango和mysql交互有两种方式:
本文包含:
通过第三方python和mysql交互的使用方法,可以参考上面2个教程。
方便程度来说,sqlite最方便,第三方也很方便,使用自带mysql驱动最麻烦(版本不对的话要修改配置文件,很坑)。
python manage.py startapp withdb
然后注册应用,编辑 settings.py
,在 INSTALLED_APPS 添加新增应用withdb(homepage是之前添加的)
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# 以上都是默认,下面是新加入的
'homepage',
'withdb'
]
编辑 withdb/models.py
文件:
from django.db import models
# Create your models here.
# 这个其实就是在建立表结构,使用的是 ORM 的思想
class UserInfo(models.Model):
# 字段名id,primary_key=True表示主键自增
id = models.AutoField(primary_key=True)
# 字段名为username和password,max_length 指这2个字段的最大长度。
username = models.CharField(max_length=20)
password = models.CharField(max_length=20)
# 其他参数可选配置包括:(可以点进CharFiled函数查看)
# verbose_name = None, name = None, primary_key = False,
# max_length = None, unique = False, blank = False, null = False,
# db_index = False, rel = None, default = NOT_PROVIDED, editable = True,
# serialize = True, unique_for_date = None, unique_for_month = None,
# unique_for_year = None, choices = None, help_text = '', db_column = None,
# db_tablespace = None, auto_created = False, validators = (),
# error_messages = None
以上作用是设置3个字段:id(自增),username,password
执行命令:
python manage.py makemigrations
这个命令的效果,相当于在该 app(应用)下建立 migrations 目录,并记录下你所有的关于 modes.py
的改动,比如 0001_initial.py
, 但是这个改动还没有作用到数据库文件。
再执行命令:
python manage.py migrate
这个命令的效果,是将上面的改动,作用到数据库之中。
老规矩,修改 urls.py
,添加路由:
# 显示页面
path('user/', db_views.index),
# 注册用户
path('user/register', db_views.register),
# 查看用户列表
path('user/getusers', db_views.getusers)
修改 withdb/views.py
,内容如下:
from django.shortcuts import render, HttpResponse
# 引入
from withdb import models
import hashlib
import json
# 返回字符串的 md5 编码
def get_md5(str):
md5 = hashlib.md5()
md5.update(str.encode('utf-8'))
# 返回 md5 字符串
return md5.hexdigest()
# Create your views here.
# 这个是显示页面的逻辑(好吧,也没啥逻辑可说)
def index(request):
return render(request, 'users.html')
# 这个是注册的逻辑
def register(request):
print('register')
if not request.method == 'POST':
return HttpResponse(json.dumps({'code': 0, 'msg': '请求类型错误'}), content_type="application/json")
# 如果是 POST 请求
data = json.loads(request.body)
username = data["username"]
pw = data["pw"]
err = None
# 先验证一下是否符合要求
if len(username) > 20 or len(pw) > 20:
err = '用户名或者密码长度过长'
if len(username) < 8 or len(pw) < 8:
err = '用户名或密码长度过短(不应短于8位)'
# 如果有报错信息,则返回
if not err == None:
return HttpResponse(json.dumps({'code': 0, 'msg': err}), content_type="application/json")
# 截取md5前20位(避免明文密码存取)
md5_pw = get_md5(pw)[0:20]
# 一切顺利保存到数据库
save_success = True
# 防止存储失败
msg = 'success'
try:
# 这个的返回值,是当前 list 的所有值
models.UserInfo.objects.create(username=username, password=md5_pw)
except BaseException as e:
save_success = False
with open('./log.log', 'a') as f:
f.write('username = %s ,pw = %s , error = %s\n' % (username, pw, e))
print(save_success, msg, '-------------------')
if save_success:
return HttpResponse(json.dumps({'code': 0, 'msg': msg}), content_type="application/json")
else:
return HttpResponse(json.dumps({'code': 0, 'msg': '发生未知错误'}), content_type="application/json")
# 这个是获取用户列表的逻辑
def getusers(request):
user_list = models.UserInfo.objects.all()
list = []
# user_list 是一个
for i in user_list:
# i 是一个 ,注意,不要把pw返回回去了
list.append({
'username': i.username,
'id': i.id
})
result = {'code': 0, 'data': list}
return HttpResponse(json.dumps(result), content_type="application/json")
分为三部分:
第二步中,注册用户应该先查询,然后排除重复的用户名,不重复才能注册,这里省略掉了(因为第三步已经有相关逻辑,这里只是教程所以没写出来)
templates 目录下创建 user.html
内容如下:
用户
用户列表
- 空
注册
用户名:
密码:
两个功能:
1、用户访问链接 /user/ 显示页面(templates/user.html);
2、页面里有两个功能:【显示用户列表】和【注册新用户】
3、显示用户列表:将请求链接:/user/getusers
,然后通过 ORM 表结构(widthdb/models.py
)来读取数据库,并通过 widthdb/views.py
的 getusers 函数返回相关信息;
4、注册用户:以异步请求的方式将username和password字段通过 /user/getusers
传入到 widthdb/views.py
的 register 函数来处理。在注册前,会验证一下数据是否符合要求。不符合则提示错误信息,符合则将数据插入到数据库之中;
分别点击页面的 点击刷新按钮,和注册按钮,发现可以正常运行(可以参考我的代码 https://github.com/qq20004604/Python3_Django_Demo )
方式和8.3的 sqlite3 使用方式几乎一样,唯一区别是存到 mysql 里,而不是 sqlite 里。
这里使用的是django默认和mysql交互的方式来实现的。(不需要手写sql,通过ORM形式实现和数据库的管理)
1、python和mysql交互,需要装一个驱动:
pip install pymysql
2、然后编辑 urls.py
同级目录的 __init__.py
,添加内容:
import pymysql
pymysql.install_as_MySQLdb()
3、但是报错:
django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.13 or newer is required; you have 0.9.3.
查找N篇解决方案,此方案可供参考:
https://blog.csdn.net/weixin_33127753/article/details/89100552
选用方案二:【删除源代码的警告代码!】(真TM暴力)
简单来说,就是注释掉那行报错的判断信息就行了。
4、注释后,有红字提示:
You have 17 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
意思是你的应用数据库没迁移(指没从sqlite3迁移到mysql里)。
编辑 settings.py
的 DATABASES 属性,如下:
DATABASES = {
# 这里是和mysql交互
'default': {
'ENGINE': 'django.db.backends.mysql', # 数据库引擎,这个用的是pymysql,具体见官方文档
'NAME': 'django', # 这里是database 名
'USER': 'root', # 为了方便,用root,实际应用中应添加特定用户
'PASSWORD': 'fwefwefvvdsbwrgbr9jj24intwev0h0nbor32fwfmv1', # 密码
'HOST': '127.0.0.1', # mysql服务所在的主机ip,这里是在本机用的docker装的mysql,所以是127.0.0.1
'PORT': '3306', # mysql服务端口
'OPTIONS': {
'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"
}
}
}
1、在数据库里建立 database(名字等于上面 mysqldb 配置中 NAME 的值);
create database django;
2、初始化数据库的表配置:
记录改动:
python manage.py makemigrations
插入到数据库中:
python manage.py migrate
3、查看数据库
进入mysql,然后 use [database_name];
,再查看有哪些表 show tables;
(可以看到有一个表格django_migrations),再查看表内容 select * from django_migrations;
,发现是有数据的。
mysql> show tables;
+----------------------------+
| Tables_in_django |
+----------------------------+
| auth_group |
| auth_group_permissions |
| auth_permission |
| auth_user |
| auth_user_groups |
| auth_user_user_permissions |
| django_admin_log |
| django_content_type |
| django_migrations |
| django_session |
| withdb_userinfo |
+----------------------------+
11 rows in set (0.01 sec)
参考8.3.4、8.3.5、8.3.6,这个时候刷新数据。
验证后可以发现和sqlite版一样正常运行。
这里指:
settings.py
修改 settings.py
,先修改 DATABASE的配置:
DATABASES = {
'sqlitedb': {
# 之前的sqlite3配置
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3.bak'),
},
# 这里是和mysql交互,用于配置默认的那些app
'default': {
'ENGINE': 'django.db.backends.mysql', # 数据库引擎,这个用的是pymysql,具体见官方文档
'NAME': 'django_default', # 这里是database 名
'USER': 'root', # 为了方便,用root,实际应用中应添加特定用户
'PASSWORD': 'fwefwefvvdsbwrgbr9jj24intwev0h0nbor32fwfmv1', # 密码
'HOST': '127.0.0.1', # mysql服务所在的主机ip,这里是在本机用的docker装的mysql,所以是127.0.0.1
'PORT': '3306', # mysql服务端口
'OPTIONS': {
'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"
}
},
# 这里是和mysql交互,用于 withdb 这个应用使用
'userdb': {
'ENGINE': 'django.db.backends.mysql', # 数据库引擎,这个用的是pymysql,具体见官方文档
'NAME': 'django', # 这里是database 名
'USER': 'root', # 为了方便,用root,实际应用中应添加特定用户
'PASSWORD': 'fwefwefvvdsbwrgbr9jj24intwev0h0nbor32fwfmv1', # 密码
'HOST': '127.0.0.1', # mysql服务所在的主机ip,这里是在本机用的docker装的mysql,所以是127.0.0.1
'PORT': '3306', # mysql服务端口
'OPTIONS': {
'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"
}
}
}
再添加两行配置:
# 多应用的db路由
DATABASE_ROUTERS = ['Python3_Django_Demo.database_router.DatabaseAppsRouter']
DATABASE_APPS_MAPPING = {
# example:
# 'app_name':'database_name',
# 这些是默认应用
'admin': 'default',
'auth': 'default',
'contenttypes': 'default',
'sessions': 'default',
'messages': 'default',
'staticfiles': 'default',
# 这些是自定义应用
'withdb': 'userdb',
}
以上配置表示,使用 database_router.py
文件里的 DatabaseAppsRouter 函数来处理路由。
以及不同app默认使用不同的db设置(也可以在实际使用的时候,手动指定具体使用哪一个)
在 settings.py
同目录下,新建 database_router.py
文件。
内容如下:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from django.conf import settings
DATABASE_MAPPING = settings.DATABASE_APPS_MAPPING
class DatabaseAppsRouter(object):
"""
A router to control all database operations on models for different
databases.
In case an app is not set in settings.DATABASE_APPS_MAPPING, the router
will fallback to the `default` database.
Settings example:
DATABASE_APPS_MAPPING = {'app1': 'db1', 'app2': 'db2'}
这个路由,针对对不同的数据库,用于操作所有的数据库模型
如果一个应用没有在 settings 里的 DATABASE_APPS_MAPPING 中配置,那么这个路由将最后被 default 这个数据库来配置
设置示例(这里指 DATABASE_APPS_MAPPING 属性):
DATABASE_APPS_MAPPING = {'app1': 'db1', 'app2': 'db2'}
"""
def db_for_read(self, model, **hints):
""""
Point all read operations to the specific database.
将所有读取操作,指向对特定的数据库
"""
if model._meta.app_label in DATABASE_MAPPING:
return DATABASE_MAPPING[model._meta.app_label]
return None
def db_for_write(self, model, **hints):
"""
Point all write operations to the specific database.
将所有的写操作,指向特定的数据库
"""
if model._meta.app_label in DATABASE_MAPPING:
return DATABASE_MAPPING[model._meta.app_label]
return None
def allow_relation(self, obj1, obj2, **hints):
"""
Allow any relation between apps that use the same database.
允许 任何使用相同数据库的应用 的任何关系
"""
db_obj1 = DATABASE_MAPPING.get(obj1._meta.app_label)
db_obj2 = DATABASE_MAPPING.get(obj2._meta.app_label)
if db_obj1 and db_obj2:
if db_obj1 == db_obj2:
return True
else:
return False
return None
# Django 1.7 - Django 1.11
def allow_migrate(self, db, app_label, model_name=None, **hints):
print
db, app_label, model_name, hints
if db in DATABASE_MAPPING.values():
return DATABASE_MAPPING.get(app_label) == db
elif app_label in DATABASE_MAPPING:
return False
return None
我们依然需要进行数据库准备。
首先需要创建2个database,分别是:django_default
和 django
这2个。
然后执行以下三行代码做数据库的准备(创建table等)
记录改动:
python manage.py makemigrations
插入到数据库中:(后面的名字是下面DATABASES的属性的key值)
python manage.py migrate
python manage.py migrate --database=userdb
上面两行 migrate ,不带参数的,只生成default里配置的那些app的table。
带参数的,生成 DATABASES 这个 dict 里 key 为 userdb ,跟他相关的应用所需要的 table。
其他的复用之前使用默认mysql配置的代码,不需要改动。
唯一需要提一下的是,在 views.py
里操作数据库,我们之前使用代码例如:
models.UserInfo.objects.all()
这里是使用默认指定的db,我们也可以使用指定db,如下:
models.UserInfo.objects.using('userdb').all()
源代码参照我的github项目:(安装好依赖后就直接能跑)
https://github.com/qq20004604/Python3_Django_Demo
总的来说:
本文项目地址:
https://github.com/qq20004604/Python3_Django_Demo
请麻烦给一个Star和fork,github上有博主的QQ群,欢迎加群讨论。
参考文献: