Python中强大的通用ORM框架:SQLAlchemy

Posted HaimaBlog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python中强大的通用ORM框架:SQLAlchemy相关的知识,希望对你有一定的参考价值。

Python中强大的通用ORM框架:SQLAlchemy
https://zhuanlan.zhihu.com/p/444930067

python-- Django ORM

Django ORM(基础)

Django 框架十分强大,自带数据库操作功能。Django 跟 SQLAchemy 一样,也是通过ORM(Object Relational Mapping,关系对象映射)的方式对数据库进行操作,django中遵循 Code Frist (根据代码中定义的类来自动生成数据库表)的原则。

 

一、创建表

1、在SQLite中创建表

1.1、在app中的models.py中先写类:

from django.db import models
# Create your models here.


class UserInfo(models.Model):
    # id列,Django框架会默认生成id(自增,主键),也可以通过AutoField类型自定义主键,不过Django框架默认生成ID列会失效
    # 用户名列,字符串类型,最大长度长度
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=64)
  1  AutoField(Field)
  2         - int自增列,必须填入参数 primary_key=True
  3 
  4     BigAutoField(AutoField)
  5         - bigint自增列,必须填入参数 primary_key=True
  6 
  7         注:当model中如果没有自增列,则自动会创建一个列名为id的列
  8         from django.db import models
  9 
 10         class UserInfo(models.Model):
 11             # 自动创建一个列名为id的且为自增的整数列
 12             username = models.CharField(max_length=32)
 13 
 14         class Group(models.Model):
 15             # 自定义自增列
 16             nid = models.AutoField(primary_key=True)
 17             name = models.CharField(max_length=32)
 18 
 19     SmallIntegerField(IntegerField):
 20         - 小整数 -3276832767
 21 
 22     PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
 23         - 正小整数 032767
 24     IntegerField(Field)
 25         - 整数列(有符号的) -21474836482147483647
 26 
 27     PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
 28         - 正整数 02147483647
 29 
 30     BigIntegerField(IntegerField):
 31         - 长整型(有符号的) -92233720368547758089223372036854775807
 32 
 33     自定义无符号整数字段
 34 
 35         class UnsignedIntegerField(models.IntegerField):
 36             def db_type(self, connection):
 37                 return \'integer UNSIGNED\'
 38 
 39         PS: 返回值为字段在数据库中的属性,Django字段默认的值为:
 40             \'AutoField\': \'integer AUTO_INCREMENT\',
 41             \'BigAutoField\': \'bigint AUTO_INCREMENT\',
 42             \'BinaryField\': \'longblob\',
 43             \'BooleanField\': \'bool\',
 44             \'CharField\': \'varchar(%(max_length)s)\',
 45             \'CommaSeparatedIntegerField\': \'varchar(%(max_length)s)\',
 46             \'DateField\': \'date\',
 47             \'DateTimeField\': \'datetime\',
 48             \'DecimalField\': \'numeric(%(max_digits)s, %(decimal_places)s)\',
 49             \'DurationField\': \'bigint\',
 50             \'FileField\': \'varchar(%(max_length)s)\',
 51             \'FilePathField\': \'varchar(%(max_length)s)\',
 52             \'FloatField\': \'double precision\',
 53             \'IntegerField\': \'integer\',
 54             \'BigIntegerField\': \'bigint\',
 55             \'IPAddressField\': \'char(15)\',
 56             \'GenericIPAddressField\': \'char(39)\',
 57             \'NullBooleanField\': \'bool\',
 58             \'OneToOneField\': \'integer\',
 59             \'PositiveIntegerField\': \'integer UNSIGNED\',
 60             \'PositiveSmallIntegerField\': \'smallint UNSIGNED\',
 61             \'SlugField\': \'varchar(%(max_length)s)\',
 62             \'SmallIntegerField\': \'smallint\',
 63             \'TextField\': \'longtext\',
 64             \'TimeField\': \'time\',
 65             \'UUIDField\': \'char(32)\',
 66 
 67     BooleanField(Field)
 68         - 布尔值类型
 69 
 70     NullBooleanField(Field):
 71         - 可以为空的布尔值
 72 
 73     CharField(Field)
 74         - 字符类型
 75         - 必须提供max_length参数, max_length表示字符长度
 76 
 77     TextField(Field)
 78         - 文本类型
 79 
 80     EmailField(CharField):
 81         - 字符串类型,Django Admin以及ModelForm中提供验证机制
 82 
 83     IPAddressField(Field)
 84         - 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制
 85 
 86     GenericIPAddressField(Field)
 87         - 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
 88         - 参数:
 89             protocol,用于指定Ipv4或Ipv6, \'both\',"ipv4","ipv6"
 90             unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要protocol="both"
 91 
 92     URLField(CharField)
 93         - 字符串类型,Django Admin以及ModelForm中提供验证 URL
 94 
 95     SlugField(CharField)
 96         - 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)
 97 
 98     CommaSeparatedIntegerField(CharField)
 99         - 字符串类型,格式必须为逗号分割的数字
100 
101     UUIDField(Field)
102         - 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证
103 
104     FilePathField(Field)
105         - 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能
106         - 参数:
107                 path,                      文件夹路径
108                 match=None,                正则匹配
109                 recursive=False,           递归下面的文件夹
110                 allow_files=True,          允许文件
111                 allow_folders=False,       允许文件夹
112 
113     FileField(Field)
114         - 字符串,路径保存在数据库,文件上传到指定目录
115         - 参数:
116             upload_to = ""      上传文件的保存路径
117             storage = None      存储组件,默认django.core.files.storage.FileSystemStorage
118 
119     ImageField(FileField)
120         - 字符串,路径保存在数据库,文件上传到指定目录
121         - 参数:
122             upload_to = ""      上传文件的保存路径
123             storage = None      存储组件,默认django.core.files.storage.FileSystemStorage
124             width_field=None,   上传图片的高度保存的数据库字段名(字符串)
125             height_field=None   上传图片的宽度保存的数据库字段名(字符串)
126 
127     DateTimeField(DateField)
128         - 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]
129 
130     DateField(DateTimeCheckMixin, Field)
131         - 日期格式      YYYY-MM-DD
132 
133     TimeField(DateTimeCheckMixin, Field)
134         - 时间格式      HH:MM[:ss[.uuuuuu]]
135 
136     DurationField(Field)
137         - 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型
138 
139     FloatField(Field)
140         - 浮点型
141 
142     DecimalField(Field)
143         - 10进制小数
144         - 参数:
145             max_digits,小数总长度
146             decimal_places,小数位长度
147 
148     BinaryField(Field)
149         - 二进制类型
models字段类型
 1 class User(models.Model):
 2     name = models.CharField(max_length=32)
 3     pwd = models.CharField(max_length=32)
 4 #class User(models.Model):
 5 #    name = models.CharField(max_length=32,db_index=True)
 6 #    pwd = models.CharField(max_length=32,db_index=True)
 7 class Meta:
 8     #指定数据库表名:tb1,如果不指定表名将会默认生成表名:app名称 + 下划线 + 类名
 9     db_table = "tb1"
10 
11     #索引,mysql每一列加上索引就会生成一个文件,因此当上面被注释的User表生成是mysql数据库就会生成一个表,两个文件,
12     #因此不想数据库生成太多索引文件,又想个别列名能够支持索引查询,这个时候就需要用到联合索引,
13     index_together = [  # 联合索引,只会生成一个索引文件 但是有一个缺点就是,遵循最左前缀模式查询
14         ("name", \'pwd\'),
15     ]
16 
17     # 最左前缀的模式:
18     # select * from where name=\'xx\'
19     # select * from where name=\'xx\' and email = \'xx\'
20     # select * from where email = \'xx\' # 无法命中索引
21 
22     #联合唯一索引,与上面的联合索引一样,就是多了一个列名组合唯一的限制
23     unique_together = (("driver", "restaurant"),)
24 
25     #admin中的配置
26     verbose_name = “name”  #在admin中会将name显示成names,多加一个“s”
27     verbose_name_plural=““name””  #在admin中会将name显示成name,显示原生自定义的名字
db_table、联合索引、联合唯一索引
 1     null                数据库中字段是否可以为空
 2     db_column           数据库中字段的列名
 3     db_tablespace
 4     default             数据库中字段的默认值
 5     primary_key         数据库中字段是否为主键
 6     db_index            数据库中字段是否可以建立索引
 7     unique              数据库中字段是否可以建立唯一索引
 8     unique_for_date     数据库中字段【日期】部分是否可以建立唯一索引
 9     unique_for_month    数据库中字段【月】部分是否可以建立唯一索引
10     unique_for_year     数据库中字段【年】部分是否可以建立唯一索引
11 
12     verbose_name        Admin中显示的字段名称
13     blank               Admin中是否允许用户输入为空
14     editable            Admin中是否可以编辑
15     help_text           Admin中该字段的提示信息
16     choices             Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
17                         如:gf = models.IntegerField(choices=[(0, \'何穗\'),(1, \'大表姐\'),],default=1) 想要在HTML中显示choice中的字段值,而不是数学索引,需要用到{{k.get_带choices参数的字段_display}}方法
18 
19     error_messages      自定义错误信息(字典类型),从而定制想要显示的错误信息;
20                         字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date
21                         如:{\'null\': "不能为空.", \'invalid\': \'格式错误\'}
22 
23     validators          自定义错误验证(列表类型),从而定制想要的验证规则
24                         from django.core.validators import RegexValidator
25                         from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\\
26                         MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator
27                         如:
28                             test = models.CharField(
29                                 max_length=32,
30                                 error_messages={
31                                     \'c1\': \'优先错信息1\',
32                                     \'c2\': \'优先错信息2\',
33                                     \'c3\': \'优先错信息3\',
34                                 },
35                                 validators=[
36                                     RegexValidator(regex=\'root_\\d+\', message=\'错误了\', code=\'c1\'),
37                                     RegexValidator(regex=\'root_112233\\d+\', message=\'又错误了\', code=\'c2\'),
38                                     EmailValidator(message=\'又错误了\', code=\'c3\'), ]
39                             )
models中的参数

1.2、在settings.py中注册app:

INSTALLED_APPS = [
    \'django.contrib.admin\',
    \'django.contrib.auth\',
    \'django.contrib.contenttypes\',
    \'django.contrib.sessions\',
    \'django.contrib.messages\',
    \'django.contrib.staticfiles\',
    \'app1\',
]

1.3、在控制台输出cmd 命令:

python3 manage.py  makemigrations #相当于在该app的migrations目录,记录下该app下modes.py所有表结构类型的改动(普通增删改查不记录)
python3 manage.py  migrate        #将刚刚对于表结构的改动作用至数据库

  

2、在MySQL中创建表

2.1、在上面步骤1.1 先写类、1.2 注册app的基础上,在与Django project中与project同名目录下的__init__.py文件中配置如下代码:

import pymysql
pymysql.install_as_MySQLdb()

注:# 由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替

2.2,在settings.py中更改数据库配置

#将原先数据库配置注释,使用mysql配置
# DATABASES = {
#     \'default\': {
#         \'ENGINE\': \'django.db.backends.sqlite3\',
#         \'NAME\': os.path.join(BASE_DIR, \'db.sqlite3\'),
#     }
# }



DATABASES = {
    \'default\': {
        \'ENGINE\': \'django.db.backends.mysql\',
        \'NAME\': \'test1\',       # 数据库名称
        \'USER\': \'root\',         # 用户名
        \'PASSWORD\': \'123456\',      # 密码
        \'HOST\': \'localhost\',             # ip
        \'PORT\': \'3306\',             # 端口
    }
}

2.3、执行命令

python3 manage.py  makemigrations
python3 manage.py  migrate  

注:配置好数据库为mysql后,重新启动Django工程,如果报错mysql django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.3 or newer is required;的话, 这是因为 mysql client 端的版本小于1.3.3。最简单的解决办法是:

#找到Django的安装路径的mysql配置下的base.py,如C:\\Python36\\Lib\\site-packages\\django\\db\\backends\\mysql\\base.py(根据实际安装路径)
#注释这句断言:
#if version < (1, 3, 3):
    #raise ImproperlyConfigured("mysqlclient 1.3.3 or newer is required; you have %s" % Database.__version__)

 

 

二、增删改查

 利用Django的ORM连接数据库进行增删改查和其他一些进阶操作。

1、增:

# 第一种方式
models.UserInfo.objects.create(username=\'root\', password=\'123\')
# 第二种方式
dic = {\'username\': \'root1\', \'password\': \'456\'}
models.UserInfo.objects.create(**dic)
#第三种方式
obj = models.UserInfo(username=\'root2\', password=\'789\')
obj.save()

2、删:

models.UserInfo.objects.filter(id="2").delete()

3、改:

models.UserInfo.objects.filter(id=1).update(password="111")

4、查:

models.User.objects.filter(id=1)             #id=1
models.User.objects.filter(id=1,name=\'root\') #id=1 and name = root
models.User.objects.filter(id__gt=1)         #id>1
models.User.objects.filter(id__lt=1)	     #id<1
models.User.objects.filter(id__gte=1)		 #id>=1
models.User.objects.filter(id__lte=1)		 #id<=1
models.Tb1.objects.filter(id__lt=10, id__gt=1)  #1<id<10 dic = {\'name\': \'xx\', \'age__gt\': 19} #**字典形式多条件查询 models.User.objects.filter(**dic) models.Business.objects.all() #QuerySet ,内部元素都是对象 [obj(id,caption,code),obj(id,caption,code),obj(id,caption,code) ] models.Business.objects.all().values(\'id\',\'caption\') # QuerySet ,内部元素都是字典 [{\'id\':1,\'code\': \'QA\'},{\'id\':2,\'code\': \'PM\'},...] models.Business.objects.all().values_list(\'id\',\'caption\') # QuerySet ,内部元素都是元组 [(1,"QA"),(2,"PM")] models.Business.objects.get(id=1) # 获取到的一个对象,如果不存在就报错 models.Business.objects.filter(id=1).first() # 获取到的一个对象,如果不存在返回NONE

5、更多进阶操作:

 1 # 获取个数
 2         #
 3         # models.Tb1.objects.filter(name=\'seven\').count()
 4 
 5         # in
 6         #
 7         # models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据
 8         # models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in
 9 
10         # isnull
11         # Entry.objects.filter(pub_date__isnull=True)
12 
13         # contains
14         #
15         # models.Tb1.objects.filter(name__contains="ven")
16         # models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
17         # models.Tb1.objects.exclude(name__icontains="ven")
18 
19         # range
20         #
21         # models.Tb1.objects.filter(id__range=[1, 2])   # 范围bettwen and
22 
23         # 其他类似
24         #
25         # startswith,istartswith, endswith, iendswith,
26 
27         # order by
28         #
29         # models.Tb1.objects.filter(name=\'seven\').order_by(\'id\')    # asc
30         # models.Tb1.objects.filter(name=\'seven\').order_by(\'-id\')   # desc
31 
32         # group by
33         #
34         # from django.db.models import Count, Min, Max, Sum
35         # models.Tb1.objects.filter(c1=1).values(\'id\').annotate(c=Count(\'num\'))
36         # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"
37 
38         # limit 、offset
39         #
40         # models.Tb1.objects.all()[10:20]
41 
42         # regex正则匹配,iregex 不区分大小写
43         #
44         # Entry.objects.get(title__regex=r\'^(An?|The) +\')
45         # Entry.objects.get(title__iregex=r\'^(an?|the) +\')
46 
47         # date
48         #
49         # Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))
50         # Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1))
51 
52         # year
53         #
54         # Entry.objects.filter(pub_date__year=2005)
55         # Entry.objects.filter(pub_date__year__gte=2005)
56 
57         # month
58         #
59         # Entry.objects.filter(pub_date__month=12)
60         # Entry.objects.filter(pub_date__month__gte=6)
61 
62         # day
63         #
64         # Entry.objects.filter(pub_date__day=3)
65         # Entry.objects.filter(pub_date__day__gte=3)
66 
67         # week_day
68         #
69         # Entry.objects.filter(pub_date__week_day=2)
70         # Entry.objects.filter(pub_date__week_day__gte=2)
71 
72         # hour
73         #
74         # Event.objects.filter(timestamp__hour=23)
75         # Event.objects.filter(time__hour=5)
76         # Event.objects.filter(timestamp__hour__gte=12)
77 
78         # minute
79         #
80         # Event.objects.filter(timestamp__minute=29)
81         # Event.objects.filter(time__minute=46)
82         # Event.objects.filter(timestamp__minute__gte=29)
83 
84         # second
85         #
86         # Event.objects.filter(timestamp__second=31)
87         # Event.objects.filter(time__second=2)
88         # Event.objects.filter(timestamp__second__gte=31)
进阶操作

注:all()、all().values()、all().values_list()示例:

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5

以上是关于Python中强大的通用ORM框架:SQLAlchemy的主要内容,如果未能解决你的问题,请参考以下文章

Python 开源项目大杂烩

SQLAlchemy-ORM

python-- Django ORM

python中orm 框架都有哪些

Python学习---django之ORM语法[对象关系映射]180124

EF框架