Django--模型&数据库CRUD
ORM对象关系映射(Object Relational Mapping)用于实现面向对象编程语言里不同类型系统的数据之间的转换。ORM 是通过使用描述对象和数据库之间的映射的元数据,将程序中的对象自动持久化到数据库中。
- ORM 在业务逻辑层和数据库层之间充当了桥梁的作用。
- Django 模型使用自带的 ORM。
本地环境
- python3.6.5
- Django2.2.17
1. 修改Django项目的数据库配置
- 修改settings.py中DATABASES数据库配置
DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': BASE_DIR / 'db.sqlite3',
# }
'default': {
'ENGINE': 'django.db.backends.mysql', # 数据库引擎
'NAME': 'ma', # 数据库名称
'HOST': '127.0.0.1', # 数据库地址
'PORT': 3306, # 数据库端口
'USER': 'root', # 数据库用户名
'PASSWORD': '123456', # 数据库密码
}
}
- 修改与 settings.py 同级目录下的 init.py 中引入模块和进行配置。否则启动服务时会报错
import pymysql
pymysql.install_as_MySQLdb()
未引入pymysql时报错如下
- 因为 ORM 无法操作到数据库级别,只能操作到数据表,所以如果要操作新的数据库,需提前新建一个数据库。
- 进入mysql服务后执行如下语句:
create database ma default charset=utf8mb4;
#设置字符集为uftmb4后排序规则默认为uft8mb4_general_ci; - 或者通过桌面客户端新建数据库
2. 定义模型
新建一个app
Django 规定,如果要使用模型,必须要创建一个 app。
- 进入项目目录执行命令:
django-admin startapp Account
-
执行成功后,生成的app数据如下
模型app的目录结构
创建模型
修改Account/models.py文件:
- 类名:代表数据库表名,且继承了models.Model
- 类属性:代表数据表中的字段。数据类型则由IntegerField(对应数据库的int类型),CharField(对应数据库的varchar类型,max_length 参数限定长度),DateTimeFiled(对应数据库的datetime类型,日期显示为年-月-日 时:分:秒),DateField(相当于数据库date类型,日期精确到年-月-日)
from django.db import models
# Create your models here.
class User(models.Model):
nickname = models.CharField(max_length=20)
age = models.IntegerField()
birthday = models.DateField()
create_at = models.DateTimeField()
updated_at = models.DateTimeField()
添加模型配置
- 修改settings.py 中找到INSTALLED_APPS,添加新创建的模型app
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'Account', # 添加此项
)
执行自带的迁移文件migrate
- 项目目录下运行:
python manage.py migrate
,执行迁移后会在当前路径下生成db.sqlite3的数据库文件。
3. 生成迁移文件并执行迁移
- 生成迁移文件:
python manage.py makemigrations {appName}
,执行该命令后Account目录下的migrations文件夹会生成对应迁移内容
- 执行迁移:
python manage.py migrate {appName}
,执行该命令后会创建表结构等。
-
执行命令后报错mysqlclient版本过低,原因是 MySQLclient 目前只支持到 Python3.4,因此如果使用的更高版本的 python,需要修改如下:
报错mysqlclient版本过低 -
修改文件D:\Python3\Lib\site-packages\django\db\backends\mysql\base.py文件:
修改Django包中对mysqlclient版本的限制导致执行迁移报错问题
- 迁移执行成功后生成的数据库表如下:
- django_content_type表和auth_permission表记录模型的CRUD
-
创建app,生成迁移文件,执行迁移之后在django_content_type表会新增该app下的模型model记录,在auth_permission表中对每一个model就会新增4条CRUD记录。
django_content_type表
自定义数据库表名和字段名
- Django中生成的数据库表名默认为{appname}_类名,如果想生成的表名直接是数据库类名的话需要做如下修改:
from django.db import models
# Create your models here.
class User(models.Model):
# 在Meta 类中通过db_table自定义数据库表名
class Meta:
db_table = 'user'
# 通过 db_column 自定义数据库字段名
nickname = models.CharField(max_length=20, db_column='nickname')
age = models.IntegerField(db_column='age')
birthday = models.DateField(auto_now=True)
create_at = models.DateTimeField(auto_now=True)
updated_at = models.DateTimeField(auto_now=True)
- 然后重新生成迁移文件并执行迁移即可生效。
操作数据库CRUD
1. 添加数据
保存并提交数据:create(),save()
方式一:通过 ORM 提供的 objects 提供的方法 create() 来实现(推荐)
方式二:模型类实例化对象.save()
- 在app同级目录Account,views.py中添加数据:
# views.py
from Account.models import User
from django.http import HttpResponse
def add_user(request):
user = User.objects.create(nickname="test", age=1, birthday="2020-9-25")
return HttpResponse("<p>添加用户数据成功!</p>")
def add_user2(request):
user = User(nickname="test", age=1, birthday="2020-9-25")
user.save()
return HttpResponse("<p>添加用户数据成功!</p>")
- 修改django_demo/urls.py文件添加路由映射:
from django.contrib import admin
from django.urls import path
from django.conf.urls import url
from . import views
from Account import views as account_views
urlpatterns = [
path('admin/', admin.site.urls),
url(r'^$', views.hello),
url('add_user/', account_views.add_user),
]
- 访问http://loacalhost:8000/add_user,提示新增数据成功
-
查看数据库中的数据如下
新增user数据
2. 查询数据
-
查询语句:
-
User.objects.filter(age=1)
#返回数组,当查询的是结果为空时返回空数组: <QuerySet [<User: User object (6)>, <User: User object (9)>]>,其中6和9指的是符合要求的所在行id -
User.objects.get(age=1)
# 返回一个对象User object (7),当查询到的数据为空或者查询到多条数据时会报错,其中7指的是符合要求的数据所在行id -
修改opdb_user.py文件:
# 查询数据库表user
def query_user(request):
# 获取所有的user
users = User.objects.all()
response = ""
for user in users:
response += "nickname: {}-----age:{}----birthday: {}<br/>".format(user.nickname, user.age, user.birthday)
return HttpResponse(response)
- 修改urls.py文件,新增url映射关系:url('query_user/', opdb_user.query_user),
-
页面效果如下
显示所有的user -
User.objects.get(age=1)
当查询到的条数大于1时,报错如下:
get()查询到的条数不为1时报错
3. 更新数据
修改数据可以使用 save() 或 update()
- 修改opdb_user.py文件:
# 更新数据
def update_user(request):
# 方式1
user = User.objects.get(id=1)
user.nickname = "哈哈哈" # 并且create_at和updated_at会更新为当前时间
user.save()
# 方式2
User.objects.filter(id=3).update(nickname="呵呵呵", age=100) # create_at和updated_at不会更新
return HttpResponse("<p>修改数据成功!</p>")
- 修改urls.py文件添加url映射:url('update_user/', opdb_user.update_user),
- 页面访问http://localhost:8000/update_user/,并查看数据库效果
4. 删除数据
可以删除单个实例对象:
User.objects.get(pk=pk).delete()
也可以删除实例结果集:User.objects.filter(age=10).delete()
- 修改opdb_user.py文件
# 删除数据
def delete_user(request):
user = User.objects.filter(age=100) # 当查询的结果为空时,执行删除操作不会报错
user.delete()
return HttpResponse("<p>删除age=100的所有用户</p>")
- 修改urls.py文件添加url映射:url('delete_user/', opdb_user.delete_user),
- 页面访问http://localhost:8000/delete_user/,并查看数据库效果