【Django】ORM操作#1 -- 2019-08-17 06:11:59
目录
原文: http://blog.gqylpy.com/gqy/260"@
一、介绍概念对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的基石. 简单的说,ORM时通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久华到关系数据库中. ORM在业务逻辑层和数据库层之间充当了桥梁的作用. 由来让我们从O/R开始。字母O起源于"对象"(Object),而R则来自于"关系"(Relational). 几乎所有的软件开发过程中都会涉及到对象和关系数据库。在用户层面和业务逻辑层面,我们是面向对象的。当对象的信息发生变化的时候,我们就需要把对象的信息保存在关系数据库中. 按照之前的方式来进行开发就会出现程序员会在自己的业务逻辑代码中存在很多杂乱的SQL语句用来增加、读取、修改、删除相关数据,而这些代码通常都是重复的. 优势ROM解决的主要问题是对象和关系的映射,它通常把一个类和一个表一一对应,类的每个实例对应表中的一条记录,类的每个属性对应表中的每个字段. ORM提供了对数据库的映射,不用直接编写SQL代码,只需像操作对象一样从数据库操作数据. 让软件开发人员专注于业务逻辑的处理,提高了开发效率 劣势ROM的缺点是会在一定程度上牺牲程序的执行效率. ORM用多了,SQL语句就不会写了,关系数据库相关技能退化... 总结ORM只是一种工具,工具确实能解决一些重复的、简单的劳动,这是不可否认的. 但我们不能指望某个工具一劳永逸地解决所有问题,一些特殊问题还是需要特殊处理的. 但是在整个软件开发过程中需要特殊处理的情况应该是很少的,否则所谓的工具也就失去了它存在的意义. 二、Django中的ORMDjango项目使用MySQL1. 在Django项目的settings.py文件中配置数据库连接信息: DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql',# 将后缀改为mysql 'NAME': "数据库名",'HOST': "数据库IP",'PORT': "端口",'USER': "远程用户",'PASSWORD': "远程用户密码",} } ***2. 在与settings.py同级的__init__.py文件中添加如下代码,告诉Django使用pymysql模块连接MySQL数据库:*** import pymysql pymysql.install_as_MySQLdb()
Model在Django中,model是你的数据的单一、明确的来源,它包含了你存储的数据的重要字段和行为。通常,一个模型(Model)映射到一个数据库表. 基本情况:
ORM与DB的关系: *** 快速入门下面这个例子定义了一个Person模型,包含name和sex: from django.db import models class Person(models.Model): name = models.CharField(max_length=24) sex = models.CharField(max_length=24) ==name和sex是模型的字段,每个字段被指定为一个属性,每个属性映射到一个数据库列.== 上面的Person模型将会像下面这样创建一个数据库表: create table myapp_person ( id serial not null primary key,name varchar(24) not null,sex varchar(24) not null ); 一些说明:
1. AutoFieldint自增列,必须传入参数:primary_key=true 2. IntegerField整数类型(int). 示例: # 设置性别: 1,2为存的值; "男","女"为显示的值. sex = models.IntegerField(choices=((1,'男'),(2,'女'))) 3. CharField字符类型(varchar),必须提供max_length参数. 4. ForeignKey用于创建外键 语法示例: class Press(models.Model): # 出版社 p_name = models.CharField(max_length=24) class Author(models.Model): # 作者 a_name = models.CharField(max_length=24) class Book(models.Model): # 书籍 b_name = models.CharField(max_length=24) class Relation(models.Model): # 书籍,作者,出版社对应关系 # 关联3个外键 book = models.ForeignKey(Book,on_delete=models.CASCADE) author = models.ForeignKey(Author,on_delete=models.CASCADE) press = models.ForeignKey(Press,on_delete=models.CASCADE) **创建后,会将外键字段名自动添加上"_id"后缀.** 5. DateField日期字段,日期格式:YYYY-MM-DD 6. DateTimeField日期时间字段,格式:YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]
7. dalate()删除 用法: 类名.objects.filter(字段名="条件").delete() 字段合集AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) - bigint自增列,必须填入参数 primary_key=True 注:当model中如果没有自增列,则自动会创建一个列名为id的列 from django.db import models class UserInfo(models.Model): # 自动创建一个列名为id的且为自增的整数列 username = models.CharField(max_length=32) class Group(models.Model): # 自定义自增列 nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) SmallIntegerField(IntegerField): - 小整数 -32768 ~ 32767 PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin,IntegerField) - 正小整数 0 ~ 32767 IntegerField(Field) - 整数列(有符号的) -2147483648 ~ 2147483647 PositiveIntegerField(PositiveIntegerRelDbTypeMixin,IntegerField) - 正整数 0 ~ 2147483647 BigIntegerField(IntegerField): - 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807 BooleanField(Field) - 布尔值类型 NullBooleanField(Field): - 可以为空的布尔值 CharField(Field) - 字符类型 - 必须提供max_length参数, max_length表示字符长度 TextField(Field) - 文本类型 EmailField(CharField): - 字符串类型,Django Admin以及ModelForm中提供验证机制 IPAddressField(Field) - 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制 GenericIPAddressField(Field) - 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6 - 参数: protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6" unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启此功能,需要protocol="both" URLField(CharField) - 字符串类型,Django Admin以及ModelForm中提供验证 URL SlugField(CharField) - 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号) CommaSeparatedIntegerField(CharField) - 字符串类型,格式必须为逗号分割的数字 UUIDField(Field) - 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证 FilePathField(Field) - 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能 - 参数: path,文件夹路径 match=None,正则匹配 recursive=False,递归下面的文件夹 allow_files=True,允许文件 allow_folders=False,允许文件夹 FileField(Field) - 字符串,路径保存在数据库,文件上传到指定目录 - 参数: upload_to = "" 上传文件的保存路径 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage ImageField(FileField) - 字符串,路径保存在数据库,文件上传到指定目录 - 参数: upload_to = "" 上传文件的保存路径 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage width_field=None,上传图片的高度保存的数据库字段名(字符串) height_field=None 上传图片的宽度保存的数据库字段名(字符串) DateTimeField(DateField) - 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] DateField(DateTimeCheckMixin,Field) - 日期格式 YYYY-MM-DD TimeField(DateTimeCheckMixin,Field) - 时间格式 HH:MM[:ss[.uuuuuu]] DurationField(Field) - 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型 FloatField(Field) - 浮点型 DecimalField(Field) - 10进制小数 - 参数: max_digits,小数总长度 decimal_places,小数位长度 BinaryField(Field) - 二进制类型 ORM字段与数据库字段对应关系
自定义字段from django.db import models # 自定义字段类 class FixedCharField(models.Field): """自定义的char类型字段类""" def __init__(self,max_length,*args,**kwargs): self.max_length = max_length super(FixedCharField,self).__init__(max_length=max_length,**kwargs) def db_type(self,connection): """限制生成数据库表的字段类型为char,长度为max_length指定的值""" return 'char(%s)' % self.max_length # 表结构类 class Class(models.Model): varchar_type = models.CharField(max_length=32) # 自带的varchar类型 char_type = FixedCharField(max_length=32) # 自定义的char类型 上面的代码创建的表结构如下: mysql> desc app01_class; +--------------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +--------------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | varchar_type | varchar(32) | NO | | NULL | | | char_type | char(32) | NO | | NULL | | +--------------+-------------+------+-----+---------+----------------+ 3 rows in set (0.00 sec) 字段参数1. null指定某个字段可以为空 2. unique指定某个字段在该表中唯一 3. db_index指定某个字段为索引 4. default为某个字段设置默认值 5. DateField 与 DateTimefield参数:
四、关系字段一对多 ForeignKey外键类型在ORM中用来表示外键关联关系. ForeignKey可以和其它表做关联关系,同时也可以和自身做关联关系. 字段参数1. to设置要关联的表 # 语法: 属性名 = models.FreignKey(to="类名") 2. to_field设置要关联的字段 示例: from django.db import models class Test01(models.Model): test01 = models.CharField(max_length=32,unique=True) # 注意:外键的值必须唯一,所以写上 uniuqe=True class Test02(models.Model): # 关联Test01表的test01字段 test02 = models.ForeignKey(to='Test01',to_field='test01') 3. related_name反向操作时使用的字段名,用于代替原反向查询时的"表名_set". 举例说明: from django.db import models class Department(models.Model): name = models.CharField(max_length=32) class Employees(models.Model): name = models.CharField(max_length=32) dep = models.ForeignKey(to='Department') # 外键 当我们要查询某个班级关联的所有学生(反向查询)时,我们会这么写: models.Department.objects.first().employees_set.all() 当我们在ForeignKey字段中添加了参数related_name后, dep = models.ForeignKey(to='Department',related_name='emps') 此时,我们要查询某个班级关联的所有学生(反向查询)时,我们会这么写: models.Department.objects.first().emps.all() 4. related_query_name反向查询操作时,使用的连接前缀,用于替换表名. 5. on_delete当删除关联表中的数据时,当前表与其关联的行的行为.
def func(): return 10 class Test(models.Model): user = models.ForeignKey( to='user',# 可执行对象的返回值 on_delete=models.SET(func) ) 6. db_constraint是否在数据库中创建外键约束,默认为True. 一对一 OneToOneField==一对一字段通常用来扩展已有字段== 一对一的关联关系多用在:当一张表的不同字段查询频率差距过大的情况下,将原本可以存储在一张表中的字段拆开放置在两张表中,然后将两张表建立一对一的关联关系 示例: class Author(models.Model): name = models.CharField(max_length=32) info = models.OneToOneField(to='AuthorInfo') # 一对一 class AuthorInfo(models.Model): phone = models.CharField(max_length=11) email = models.EmailField() 字段参数1. to设置要关联的表 2. to_field设置要关联的表的字段 3. on_delete同ForeignKey字段 多对多 ManyToManyField用于表示多对多的关联关系. 字段参数1. to设置要关联的表 2. related_name同ForeignKey字段 3. related_query_name同ForeignKey字段 4. symmetrical指定内部是否创建反向操作的字段,默认为True. 举例说明: class Dep(models.Model): # 部门 name = models.CharField(max_length=32) class Emp(models.Model): # 员工 name = models.CharField(max_length=32) dep = models.ManyToManyField(to='Dep') # 未创建反向操作字段 # 此时,Emp对象没有person_set属性,不可反向查询 class Dep(models.Model): # 部门 name = models.CharField(max_length=32) class Emp(models.Model): # 员工 name = models.CharField(max_length=32) dep = models.ManyToManyField(to='Dep',symmetrical=False) # 创建反向操作字段 # 此时,Emp对象就可以使用person_set属性进行反向查询. 5. through在使用ManyToManyField字段时,Django会自动生成一张表来管理多对多的关联关系. 6. through_fields设置要关联的表的字段 语法: through_fields(field1,field2) # field1:指定ManyToManyField的模型外键的名 # field2:指定关联目标模型的外键名 7. db_table默认创建第三张表时,数据库中表的名称. 多对多关系的三种方式自行创建第三张表from django.db import models class Book(models.Model): name = models.CharField(max_length=32,verbose_name="书籍名称") class Author(models.Model): name = models.CharField(max_length=32,verbose_name="作者姓名") # 自行创建第三张表,分别通过外键关联书和作者 class Author2Book(models.Model): author = models.ForeignKey(to='Author') book = models.ForeignKey(to='Book') class Meta: unique_together = ('author','book') 通过ManyToManyField自动创建第三张表from django.db import models class Book(models.Model): name = models.CharField(max_length=32,verbose_name="书籍名称") # 通过ORM自带的ManyToManyField自动创建第三张表 class Author(models.Model): name = models.CharField(max_length=32,verbose_name="作者姓名") books = models.ManyToManyField(to='Book',related_name='authors') 设置ManyToManyField并指定自行创建的第三张表from django.db import models class Book(models.Model): name = models.CharField(max_length=32,verbose_name="书籍名称") # 自己创建第三张表,并通过ManyToManyField指定关联 class Author(models.Model): name = models.CharField(max_length=32,through='Author2Book',through_fields=('author','book')) # through_fields接收一个2元组('field1','field2') # 其中field1指定定义ManyToManyField的模型外键的名(author) # field2是关联目标模型的外键名(book) class Author2Book(models.Model): author = models.ForeignKey(to='Author') book = models.ForeignKey(to='Book') class Meta: unique_together = ('author','book') 注意: 但是当我们使用第三种方式创建多对多关联关系时,就无法使用set、add、remove、clear方法来管理多对多的关系了,需要通过第三张表的model来管理多对多关系. 元消息ORM对应的类里面包含另一个Meta类,而Meta类封装了一些数据库的消息。主要字段如下:
更多操作请见:【Django】ORM操作#2 原文: http://blog.gqylpy.com/gqy/260(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |