python数据模型搭建_python之路(19)django数据库模型(model)

前言

object relation mapping(ORM)关系对象映射表,一个类实例映射为一条表记录

目录

数据库配置

1.django 默认使用sqlite的数据库,如果需要使用mysql数据库,就需要在settings中修改配置信息

DATABASES ={'default': {'ENGINE': 'django.db.backends.mysql','NAME' : '', #你的数据库的名字

'USER' : '', #你的数据库用户

'PASSWORD' : '', #你的数据库密码

'HOST' : '', #你的数据库主机,默认localhost

'PORT' : '3306', #你的数据库端口

}

}

mysql数据库配置信息

2.需要手动导入PyMySQL,在_init_.py中导入

import MySQLdb

#注:如果想要显示表执行的sql语句,就在settings中配置

LOGGING={'version': 1,'disable_existing_loggers': False,'handlers': {'console':{'level':'DEBUG','class':'logging.StreamHandler',

},

},'loggers': {'django.db.backends': {'handlers': ['console'],'propagate': True,'level':'DEBUG',

},

}

}

创建类

1. 在models.py中创建类映射表

from django.db importmodels#Create your models here.

classBook(models.Model):

name=models.CharField(max_length=20)

price=models.FloatField()

pub_date=models.DateField()

publish= models.ForeignKey("Publish", on_delete=models.CASCADE) #一对多

authors = models.ManyToManyField("Author") #多对多

def __str__(self):returnself.nameclassPublish(models.Model):

name=models.CharField(max_length=32)

city=models.CharField(max_length=32)def __str__(self):returnself.nameclassAuthor(models.Model):

name= models.CharField(max_length=32)

age= models.IntegerField(default=20)def __str__(self):return self.name

2.在终端中输入 python manage.py makemigrations , python manage.py migrate 两条命令

类属性进阶操作

classUserInfo(models.Model):

age=CharFiled(是否为空,类型,长度,列名,索引,错误提示,自定义验证规则)

...

...

字段参数

null 数据库中字段是否可以为空

db_column 数据库中字段的列名

default 数据库中字段的默认值

primary_key 数据库中字段是否为主键

db_index 数据库中字段是否可以建立索引

unique 数据库中字段是否可以建立唯一索引(用于一对一)

unique_for_date 数据库中字段【日期】部分是否可以建立唯一索引

unique_for_month 数据库中字段【月】部分是否可以建立唯一索引

unique_for_year 数据库中字段【年】部分是否可以建立唯一索引

verbose_name Admin中显示的字段名称

blank Admin中是否允许用户输入为空

editable Admin中是否可以编辑

help_text Admin中该字段的提示信息

choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作

如:gf= models.IntegerField(choices=[(0, 'chen'),(1, 'xiaoyi'),],default=1)

error_messages 自定义错误信息

字典健:null, blank, invalid, invalid_choice, unique,andunique_for_date

如:{'null': "不能为空.", 'invalid': '格式错误'}

单表操作

-----------增#单表

#添加方法一

b = Book(name="python基础",price=99,author="chen",pub_date="2017-12-12")

b.save()#添加方法二

Book.objects.create(name="PHP基础",price=70,author="chen",pub_date="2016-12-12")-----------删#单表

Book.objects.filter(author="liu").delete()-----------改#单表

Book.objects.filter(author="chen").update(price=100)-----------查#单表

book_list =Book.objects.all()print(book_list[0])

book_list= Book.objects.all()[::-2]

book_list= Book.objects.all()[::2]

book_list=Book.objects.first()

book_list=Book.objects.last()

book_list= Book.objects.get(id=4) #只能取出一条记录的时候不报错

ret = Book.objects.filter(author="chen").values("name","price") #以字典的形式显示

ret = Book.objects.filter(author="chen").values_list("name","price") #以元组的形式显示

book_list = Book.objects.exclude(author="chen").values("name","price") #除了chen以外的人的数据

book_list = Book.objects.all().values("name").distinct() #根据一个字段去重

ret = Book.objects.all().values("name").distinct().count() #根据一个字段去重

Book.objects.filter(authors__id__in=[1,2]) #获取id等于1或2的数据

Book.objects.filter(authors__id__range=[1,2]) #范围

#万能的__

#价格大于50的数/85.41

book_list = Book.objects.filter(price__gt=50).values("name","price")#模糊查询

book_list = Book.objects.filter(name__icontains="P").values("name","price")

一对多(外键)

外键关系及参数

ForeignKey(ForeignObject)

to, 要进行关联的表名

to_field=None, 要关联的表中的字段名称

on_delete=None, 当删除关联表中的数据时,当前表与其关联的行的行为-models.CASCADE,删除关联数据,与之关联也删除(常用)-models.DO_NOTHING,删除关联数据,引发错误IntegrityError-models.PROTECT,删除关联数据,引发错误ProtectedError-models.SET_NULL,删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)-models.SET_DEFAULT,删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)

related_name=None, 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()

related_query_name=None, 反向操作时,使用的连接前缀,用于替换【表名】 如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')

limit_choices_to=None, 在Admin或ModelForm中显示关联数据时,提供的条件:

如:- limit_choices_to={'nid__gt': 5}- limit_choices_to=lambda : {'nid__gt': 5}

db_constraint=True 是否在数据库中创建外键约束

parent_link=False 在Admin中是否显示关联数据

书籍和出版社是一对多的关系

classBook(models.Model):

name=models.CharField(max_length=20)

price=models.FloatField()

pub_date=models.DateField()

publish= models.ForeignKey("Publish", on_delete=models.CASCADE) #一对多

def __str__(self):returnself.nameclassPublish(models.Model):

name=models.CharField(max_length=32)

city=models.CharField(max_length=32)def __str__(self):return self.name

添加数据的方法

#多表添加

Book.objects.create(name="linux运维",price=77,pub_date="2017-12-12",publish_id=2)

Book.objects.create(name="GO",price=23,pub_date="2017-05-12",publish=publish_obj)

多表查询的方法

#含外键:一对多查询

#查询人民出版社出过的所有书籍名字和价格

#方式一:

pub_obj=Publish.objects.filter(name="人民出版社")[0]

ret=Book.objects.filter(publish=pub_obj).values("name","price")#方式二

pub_obj = Publish.objects.filter(name="人民出版社")[0]print(pub_obj.book_set.all().values("name","price")) #book_set

print(type(pub_obj.book_set.all()))#方式三,用__

ret=Book.objects.filter(publish__name="人民出版社").values("name","price")#python基础书出版社的名字

#法一

ret = Publish.objects.filter(book__name="Python基础").values("name")#法二

ret3=Book.objects.filter(name="python基础").values("publish__name")#北京出版出版的所有的书

ret = Book.objects.filter(publish__city="北京").values("name")

ret= Publish.objects.filter(city="北京")

一对一(外键+unique)

classBook(models.Model):

name=models.CharField(max_length=20)

price=models.FloatField()

pub_date=models.DateField()

publish=models.ForeignKey(

to= "Publish",

on_delete=models.CASCADE,

unique=True,

)#一对一

def __str__(self):returnself.nameclassPublish(models.Model):

name=models.CharField(max_length=32)

city=models.CharField(max_length=32)def __str__(self):return self.name

多对多(关系表)

多对多关系及参数

ManyToManyField(RelatedField)

to, 要进行关联的表名

related_name=None, 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()

related_query_name=None, 反向操作时,使用的连接前缀,用于替换【表名】 如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')

limit_choices_to=None, 在Admin或ModelForm中显示关联数据时,提供的条件:

如:- limit_choices_to={'nid__gt': 5}- limit_choices_to=lambda : {'nid__gt': 5}

symmetrical=None, 仅用于多对多自关联时,symmetrical用于指定内部是否创建反向操作的字段#可选字段有:code, id, m1

classBB(models.Model):

code= models.CharField(max_length=12)

m1= models.ManyToManyField('self',symmetrical=True)#可选字段有: bb, code, id, m1

classBB(models.Model):

code= models.CharField(max_length=12)

m1= models.ManyToManyField('self',symmetrical=False)

through=None, 自定义第三张表时,使用字段用于指定关系表

through_fields=None, 自定义第三张表时,使用字段用于指定关系表中那些字段做多对多关系表from django.db importmodelsclassPerson(models.Model):

name= models.CharField(max_length=50)classGroup(models.Model):

name= models.CharField(max_length=128)

members=models.ManyToManyField(

Person,

through='Membership',

through_fields=('group', 'person'),

)classMembership(models.Model):

group= models.ForeignKey(Group, on_delete=models.CASCADE)

person= models.ForeignKey(Person, on_delete=models.CASCADE)

inviter=models.ForeignKey(

Person,

on_delete=models.CASCADE,

related_name="membership_invites",

)

invite_reason= models.CharField(max_length=64)

db_constraint=True, 是否在数据库中创建外键约束

db_table= None, 默认创建第三张表时,数据库中表的名称

书籍和作者是多对多的关系

注:使用authors = models.ManyToManyField("Author"),会自动创建book_authors表,也可以自己创建关系表(不会有authors属性)classBook(models.Model):

name=models.CharField(max_length=20)

price=models.FloatField()

pub_date=models.DateField()

authors= models.ManyToManyField("Author") #多对多

def __str__(self):returnself.nameclassAuthor(models.Model):

name= models.CharField(max_length=32)

age= models.IntegerField(default=20)def __str__(self):return self.name

-----------增#绑定多表关系

book_obj = Book.objects.get(id=4)

authors_objs= Author.objects.get(id=2) #authors_objs = Author.objects.all()

book_obj.authors.add(authors_objs)-----------查#多对多的关系,第三张表关系表

#通过对象的方式绑定关系

#书找作者

book_obj=Book.objects.get(id=3)print(book_obj.authors.all())#作者找书

author_obj = Author.objects.get(id=2)print(author_obj.book_set.all())return HttpResponse("添加成功")-----------删#解除多表关系

book_obj = Book.objects.get(id=4)

authors_objs= Author.objects.all() #是列表

book_obj.authors.remove(*authors_objs)

book_obj.authors.remove(2) #删除的是数量

#清空

book_obj.authors.clear()-----------改#修改的set()方法

book_obj = Book.objects.get(id=4)

book_obj.authors.set([2,3])

手动创建的多表关系

#手动创建关系表

classBook(models.Model):

name=models.CharField(max_length=20)

price=models.FloatField()

pub_date=models.DateField()def __str__(self):returnself.nameclassBook_Author(models.Model):

book=models.ForeignKey("Book",on_delete=models.CASCADE)

author=models.ForeignKey("Author",on_delete=models.CASCADE)classAuthor(models.Model):

name= models.CharField(max_length=32)

age= models.IntegerField(default=20)def __str__(self):return self.name

-----------增#手动创建的关系表

Book_Author.objects.create(book_id=2,author_id=3)-----------查#关联查询,查找书的所有作者

obj = Book.objects.get(id=2)print(obj.book_author_set.all()[0].author)#chen出过的书和价格

ret = Book.objects.filter(book_author__author__name="chen").values("name","price")

手动创建的表因为没有第三张的字段,因此没有自动创建的表查询的方便,而自动创建的表默认只有三个字段

因此引入   手动+自动联合创建表

classUser(models.Model):

username= models.CharField(max_length=32,db_index=True)def __str__(self):returnself.usernameclassTag(models.Model):

title= models.CharField(max_length=16)

m=models.ManyToManyField(

to='User',

through='UserToTag',

through_fields=['u','t']

)def __str__(self):returnself.title#使用ManyToManyField只能在第三张表中创建三列数据

classUserToTag(models.Model):#nid = models.AutoField(primary_key=True)

u = models.ForeignKey(to='User')

t= models.ForeignKey(to='Tag')

ctime=models.DateField()#用于关系表u,t两个字段共同约束唯一

classMeta:

unique_together=[

('u','t'),

]

自关联

用户粉丝互相关注(在同一张用户表里,用户互相关联)

classUser(models.Model):

username= models.CharField(max_length=32,db_index=True)

d= models.ManyToManyField('User',related_name='b')def __str__(self):return self.username

注:自关联的跨表查询

symmetrical=None, 仅用于多对多自关联时,symmetrical用于指定内部是否创建反向操作的字段#可选字段有:code, id, m1

classBB(models.Model):

code= models.CharField(max_length=12)

m1= models.ManyToManyField('self',symmetrical=True)#可选字段有: bb, code, id, m1

classBB(models.Model):

code= models.CharField(max_length=12)

m1= models.ManyToManyField('self',symmetrical=False)

聚合函数,Q函数,F函数

先导入模块

from django.db.models importMin,Avg,Max,Sumfrom django.db.models import F,Q

#聚合函数(需要先导入函数)

ret = Book.objects.all().aggregate(Avg("price"))

ret= Book.objects.all().aggregate(chen_money = Sum("price")) #取别名

#查各个作者的书的价格总和

value:按照作者名字分组

ret= Book.objects.values("authors__name").annotate(Sum("price"))print(ret)#查各个出版社出的书的最小

ret = Publish.objects.values("name").annotate(Min("book__price"))print(ret)#-----------------------------------------------------------------------------------------------------------------------------

#F查询和Q查询,(使用前要导入模块)#F拿到的值

Book.objects.all().update(price=F("price")+10)#Q可以做or操作 ,~Q表示非

re = Book.objects.filter(Q(price=80) | Q(name="GO"))#组合查询

re = Book.objects.filter(Q(name__contains="G"))#Q查询和关键字查询组合,Q要在前面

re = Book.objects.filter(Q(name="GO"),price=80)

惰性取值,迭代对象,exists()函数

#只有在使用ret使用的时候才去查询,惰性取值

re = Book.objects.filter(price=80) #不会取值

for i in re: #使用时才会去查询

print(i)print(re)#---------------------------------------------------------------------

#exists()

re = Book.objects.filter(price=80)

re.exists()#会查询,但re不会被赋值,只有使用re变量的时候才会被赋值

#----------------------------------------------------------------------

#iterator() 迭代器对象

ret = Book.objects.filter(price=80)

ret= ret.iterator()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值