python-- Django ORM
Posted Wilson
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 - 小整数 -32768 ~ 32767 21 22 PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) 23 - 正小整数 0 ~ 32767 24 IntegerField(Field) 25 - 整数列(有符号的) -2147483648 ~ 2147483647 26 27 PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) 28 - 正整数 0 ~ 2147483647 29 30 BigIntegerField(IntegerField): 31 - 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807 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 - 二进制类型
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,显示原生自定义的名字
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 )
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-- Django ORM的主要内容,如果未能解决你的问题,请参考以下文章
Django:显示/记录来自 python shell 的 ORM sql 调用