django-orm
###数据库设定 Django默认使用的为sqlite
,因此在使用mysql或其余数据库的时候须要对其进行相关设定前端
####1.settings.pypython
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME':'dbname', 'USER': 'root', 'PASSWORD': 'xxx', 'HOST': '', 'PORT': '', } }
####2. project项目下的_init_.pymysql
因为Django默认使用MySQLdb,python3中无此模块,使用pymysql的话须要再次添加: import pymysql pymysql.install_as_MySQLdb()
####3. 注册 在settings中INSTALLED_APPS注册咱们的appsql
####4.app的models.py中建立表数据库
from django.db import models # Create your models here. class UserInfo(models.Model): # django会默认帮你建立一个自增id字段做为主键 username = models.CharField(max_length=32) password = models.CharField(max_length=64) email = models.EmailField()
####5. makemigrationsdjango
python manage.py makemigrations 建立更改的文件
####6.migratesession
python manage.py migrate 将生成的py文件应用到数据库
####7. 生成的表:app
+----------------------------+ | Tables_in_cmdb | +----------------------------+ | app_cmdb_userinfo | | auth_group | | auth_group_permissions | | auth_permission | | auth_user | | auth_user_groups | | auth_user_user_permissions | | django_admin_log | | django_content_type | | django_migrations | | django_session | +----------------------------+ mysql> desc app_cmdb_userinfo; +----------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------+--------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | username | varchar(32) | NO | | NULL | | | password | varchar(64) | NO | | NULL | | | email | varchar(254) | NO | | NULL | | +----------+--------------+------+-----+---------+----------------+
Django ORM操做相关
###1.添加数据函数
from app_cmdb import models # 有几个字段,传几个参数就好了 models.UserInfo.objects.create(username="leon", password="123123", email='4641231@qq.com') # 方法2 stu1 = user(username="leon", password="123123", email='4641231@qq.com') stu1.save() # flush到数据库中
###2.数据修改测试
# 单个数据的多个字段同时跟新 models.UserInfo.objects.get(username="leon", password="123123", email='4641231@qq.com').update(username="Leon",password="qweasdC") # 跟新某个字段 user_obj = models.UserInfo.objects.get(username="leon", password="123123") user_obj.username="Jack" user_obj.save() # 多条数据同时跟新 models.UserInfo.objects.all().update(username='Zhang')
###3.数据删除
# 删除表中全部数据 models.UserInfo.objects.all().delete() # 筛选单个删除 models.UserInfo.objects.get(username="leon").delete() # 过滤多个删除 models.UserInfo.objects.filter(username="leon").delete()
###4.数据查询 全部查询、过滤、排序、取值方法能够结合本身的使用场景来使用,以达到最佳的效果,下面是一些基础的查询操做,在文末会有更加详细的介绍
# 查询全部记录 models.UserInfo.objects.all() # 带字段名的全部记录,就是将全部记录以key-value的形式保存在字典中 models.UserInfo.objects.all().values() >>><QuerySet [{'id': 1, 'username': 'leon', 'password': '123123', 'email': '4641231@qq.com'}, {'id': 2, 'username': 'leon', 'password': '1123123', 'email': '4641231@qq.com'}]> # 查询单条记录,使用get查询单条数据,若是没有查到,会直接报错,结合try来使用 models.UserInfo.objects.get(name='Aaron') # 查询多条中的第一条记录,多个过滤条件,须要在filter中用逗号分隔开 models.UserInfo.objects.filter(username='leon', password="123123").first() # 模糊过滤,字段只要包含就能够 models.UserInfo.objects.filter(username__contains='leo').first() # 模糊-不区分大小写 models.UserInfo.objects.filter(username__icontains='leo').first() # 将字段内容排序后显示 models.UserInfo.objects.order_by('username') # 查询记录的个数 models.UserInfo.objects.filter().conut() # 筛选之大于小于,多个用逗号分开 models.UserInfo.objects.filter(id__gt=1) # 大于1 models.UserInfo.objects.filter(id__gte=1) # 大于等于1 models.UserInfo.objects.filter(id__lt=1) # 小于1 models.UserInfo.objects.filter(id__lte=1) # 小于等于1 models.UserInfo.objects.filter(id_gt=1,id__lte=10) # 大于1小于等于10 # in,not in models.UserInfo.objects.filter(id__in=[11, 22, 33]) # 获取id等于十一、2二、33的数据 models.UserInfo.objects.exclude(id__in=[11, 22, 33]) # not in # 排序值逆序 models.UserInfo.objects.order_by('-username') # 限制数据条数,由于返回的是一个QuerySet类型的列表,咱们可使用列表的分片来获取想要的数据内容,依然按照`顾首不顾尾`的原则 models.UserInfo.objects.filter(username="leon")[0] # 第一条数据 models.UserInfo.objects.filter(username="leon")[0:3] # 去前三条数据
###5.数据字段类型
- 几种主要的类型之-数字类型
1. AutoField int类型(1 to 2147483647)的自增id列,须加参数 primary_key=True 2. BigAutoField bigint类型(1 to 9223372036854775807),同上 3. BigIntegerField 4. IntegerField 5. FloatField 6. SmallIntegerField 7. PositiveIntegerField 8. PositiveSmallIntegerField
- 字符串类型
1. CharField 2. EmailField (admin) 3. GenericIPAddressField (admin) 4. URLField (admin) 5. UUIDField
- 时间类型
1. DateField (Python:datetime.date) 2. DateTimeField (Python: datetime.datetime ) 3. DecimalField (python : Decimal) 4. DurationField (python : timedelta) 5. TimeField (python : datetime.time)
- 二进制类型
1. BinaryField
- 布尔类型
1. BooleanField
- 文件类型
1. FileField
###6.参数
- 基本
- null 是否能够为空 - default 默认值 - primary_key 主键 - db_column 舍子数据库中的列名 - db_index 创建普通索引 - unique 惟一索引 - unique_for_data 只对时间作索引 - unique_for_month 只对月份作索引 - unique_for_year 只对年份作索引 - auto_now 添加仍是修改对象,时间为你添加或者修改的时间,须要使用obj.save()来跟新,而update不能跟新 - auto_now_add 建立时自动建立时间,跟新不动
- admin:
- choices 两个做用 user_type_choices = ( # 将这些字段放进内存,而避免数据库连表操做 (1,'root'), (2,'root1'), (3,'root1') ) 并且在django-admin中能够经过select直接选择 user_type_id = models.IntegerField(choices=user_type_choices,default=1) - blank admin中是否能够为空 - verbose_name="用户名" 前端显示的别名 - editable 是否能够被编辑 - error_messages 输入错误提示消息自定义 error_messages={'required':u'邮箱不能为空'}???? - help_text help_text="user_name" 输入框下的用户提示信息 - validators Django的form自定义验证机制设置
###7.外键的连表操做 表结构
class Host(models.Model): nid = models.AutoField(primary_key=True) hostname = models.CharField(max_length=32, db_index=True) ip = models.GenericIPAddressField(db_index=True, protocol='ipv4') port = models.IntegerField() b = models.ForeignKey(to='Business', to_field='id') def __str__(self): # 定制输出对象的时候,自动输出name字段 return self.name class Business(models.Model): caption = models.CharField(max_length=32) code = models.CharField(max_length=32)
测试数据
####1.单表相关
- 查询
# QuerySet内部为对象,模板获取的时候用"."来获取 v1 = models.Business.objects.all() # QuerySet内部为key、value的字典,由于是字典,在模板中获取的时候用"."来获取, v2 = models.Business.objects.all().values('id', 'caption') #只获取特定字段 # QuerySet内部为元组,由于是元组,在模板中获取的时候使用0,1,2的index来获取 v3 = models.Business.objects.all().values_list('id', 'caption')
class Host(models.Model): class Meta: # django建立表的时候未指定此字段,则默认为app名称_类名小写 db_table = "host" # 数据库中生成的表名称 # 多字段联合索引,注意mysql联合索引的最左前缀原则!!! index_together = [ ("hostname", "ip"), ] # 多字段联合惟一索引 unique_together = (("hostname", "ip"),) # admin中一种易于理解展现形式,默认展现为类名,设定此字段后显示为该字段加's' verbose_name='主机' # 同上,可是不会加上's' verbose_name_plural='主机' ......待补充~
verbose_name
结果
verbose_name_plural
结果
####2. 一对多ForeignKey
1) 数据查询
- 正向数据查询
# QuerySet内部为对象 v1 = models.Host.objects.filter(nid__gt=0) # QuerySet内部为key、value的字典,由于是字典 v2 = models.Host.objects.all().values('nid', 'hostname', 'b_id', 'b__caption', 'b__code') # QuerySet内部为元组,由于是元组 v2 = models.Host.objects.all().values_list('nid', 'hostname', 'b_id', 'b__caption', 'b__code') # 经过host字段查business v = models.Host.objects.filter(id=1).all() v[0].b.caption 或 v[0].b.code
- 数据反向查询,从Business查询Host
# QuerySet对象 v = models.Business.objects.filter(id=1).all() # 这样就能够获取全部绑定business.id=1的全部Host的对象 v[0].host_set.all() # 获取对应的值 v[0].b.caption 或 v[0].b.code # QuerySet字典 models.Business.objects.all().values('caption','host__hostname') # QuerySet元组 models.Business.objects.all().values_list('caption','host__hostname')
2) 可用的字段以及参数
-
to
要进行关联的表名 -
to_field
要关联的表中的字段名称 -
db_constraint=True
是否在数据库中建立外键约束。例如,默认django在建立host数据的时候对他的b_id
字段没有约束性,只是在建立sql语句的时候对sql语句进行了约束。当你设定该字段为False的时候,django支持你的b_id不建立与business表的约束条件,你能够随意设定该值 -
on_delete
:外键指向的对象删除时,本对象应该采起的措施,默认级联删除CASCADE。假如删除business
表中的一条数据,在新版本的django中也会把与其关联的host
表中的数据也删除,可是在mysql中使用delete
语句是会引起异常的。on_delete
定制当删除关联表中的数据时,定制当前表与其关联的行的行为官方文档:
- models.CASCADE,删除外键对象(Business)数据,与之关联的全部数据也彻底删除(默认行为) - models.DO_NOTHING,删除外键对象(Business)数据,不删除被关联(Host)的数据,引起db层错误IntegrityError - models.PROTECT,删除外键对象(Business)数据,不删除被关联(Host)的数据,引起django层错误ProtectedError - models.SET_NULL,删除外键对象(Business)数据,与之关联的(Host)对应字段值设置为null,且前提外键字段须要设置为可为空 - models.SET_DEFAULT,删除外键对象(Business)数据,与之关联的(Host)对应字段值设置为默认值,前提外键字段须要设置默认值 - models.SET,删除外键对象(Business)数据, a. 与之关联的(Host)对应字段值设置为指定值,设置:models.SET(值) b. 与之关联的(Host)对应字段值设置为可执行对象的返回值,设置:models.SET(可执行对象)
on_delete
中的models.SET
举例:
# 咱们能够在func函数中自定制返回结果,这样开发起来就会有更多选择,能够对数据判断等等~ def func1(): return 10 class MyModel(models.Model): user =models.ForeignKey(to="User",to_field="id"on_delete=models.SET(func1),)
related_name='connFK'
上面反向操做时,使用的是表名,用于代替表名_set
成为obj.connFK.all()
,例如:
v = models.Business.objects.filter(id=1).all() v[0].connFK.all()
related_query_name='host_table'
反向操做时,原来使用的是表名,此字段只是用来替换表名,例如:
models.Business.objects.all().values_list('caption','host__hostname') # 变为 models.Business.objects.all().values_list('caption','host_table__hostname')
limit_choices_to=None
显示关联数据时,提供的筛选条件:
limit_choices_to={'id__gt': 1} limit_choices_to=lambda : {'id__gt': 1}
- swappable??
####2. 一对一:OneToOneField
Stack Overflow热帖,这个问答讲解的其实特别的好,分享一下~
表结构,一个汽车只能够对应一个引擎,一个引擎也只能对应一个汽车
class Engine(models.Model): name = models.CharField(max_length=25) def __unicode__(self): return self.name class Car(models.Model): name = models.CharField(max_length=25) engine = models.OneToOneField(Engine) def __unicode__(self): return self.name
其实OneToOneField
其实能够理解为 ForeignKey
加上 unique=True
的另外一种展示形式,可是外键不加unique=True
的约束的时候,反向查询返回的是一个QuerSet列表,而OneToOneField
反向查询只返回一个QuerSet对象,由于他是一对一的
class Engine2(models.Model): name = models.CharField(max_length=25) def __unicode__(self): return self.name class Car2(models.Model): name = models.CharField(max_length=25) engine = models.ForeignKey(Engine2, unique=True) def __unicode__(self): return self.name
parent_link=False
??待研究
####3. 多对多:ManyToManyField
官方文档
表结构,一个做者能够出版不少本书,一本书有不少个做者
class Author(models.Model): name = models.CharField(max_length=64) age = models.IntegerField() def __unicode__(self): return self.name class Book(models.Model): book_name = models.CharField(max_length=128) pub_date = models.DateField() book_to_author = models.ManyToManyField('Author') def __unicode__(self): return self.book_name
这样就会生成三张表,一个做者表,一个书表,还有一个Django自动生成的第三张表,存放做者与书之间的关系表:
在Django中,多对多关系中的第三张表,咱们可让Django自动建立,也能够选择本身建立第三张表,当本身建立的时候,又有两种状况:
-
有
ManyToManyField
字段, 当存在这个字段的时候,Django支持咱们对数据的查询、清除操做可使用这个字段,可是其余操做是不可使用这个字段的: -
没有
ManyToManyField
字段,当没有这个字段的时候,第三张表中就是所有是ForiegnKey
,而咱们对数据的操做就只能经过这个第三张表来操做:
1)数据查询
# 经过book_to_author字段来正向查询 v = models.Book.objects.filter(id=1).first() print(v.book_to_author.all()) >>>> <QuerySet [<Author: Author object>, <Author: Author object>]> # 反向查询 v1 = models.Author.objects.filter(id=1).first().book_set.all() v2 = models.Author.objects.filter(id=1).values('name','book__book_name') v3 = models.Author.objects.filter(id=1).values_list('name','book__book_name')
2)其余操做
v = models.Book.objects.filter(id=1).first() v.book_to_author.remove # 能够删除某一条对应关系 v.book_to_author.add # 添加一条关系 v.book_to_author.set # 直接设定,会覆盖原值 v.book_to_author.clear # 清除v对象的全部与之联系
3)参数以及字段
-
to
同ForeignKey中解释,指定须要关联的表名 -
db_table
设定表名,再也不使用Django默认建立的表名 -
related_name
同ForeignKey中解释 -
related_query_name
同ForeignKey中解释 -
limit_choices_to
同ForeignKey中解释 -
db_constraint
同ForeignKey中解释 -
through
当第三张表是本身建立的的时候,此字段用于指定第三张关系表。若是不指定,且还有ManyToManyField
字段的时候,Django会在数据库中多建立第四张表(本身建立和自动建立都会存在)。使用该字段来定制关系表,就不会建立你本身的那张表 -
through_fields
Django默认建立第三张关系表的时候,这个关系表只有三个字段,当第三张表是本身建立的时候,不能规定你的第三张表中的有多少列数据,可是能够经过该字段传入一个多字段的列表来指定那些字段作多对多关系 -
swappable
-
symmetrical