做暧暧暖网站,怎么做网站底部备案号,矿泉水瓶手工制作大全,百度推广登录上一节提到了Django是基于MVC架构的Web框架#xff0c;MVC架构追求的是“模型”和“视图”的解耦合。所谓“模型”说得更直白一些就是数据#xff08;的表示#xff09;#xff0c;所以通常也被称作“数据模型”。在实际的项目中#xff0c;数据模型通常通过数据库实现持久… 上一节提到了Django是基于MVC架构的Web框架MVC架构追求的是“模型”和“视图”的解耦合。所谓“模型”说得更直白一些就是数据的表示所以通常也被称作“数据模型”。在实际的项目中数据模型通常通过数据库实现持久化操作而关系型数据库在过去和当下都是持久化的首选方案下面我们通过完成一个投票项目来讲解和模型相关的知识点。投票项目的首页会展示某在线教育平台所有的学科点击学科可以查看到该学科的老师及其信息用户登录后在查看老师的页面为老师投票可以投赞成票和反对票未登录的用户可以通过登录页进行登录尚未注册的用户可以通过注册页输入个人信息进行注册。在这个项目中我们使用MySQL数据库来实现数据持久化操作。
1 ORM模型
1.1 ORM介绍 对象关系映射Object Relational Mapping简称ORM模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。 简单的说ORM 是通过使用描述对象和数据库之间映射的元数据将程序中的对象自动持久化到关系数据库中。ORM 在业务逻辑层和数据库层之间充当了桥梁的作用。ORM 解决的主要问题是对象和关系的映射。它通常把一个类和一个表一一对应类的每个实例对应表中的一条记录类的每个属性对应表中的每个字段具体如下图所示。ORM 提供了对数据库的映射不用直接编写 SQL 代码只需像操作对象一样从数据库操作数据。让软件开发人员专注于业务逻辑的处理提高了开发效率。 ORM 模式也是有一定缺点的它会在一定程度上牺牲程序的执行效率。此外还存在许多复杂场景是 ORM 模式无法解决的同样还是需要手动编写 SQL 语句完成。
1.2 创建 Django 项目 首先创建Django项目vote在项目下创建名为polls的应用和保存模板页的文件夹tempaltes项目文件夹的结构如下所示。 根据上面描述的项目需求这里准备了四个静态页面分别是展示学科的页面subjects.html显示学科老师的页面teachers.html登录页面login.html注册页面register.html稍后我们会将静态页修改为Django项目所需的模板页。
1.3 数据库中生成模型表 在 Django 中一个模型(model)会映射到一个数据库表。每个模型都是一个 Python 类它是django.db.models.Model 的子类模型的每个属性都代表一个数据库字段。
(1) 在 polls 中添加数据模型 在 polls 的 models.py 中添加如下代码
from django.db import models # 引入Django.db.models模块class Subject(models.Model):编写Subject模型类数据模型应该继承于models.Model或其子类no models.AutoField(primary_keyTrue, verbose_name编号)name models.CharField(max_length50, verbose_name名称)intro models.CharField(max_length1000, verbose_name介绍)is_hot models.BooleanField(verbose_name是否热门)def __str__(self):return self.nameclass Meta:# 通过db_table自定义数据表名db_table tb_subjectclass Teacher(models.Model):编写Teacher模型类数据模型应该继承于models.Model或其子类sex_choices ((0, 女),(1, 男),)no models.AutoField(primary_keyTrue, verbose_name编号)name models.CharField(max_length20, verbose_name姓名)sex models.BooleanField(defaultTrue, verbose_name性别, choicessex_choices)birth models.DateField(verbose_name出生日期)intro models.CharField(max_length1000, verbose_name个人介绍)photo models.ImageField(max_length255, verbose_name照片)gcount models.IntegerField(default0, db_columngcount, verbose_name好评数)bcount models.IntegerField(default0, db_columnbcount, verbose_name差评数)sno models.ForeignKey(Subject, on_deletemodels.CASCADE, db_columnsno)def __str__(self):return self.nameclass Meta:db_table tb_teacherSubject 和 Teacher 模型中的每一个属性都指明了models下面的一个数据类型代表了数据库中的一个字段。上面的类在数据库中会创建如下的表见1.3节的第二步创建表格的过程。
(2) 迁移模型 使用 Django 给我们提供的两个命令来在数据库中生成 polls 应用下定义的数据模型第一步生成迁移文件第二步将迁移文件应用到数据库
python manage.py makemigrations
python manage.py migrate1.3 自动生成数据模型
1. 配置关系型数据库MySQL
(1) 在MySQL中创建数据库创建用户授权用户访问该数据库。
create database vote default charset utf8;
create user username% identified by yourpassword;
grant all privileges on vote.* to username%;
flush privileges;(2) 在 MySQL 中创建保存学科和老师信息的二维表保存用户信息的表稍后处理。
use vote;-- 创建学科表
create table tb_subject
(no integer auto_increment comment 学科编号,name varchar(50) not null comment 学科名称,intro varchar(1000) not null default comment 学科介绍,is_hot boolean not null default 0 comment 是不是热门学科,primary key (no)
);
-- 创建老师表
create table tb_teacher
(no integer auto_increment comment 老师编号,name varchar(20) not null comment 老师姓名,sex boolean not null default 1 comment 老师性别,birth date not null comment 出生日期,intro varchar(1000) not null default comment 老师介绍,photo varchar(255) not null default comment 老师照片,gcount integer not null default 0 comment 好评数,bcount integer not null default 0 comment 差评数,sno integer not null comment 所属学科,primary key (no),foreign key (sno) references tb_subject (no)
);(3) 安装数据库的驱动Python 3.x 使用 pymysql 作为 MySQL的驱动然后在Django项目文件夹的__init__.py中添加如下所示的代码
import pymysql
pymysql.install_as_MySQLdb() # 为了pymysql发挥最大数据库操作性能温馨提示 如果使用Django 2.2及以上版本还会遇到PyMySQL跟Django框架的兼容性问题兼容性问题会导致项目无法运行需要按照GitHub上PyMySQL仓库Issues中提供的方法进行处理。总体来说使用pymysql会比较麻烦强烈建议大家首选安装mysqlclientmysqlclient执行效率也比较高。
(4) 修改项目的settings.py文件首先将我们创建的应用polls添加已安装的项目INSTALLED_APPS中然后配置MySQL作为持久化方案。
INSTALLED_APPS [django.contrib.admin,django.contrib.auth,django.contrib.contenttypes,django.contrib.sessions,django.contrib.messages,django.contrib.staticfiles,polls, # 把应用文件加入
]ATABASES {default: {# 数据库引擎配置ENGINE: django.db.backends.mysql,# 数据库的名字NAME: vote,# 数据库服务器的IP地址本机可以写为localhost或127.0.0.1)HOST: localhost,# 启动MySQL服务的端口号PORT: 3306,# 数据库用户名和口令USER: carpediem,PASSWORD: carpediem2021,# 数据库使用的字符集CHARSET: utf8,# 数据库时间日期的时区设定TIME_ZONE: Asia/Chongqing,}
}在配置ENGINE属性时常用的可选值包括
django.db.backends.sqlite3SQLite嵌入式数据库。django.db.backends.postgresqlBSD许可证下发行的开源关系型数据库产品。django.db.backends.mysql甲骨文公司经济高效的数据库产品。django.db.backends.oracle甲骨文公司关系型数据库旗舰产品。 其他的配置可以参考官方文档中的数据库配置部分。
(5) Django框架提供了ORM来解决数据持久化问题ORM翻译成中文叫“对象关系映射”。因为Python是面向对象的编程语言我们在Python程序中使用对象模型来保存数据而关系型数据库使用关系模型用二维表来保存数据这两种模型并不匹配。使用ORM是为了实现对象模型到关系模型的双向转换这样就不用在Python代码中书写SQL语句和游标操作因为这些都会由ORM自动完成。利用Django的ORM我们可以直接将刚才创建的学科表和老师表变成Django中的模型类。
python manage.py inspectdb polls/models.py我们可以对自动生成的模型类稍作调整代码如下所示。
from django.db import modelsclass Subject(models.Model):no models.AutoField(primary_keyTrue, verbose_name编号)name models.CharField(max_length50, verbose_name名称)intro models.CharField(max_length1000, verbose_name介绍)is_hot models.BooleanField(verbose_name是否热门)class Meta:managed Falsedb_table tb_subjectclass Teacher(models.Model):no models.AutoField(primary_keyTrue, verbose_name编号)name models.CharField(max_length20, verbose_name姓名)sex models.BooleanField(defaultTrue, verbose_name性别)birth models.DateField(verbose_name出生日期)intro models.CharField(max_length1000, verbose_name个人介绍)photo models.ImageField(max_length255, verbose_name照片)gcount models.IntegerField(default0, db_columngcount, verbose_name好评数)bcount models.IntegerField(default0, db_columnbcount, verbose_name差评数)sno models.ForeignKey(Subject, models.DO_NOTHING, db_columnsno)class Meta:managed Falsedb_table tb_teacher若你的确想要允许 Django 管理这些表格的生命周期你需要将上面的 managed 选项的值改为 True 或者删掉它因为 True 是默认值 温馨提示 所有模型都是django.db.models.Model类的子类模型类跟关系型数据库的二维表对应模型对象跟表中的记录对应模型对象的属性跟表中的字段对应。每个字段由django.db.models.Field子类内置在Django core的实例表示它们并将被转换为数据库的列。 该功能仅是一个快捷方式不是最佳的创建模型的方法。参考 inspectdb 文档 获取更多信息
补充 1. 通用字段属性
选项说明null数据库中对应的字段是否允许为NULL默认为Falseblank后台模型管理验证数据时是否允许为NULL默认为Falsechoices设定字段的选项各元组中的第一个值是设置在模型上的值第二值是人类可读的值db_column字段对应到数据库表中的列名未指定时直接使用字段的名称db_index设置为True时将在该字段创建索引db_tablespace为有索引的字段设置使用的表空间默认为DEFAULT_INDEX_TABLESPACEdefault字段的默认值editable字段在后台模型管理或ModelForm中是否显示默认为Trueerror_messages设定字段抛出异常时的默认消息的字典其中的键包括null、blank、invalid、invalid_choice、unique和unique_for_datehelp_text表单小组件旁边显示的额外的帮助文本。primary_key将字段指定为模型的主键未指定时会自动添加AutoField用于主键只读。unique设置为True时表中字段的值必须是唯一的verbose_name字段在后台模型管理显示的名称未指定时使用字段的名称
2. ForeignKey属性
limit_choices_to值是一个Q对象或返回一个Q对象用于限制后台显示哪些对象。related_name用于获取关联对象的关联管理器对象反向查询如果不允许反向该属性应该被设置为或者以结尾。to_field指定关联的字段默认关联对象的主键字段。db_constraint是否为外键创建约束默认值为True。on_delete外键关联的对象被删除时对应的动作可取的值包括django.db.models中定义的 CASCADE级联删除。PROTECT抛出ProtectedError异常阻止删除引用的对象。SET_NULL把外键设置为null当null属性被设置为True时才能这么做。SET_DEFAULT把外键设置为默认值提供了默认值才能这么做。
3. ManyToManyField属性
symmetrical是否建立对称的多对多关系。through指定维持多对多关系的中间表的Django模型。throughfields定义了中间模型时可以指定建立多对多关系的字段。db_table指定维持多对多关系的中间表的表名。
4. 模型元数据选项
选项说明abstract设置为True时模型是抽象父类app_label如果定义模型的应用不在INSTALLED_APPS中可以用该属性指定db_table模型使用的数据表名称db_tablespace模型使用的数据表空间default_related_name关联对象回指这个模型时默认使用的名称默认为model_name_setget_latest_by模型中可排序字段的名称。managed设置为True时Django在迁移中创建数据表并在执行flush管理命令时把表移除order_with_respect_to标记对象为可排序的ordering对象的默认排序permissions创建对象时写入权限表的额外权限default_permissions默认为(add, change, delete)unique_together设定组合在一起时必须独一无二的字段名index_together设定一起建立索引的多个字段名verbose_name为对象设定人类可读的名称verbose_name_plural设定对象的复数名称2 使用ORM完成模型的CRUD操作
2.1 基本的增删改查 有了Django框架的ORM我们可以直接使用面向对象的方式来实现对数据的CRUD增删改查操作。我们可以在PyCharm的终端中输入下面的命令进入到Django项目的交互式环境然后尝试对模型的操作。
python manage.py shell1. 新增
from polls.models import SubjectSubject.objects.create(nameH5前端开发, intro前段比较热的学科, is_hotTrue)subject1 Subject(namePython全栈开发, intro当下最热门的学科, is_hotTrue)
subject1.save()
subject2 Subject(name全栈软件测试, intro学习自动化测试的学科, is_hotFalse)
subject2.save()
subject3 Subject(nameJavaEE分布式开发, intro基于Java语言的服务器应用开发, is_hotTrue)2. 删除
subject Subject.objects.get(no2)
subject.delete()3. 更新
subject Subject.objects.get(no1)
subject.name Python全栈人工智能
subject.save()4. 查询
(1) 查询所有对象
Subject.objects.all()(2) 过滤数据
# 查询名称为“Python全栈人工智能”的学科
Subject.objects.filter(namePython全栈人工智能)# 查询名称包含“全栈”的学科模糊查询
Subject.objects.filter(name__contains全栈)
Subject.objects.filter(name__startswith全栈)
Subject.objects.filter(name__endswith全栈)# 查询所有热门学科
Subject.objects.filter(is_hotTrue)# 查询编号大于3小于10的学科
Subject.objects.filter(no__gt3).filter(no__lt10)
Subject.objects.filter(no__gt3, no__lt10)# 查询编号在3到7之间的学科
Subject.objects.filter(no__gte3, no__lte7)
Subject.objects.filter(no__range(3, 7))(3) 查询单个对象
# 查询主键为1的学科
Subject.objects.get(pk1)
Subject.objects.get(no1)
Subject.objects.filter(no1).first()
Subject.objects.filter(no1).last()(4) 排序
# 查询所有学科按编号升序排列
Subject.objects.order_by(no)
# 查询所有部门按部门编号降序排列
Subject.objects.order_by(-no)(5) 切片
# 按编号从小到大查询前3个学科
Subject.objects.order_by(no)[:3](6) 计数
# 查询一共有多少个学科
Subject.objects.count()(7) 高级查询
# 查询编号为1的学科的老师
Teacher.objects.filter(sno__no1)
Subject.objects.get(pk1).teacher_set.all() # 查询学科名称有“全栈”二字的学科的老师
Teacher.objects.filter(sno__name__contains全栈) 上面的 objects 是一个特殊的属性通过它来查询数据库它是模型的一个 Manager。在 filter() 方法中还有一些比较神奇的双下划线辅助我们进一步过滤结果详细了解请阅读官方文档————执行查询
温馨提示
说明1由于老师与学科之间存在多对一外键关联所以能通过学科反向查询到该学科的老师从一对多关系中“一”的一方查询“多”的一方反向查询属性默认的名字是类名小写_set如上面例子中的teacher_set当然也可以在创建模型时通过ForeingKey的related_name属性指定反向查询属性的名字。如果不希望执行反向查询可以将related_name属性设置为’‘或者以’开头的字符串。说明2ORM查询多个对象时会返回QuerySet对象QuerySet使用了惰性查询即在创建QuerySet对象的过程中不涉及任何数据库活动等真正用到对象时对QuerySet求值才向数据库发送SQL语句并获取对应的结果这一点在实际开发中需要引起注意说明3如果希望更新多条数据不用先逐一获取模型对象再修改对象属性可以直接使用QuerySet对象的update()方法一次性更新多条数据。 参考
Django 使用原生的 SQL 语句操作 MySQL 数据库https://www.imooc.com/wiki/djangolesson/nativesql.html深入模型https://gitee.com/zengyujin/Python-100-Days/blob/master/Day41-55/42.深入模型.mdDjango入门指南-第5章模型设计:https://www.bookstack.cn/read/django-beginners-guide-zh/Fundamentals-2.mdDjango v4.0 中文文档 模型https://www.bookstack.cn/read/Django-4.0-zh/94d959954f3d0daa.md