Django model 介绍
提前准备并运行项目 步骤
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
cd s55djano_model_form_sessoin_cookie_中间件/ django-admin startproject my_django cd my_django/ cd my_django/ python3 manage.py startapp app01
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
my_django/__init__.py python3 是pymysql 没有MySQLDB 配置 import pymysql pymysql.install_as_MySQLdb() setting内instaldb 配置app01名字 urls from app01 import views url(r'^index/$', views.index), models class UserType(models.Model): nid=models.AutoField(primary_key=True) #自增 主键 caption=models.CharField(max_length=16) #必须给长度 class UserInfo(models.Model): username = models.CharField(max_length=32) email=models.EmailField(max_length=32) pwd = models.CharField(max_length=32) user_type=models.ForeignKey("UserType") # 不加引号,这个类必须提前创建 加了引号 上面的类也可以放在下面 setting内instaldb 配置app01名字 settings配置连接mysql DATABASES = { "default":{ "ENGINE":'django.db.backends.mysql', "NAME":"django_s55", 'USER': 'root', 'PASSWORD': '123456', 'HOST': '', 'PORT': '', } } mysql> create database django_s55 default character set utf8 collate utf8_bin; Query OK, 1 row affected (0.01 sec) 生成表 python3 manage.py makemigrations python3 manage.py migrate views from django.shortcuts import HttpResponse from app01.models import * # 应用数据库需要导入 添加数据 #1 obj = UserType(caption="管理员") obj.save() #1 UserType.objects.create(caption="普通管理员") #1 user_dict={"caption":"超级管理员"} UserType.objects.create(**user_dict) #2 一对多插入 user_dict = { "username":"alex", 'email':'alex@qq.com', 'pwd':123, 'user_type':UserType.objects.get(nid=1), #这里是类名 val是对象 } UserInfo.objects.create(**user_dict) #2 制定数据库字段 user_dict = { "username":"erice", 'email':'erice@qq.com', 'pwd':123, 'user_type_id':1, #这里是数据库字段名 } UserInfo.objects.create(**user_dict) 启动项目 python manage.py runserver 127.0.0.1:8001
一 model 介绍
到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞:
- 创建数据库,设计表结构和字段
- 使用 MySQLdb 来连接数据库,并编写数据访问层代码
- 业务逻辑层去调用数据访问层执行数据库操作
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import MySQLdb def GetList(sql): db = MySQLdb.connect(user='root', db='wupeiqidb', passwd='1234', host='localhost') cursor = db.cursor() cursor.execute(sql) data = cursor.fetchall() db.close() return data def GetSingle(sql): db = MySQLdb.connect(user='root', db='wupeiqidb', passwd='1234', host='localhost') cursor = db.cursor() cursor.execute(sql) data = cursor.fetchone() db.close() return dataimport MySQLdb def GetList(sql): db = MySQLdb.connect(user='root', db='wupeiqidb', passwd='1234', host='localhost') cursor = db.cursor() cursor.execute(sql) data = cursor.fetchall() db.close() return data def GetSingle(sql): db = MySQLdb.connect(user='root', db='wupeiqidb', passwd='1234', host='localhost') cursor = db.cursor() cursor.execute(sql) data = cursor.fetchone() db.close() return data
django为使用一种新的方式,即:关系对象映射(Object Relational Mapping,简称ORM)。
PHP:activerecord
Java:Hibernate
C#:Entity Framework
django中遵循 Code Frist 的原则,即:根据代码中定义的类来自动生成数据库表。
1、创建Model,之后可以根据Model来创建数据库表
from django.db import models class userinfo(models.Model): name = models.CharField(max_length=30) email = models.EmailField() memo = models.TextField()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1、models.AutoField 自增列 = int(11) 如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。 2、models.CharField 字符串字段 必须 max_length 参数 3、models.BooleanField 布尔类型=tinyint(1) 不能为空,Blank=True 4、models.ComaSeparatedIntegerField 用逗号分割的数字=varchar 继承CharField,所以必须 max_lenght 参数 5、models.DateField 日期类型 date 对于参数,auto_now = True 则每次更新都会更新这个时间;auto_now_add 则只是第一次创建添加,之后的更新不再改变。 6、models.DateTimeField 日期类型 datetime 同DateField的参数 7、models.Decimal 十进制小数类型 = decimal 必须指定整数位max_digits和小数位decimal_places 8、models.EmailField 字符串类型(正则表达式邮箱) =varchar 对字符串进行正则表达式 9、models.FloatField 浮点类型 = double 10、models.IntegerField 整形 11、models.BigIntegerField 长整形 integer_field_ranges = { 'SmallIntegerField': (-32768, 32767), 'IntegerField': (-2147483648, 2147483647), 'BigIntegerField': (-9223372036854775808, 9223372036854775807), 'PositiveSmallIntegerField': (0, 32767), 'PositiveIntegerField': (0, 2147483647), } 12、models.IPAddressField 字符串类型(ip4正则表达式) 13、models.GenericIPAddressField 字符串类型(ip4和ip6是可选的) 参数protocol可以是:both、ipv4、ipv6 验证时,会根据设置报错 14、models.NullBooleanField 允许为空的布尔类型 15、models.PositiveIntegerFiel 正Integer 16、models.PositiveSmallIntegerField 正smallInteger 17、models.SlugField 减号、下划线、字母、数字 18、models.SmallIntegerField 数字 数据库中的字段有:tinyint、smallint、int、bigint 19、models.TextField 字符串=longtext 20、models.TimeField 时间 HH:MM[:ss[.uuuuuu]] 21、models.URLField 字符串,地址正则表达式 22、models.BinaryField 二进制 23、models.ImageField 图片 24、models.FilePathField 文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1、null=True 数据库中字段是否可以为空 2、blank=True django的 Admin 中添加数据时是否可允许空值 3、primary_key = False 主键,对AutoField设置主键后,就会代替原来的自增 id 列 4、auto_now 和 auto_now_add auto_now 自动创建---无论添加或修改,都是当前操作的时间 auto_now_add 自动创建---永远是创建时的时间 5、choices GENDER_CHOICE = ( (u'M', u'Male'), (u'F', u'Female'), ) gender = models.CharField(max_length=2,choices = GENDER_CHOICE) 6、max_length 7、default 默认值 8、verbose_name Admin中字段的显示名称 9、name|db_column 数据库中的字段名称 10、unique=True 不允许重复 11、db_index = True 数据库索引 12、editable=True 在Admin里是否可编辑 13、error_messages=None 错误提示 14、auto_created=False 自动创建 15、help_text 在Admin中提示帮助信息 16、validators=[] 17、upload-to
参数:symmetrical=False
symmetrical=False #默认是不互相关联, 比如微博关注:alex 关注了jack 那么坐成多对多关系,这个参数如果是true则jack也会默认关注alex,如果是false则不关注。担心关系而已 但是1.9.10版本的django有点问题。大家自行测试
follow_list = models.ManyToManyField('self',blank=True,related_name="my_followers",symmetrical=False)
连表关系 related_name
class Comment(models.Model): '''评论''' to_weibo = models.ForeignKey(Weibo) p_comment = models.ForeignKey('self',related_name="child_comments") user = models.ForeignKey('UserProfile') comment_type_choices = ((0,'comment'),(1,'thumb_up')) comment_type = models.IntegerField(choices=comment_type_choices,default=0) comment = models.CharField(max_length=140) date = models.DateTimeField(auto_created=True) def __str__(self): return self.comment 大家看上面的model数据表类。 对于p_comment这个字段,是关联了自身的表的自身字段做的外键, 而对于正向查找则是 外键字段__外键表字段 而反向查找 则是字典表对象.外键表_set.all()但是这个表示自身呢??我们用这个related_name值代替外键表 字典表对象.related_name_set.select_related()
2、连表关系:
- 一对多,models.ForeignKey(ColorDic)
- 一对一,models.OneToOneField(OneModel)
- 多对多,authors = models.ManyToManyField(Author)
应用场景: 一对一:在某表中创建一行数据时,有一个单选的下拉框(下拉框中的内容被用过一次就消失了)。 例如:原有含10列数据的一张表保存相关信息,经过一段时间之后,10列无法满足需求,需要为原来的表再添加5列数据。 一对多:当一张表中创建一行数据时,有一个单选的下拉框(可以被重复选择)。 例如:创建用户信息时候,需要选择一个用户类型【普通用户】【金牌用户】【铂金用户】等。 多对多:在某表中创建一行数据是,有一个可以多选的下拉框。 例如:创建用户信息,需要为用户指定多个爱好。
3、数据库操作
- 增加:创建实例,并调用save
- 更新:a.获取实例,再sava;b.update(指定列)
- 删除:a. filter().delete(); b.all().delete()
- 获取:a. 单个=get(id=1) ;b. 所有 = all()
- 过滤:filter(name='xxx');filter(name__contains='');(id__in = [1,2,3]) ; filter().frirst 获取对象
- icontains(大小写无关的LIKE),startswith和endswith, 还有range(SQLBETWEEN查询)'gt', 'in', 'isnull', 'endswith', 'contains', 'lt', 'startswith', 'iendswith', 'icontains','range', 'istartswith'
- 排序:order_by("name") =asc ;order_by("-name")=desc
- 返回第n-m条:第n条[0];前两条[0:2]
- 指定映射:values
- 数量:count()
- 聚合:from django.db.models import Min,Max,Sum objects.all().aggregate(Max('guest_id'))
- 原始SQL
cursor = connection.cursor() cursor.execute('''SELECT DISTINCT first_name ROM people_person WHERE last_name = %s""", ['Lennon']) row = cursor.fetchone()
上传文件实例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class FileForm(forms.Form): ExcelFile = forms.FileField()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.db import models class UploadFile(models.Model): userid = models.CharField(max_length = 30) file = models.FileField(upload_to = './upload/') date = models.DateTimeField(auto_now_add=True)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def UploadFile(request): uf = AssetForm.FileForm(request.POST,request.FILES) if uf.is_valid(): upload = models.UploadFile() upload.userid = 1 upload.file = uf.cleaned_data['ExcelFile'] upload.save() print upload.file
二 django model 进阶篇
2.1 操作表
1、基本操作 增 删 改 查
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 增 # # models.Tb1.objects.create(c1='xx', c2='oo') 增加一条数据,可以接受字典类型数据 **kwargs # obj = models.Tb1(c1='xx', c2='oo') # obj.save() # 查 # # models.Tb1.objects.get(id=123) # 获取单条数据,不存在则报错(不建议) # models.Tb1.objects.all() # 获取全部 # models.Tb1.objects.filter(name='seven') # 获取指定条件的数据 # 删 # # models.Tb1.objects.filter(name='seven').delete() # 删除指定条件的数据 # 改 # models.Tb1.objects.filter(name='seven').update(gender='0') # 将指定条件的数据更新,均支持 **kwargs # obj = models.Tb1.objects.get(id=1) # obj.c1 = '111' # obj.save() # 修改单条数据
2、进阶操作(了不起的双下划线 __就是join意思 )
利用双下划线将字段和对应的操作连接起来
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 获取个数 # # models.Tb1.objects.filter(name='seven').count() # 大于,小于 # # models.Tb1.objects.filter(id__gt=1) # 获取id大于1的值 # models.Tb1.objects.filter(id__lt=10) # 获取id小于10的值 # models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值 # in # # models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据 # models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in # contains # # models.Tb1.objects.filter(name__contains="ven") # models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感 # models.Tb1.objects.exclude(name__icontains="ven") # range # # models.Tb1.objects.filter(id__range=[1, 2]) # 范围bettwen and # 其他类似 # # startswith,istartswith, endswith, iendswith, # order by # # models.Tb1.objects.filter(name='seven').order_by('id') # asc # models.Tb1.objects.filter(name='seven').order_by('-id') # desc # limit 、offset # # models.Tb1.objects.all()[10:20] # group by from django.db.models import Count, Min, Max, Sum # models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num')) # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id" 进阶操作
例子:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.db import models # Create your models here. class UserType(models.Model): nid=models.AutoField(primary_key=True) #自增 主键 caption=models.CharField(max_length=16) #必须给长度 class UserInfo(models.Model): username = models.CharField(max_length=32) email=models.EmailField(max_length=32) pwd = models.CharField(max_length=32) user_type=models.ForeignKey("UserType") # 不加引号,这个类必须提前创建 加了引号 上面的类也可以放在下面 # 原始创建多对多 ''' class HostToGroup(models.Model): hgid =models.AutoField(primary_key=True) hid = models.ForeignKey('Host') gid = models.ForeignKey("Group") class Host(models.Model): hid = models.AutoField(primary_key=True) hostname = models.CharField(max_length=32) ip = models.CharField(max_length=17) class Group(models.Model): gid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) ''' # django 创建 # python3 manage.py makemigrations # python3 manage.py migrate class Host(models.Model): hid = models.AutoField(primary_key=True) hostname = models.CharField(max_length=32) ip = models.CharField(max_length=17) # h2g = models.ManyToManyField('Group') # group_set 反向查的对象 class Group(models.Model): gid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) h2g = models.ManyToManyField('Host')
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.shortcuts import render from django.shortcuts import HttpResponse from app01.models import * # Create your views here. def index(request): ''' #1 obj = UserType(caption="管理员") obj.save() #1 UserType.objects.create(caption="普通管理员") #1 user_dict={"caption":"超级管理员"} UserType.objects.create(**user_dict) ''' #2 一对多插入 # user_dict = { # "username":"alex", # 'email':'alex@qq.com', # 'pwd':123, # 'user_type':UserType.objects.get(nid=1), #这里是类名 val是对象 # } # UserInfo.objects.create(**user_dict) # #2 制定数据库字段 # user_dict = { # "username":"erice", # 'email':'erice@qq.com', # 'pwd':123, # 'user_type_id':1, #这里是数据库字段名 # } # UserInfo.objects.create(**user_dict) # 3 # ret = UserInfo.objects.all() # print(type(ret),ret.query,ret) # queryset类型 可迭代 # for item in ret: # print(type(item),item,item.query) # 3 values # ret =UserInfo.objects.all().values('username','pwd') # 集合 内为 字典 key为 username pwd <QuerySet [{'pwd': '123', 'username': 'alex'}, {'pwd': '123', 'username': 'erice'}]> # print(type(ret),ret,ret.query) # ret = UserInfo.objects.all().values_list('username','pwd') #<QuerySet [('alex', '123'), ('erice', '123')]> # print(ret) #4 连表 外键字段__字典表字段 就是连表 (语句内部需要用__来找 其他时候for循环对象 obj.外键字段.字典表的字段 ) # ret = UserInfo.objects.all().values("user_type__caption") # #<QuerySet [{'user_type__caption': '管理员'}, {'user_type__caption': '管理员'}]> SELECT `app01_usertype`.`caption` FROM `app01_userinfo` INNER JOIN `app01_usertype` ON (`app01_userinfo`.`user_type_id` = `app01_usertype`.`nid`) # # print(ret,ret.query) # #5 一对多 正向查找 通过 # UserInfo.objects.filter(username="alex") # UserInfo.objects.filter(user_type_id=1) # ret = UserInfo.objects.filter(user_type__caption="管理员").values('username','user_type__caption') #通过外键字段找字典表数据 # print(ret,type(ret)) #6 一对多 反向查找 多关系表_set # obj = UserType.objects.filter(caption="管理员").first() # """ # 1 # 管理员 # <QuerySet [<UserInfo: UserInfo object>, <UserInfo: UserInfo object>]> # """ # print(obj.nid) # print(obj.caption) # # 多关系表_set 支持all等filter方法 # print(obj.userinfo_set.all()) # 7 一对一 onetoone 其实是 foreignkey unique # 多对多创建数据 # Host.objects.create(hostname="c1",ip='1.1.1.1') # Host.objects.create(hostname="c2",ip='1.1.1.2') # Host.objects.create(hostname="c3",ip='1.1.1.3') # Host.objects.create(hostname="c4",ip='1.1.1.4') # # Group.objects.create(name='人事部') # Group.objects.create(name='财务部') # Group.objects.create(name='法物部') # Group.objects.create(name='客服部') # Group.objects.create(name='运营部') # Group.objects.create(name='研发部') # 8 多对多 正向插入 多台机器分配给一个组 # obj = Group.objects.get(gid=1) # print(obj.gid,obj.name,obj.h2g.all()) # 1 人事部 <QuerySet []> # 1 t条条插入 # h2 = Host.objects.get(hid=2) # h1 = Host.objects.get(hid=1) # obj.h2g.add(h2,h1) # queryset 集合插入 *集合 # obj = Group.objects.get(gid=1) # list = Host.objects.filter(hid__gt=3) # obj.h2g.add(*list) # 9 多对多 反向插入 根据 表名_set # 1 条条 插入 # h = Host.objects.get(hid=1) # g1 = Group.objects.get(gid=1) # g1.h2g.add(h) # g2 = Group.objects.get(gid=2) # g2.h2g.add(h) # 2 多条反向插入 # h = Host.objects.get(hid=1) # h.hostname,h.hid,h.group_set #group表_set # # h.group_set.add(*Group.objects.filter(gid__gt=3)) return HttpResponse("ok")
3 详细讲解用法 (大部分用法都在这)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class UserProfile(models.Model): user_info = models.OneToOneField('UserInfo') username = models.CharField(max_length=64) password = models.CharField(max_length=64) def __unicode__(self): return self.username class UserInfo(models.Model): user_type_choice = ( (0, u'普通用户'), (1, u'高级用户'), ) user_type = models.IntegerField(choices=user_type_choice) name = models.CharField(max_length=32) email = models.CharField(max_length=32) address = models.CharField(max_length=128) def __unicode__(self): return self.name class UserGroup(models.Model): caption = models.CharField(max_length=64) user_info = models.ManyToManyField('UserInfo') def __unicode__(self): return self.caption class Host(models.Model): hostname = models.CharField(max_length=64) ip = models.GenericIPAddressField() user_group = models.ForeignKey('UserGroup') def __unicode__(self): return self.hostname
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
user_info_obj = models.UserInfo.objects.filter(id=1).first() print user_info_obj.user_type print user_info_obj.get_user_type_display() print user_info_obj.userprofile.password # 外键字段__字典表字段 在filter查询 否则的话 是点. user_info_obj = models.UserInfo.objects.filter(id=1).values('email', 'userprofile__username').first() print user_info_obj.keys() print user_info_obj.values()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
类似一对一 1、搜索条件使用 __ 连接 2、获取值时使用 . 连接
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
user_info_obj = models.UserInfo.objects.get(name=u'武沛齐') user_info_objs = models.UserInfo.objects.all() group_obj = models.UserGroup.objects.get(caption='CEO') group_objs = models.UserGroup.objects.all() # 添加数据 #group_obj.user_info.add(user_info_obj) #group_obj.user_info.add(*user_info_objs) # 删除数据 #group_obj.user_info.remove(user_info_obj) #group_obj.user_info.remove(*user_info_objs) # 添加数据 #user_info_obj.usergroup_set.add(group_obj) #user_info_obj.usergroup_set.add(*group_objs) # 删除数据 #user_info_obj.usergroup_set.remove(group_obj) #user_info_obj.usergroup_set.remove(*group_objs) # 获取数据 #print group_obj.user_info.all() #print group_obj.user_info.all().filter(id=1) # 获取数据 #print user_info_obj.usergroup_set.all() #print user_info_obj.usergroup_set.all().filter(caption='CEO') #print user_info_obj.usergroup_set.all().filter(caption='DBA') 多对多操作
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# F 使用查询条件的值 # # from django.db.models import F # models.Tb1.objects.update(num=F('num')+1) # Q 构建搜索条件 from django.db.models import Q # con = Q() # # q1 = Q() # q1.connector = 'OR' # q1.children.append(('id', 1)) # q1.children.append(('id', 10)) # q1.children.append(('id', 9)) # # q2 = Q() # q2.connector = 'OR' # q2.children.append(('c1', 1)) # q2.children.append(('c1', 10)) # q2.children.append(('c1', 9)) # # con.add(q1, 'AND') # con.add(q2, 'AND') # # models.Tb1.objects.filter(con) # # from django.db import connection # cursor = connection.cursor() # cursor.execute("""SELECT * from tb where name = %s""", ['Lennon']) # row = cursor.fetchone() 其他操作
Django模糊查询 Q
Q(Name__contains=sqlstr)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1.django 用Q(a)|Q(b)来实现 sql中 where a or b 功能 2.Q(Name__contains=sqlstr) 这句的意思是 在 sql 中 like '%sqlstr%' 3.Q(VIPId__VIPMachineCode__contains=sqlstr) 意思跟上面一样,不过要注意 VIPId 在CarOwner中是一个外键,引用的字段是VIP中的主键 4.如果filter()函数中有逗号,是代表WHERE AND 的意思 具体实现代码 class VipSerachList(ListView): def get(self, request,page, *args, **kwargs): sqlstr=request.session["VipSearachTxt"] carOwner= CarOwner.objects.filter(Q(Name__contains=sqlstr)|Q(MUser__username__contains=sqlstr)|Q(VIPId__VIPMachineCode__contains=sqlstr)|Q(VipState__StateName__contains=sqlstr)) #sql Q()相当于where or 查询,查询外键的话,字段__外键的其他字段 page_obj = JuncheePaginator(carOwner,8) try: thePage = page_obj.page(int(page)) except PageNotAnInteger: thePage = page_obj.page(int(1)) except EmptyPage: thePage = page_obj.page(page_obj.num_pages) return render_to_response('OMS_VipSerachList.html',{'page_obj':thePage, 'is_paginated': page_obj.num_pages > 1,},context_instance=RequestContext(request))
Q 实现and 和 or
我的博客需要添加一个搜索的功能,当然是模糊搜索,为了方便想直接利用django中ORM自带的模糊搜索。但是后来我发现个问题,到现在为止 我看到个资料中还没有讲到过在多个字段中都模糊搜索的例子。比如,我这个搜索,需要在标题和内容中都要进行查找,在以往的资料中没有解决方案。 之前的都是在一个字段中中查找,用contains或者icontains,他们的区别就是区分大小写。后来我想是不是可以用这个方式来进行模糊查找呢? Entity.objects.filter(title__contiains=='xx').filter(content__contains="xx") 但是这个方式是and的,并不是or的 继续查资料,然后就发现了extra这个万能的方法,这个方法就是在复杂查询的情况下使用的,他可以指定各种参数,是各种,很多种。 但是因为他太全能力,我也没用好,一直也没鼓捣出来怎么模糊查询。 就继续查找资料吧,我寻思怎么也得有人用到模糊查询的吧,果然,发现一个好东西,先上链接: https://docs.djangoproject.com/en/1.3/topics/db/queries/#complex-lookups-with-q-objects 具体的用法我就不多讲了,文档上很清楚的么,我就把我的项目中的代码贴一下 articlelist=Article.objects.filter(Q(title__icontains=search)|Q(content__icontains=search)) 很好用的哦~
应用Q:filter过滤不等于
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
如果想按条件过滤掉某些数据,用filter方法。但如何表示“不等于”这个概念呢? myapps = App.objects.filter(name != '')) 这种写法是不对的,正确写法是: from django.db.models import Q myapps = App.objects.filter(~Q(name= ''))
三 分开讲解上面的详细用法3:表字段的约束 一对一 一对多 多对多各种关系添加 查询注意点
3.1 django的model注意零碎点 :
(1)3版本python 需要定义为MySQLDB
my_django/__init__.py python3 是pymysql 没有MySQLDB 配置 import pymysql pymysql.install_as_MySQLdb()
(2) settings文件 添加app名称
setting内instaldb 配置app01名字
(3)mysql数据库连接
settings配置连接mysql DATABASES = { "default":{ "ENGINE":'django.db.backends.mysql', "NAME":"django_s55", 'USER': 'root', 'PASSWORD': '123456', 'HOST': '', 'PORT': '', } }
(4)其他准备 建库 生成表
mysql> create database django_s55 default character set utf8 collate utf8_bin; Query OK, 1 row affected (0.01 sec) 生成表 python3 manage.py makemigrations python3 manage.py migrate
3.2 models 创建 一对多表 创建两个字段的约束:唯一组合索引
(1)唯一组合索引与 普通组合索引
class Meta: unique_together =[ ("username","email"), ]
class Meta:
index_together =[
("username","email"),
]
(2)一对多表语句
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class UserType(models.Model): nid=models.AutoField(primary_key=True) #自增 主键 caption=models.CharField(max_length=16) #必须给长度 class UserInfo(models.Model): username = models.CharField(max_length=32) email=models.EmailField(max_length=32) pwd = models.CharField(max_length=32) user_type=models.ForeignKey("UserType") # 不加引号,这个类必须提前创建 加了引号 上面的类也可以放在下面 class Meta: index_together =[ ("username","email"), ]
注意的一点
不加引号,这个类必须提前创建 加了引号 上面的类也可以放在下面
user_type=models.ForeignKey("UserType") # 不加引号,这个类必须提前创建 加了引号 上面的类也可以放在下面
(3) 一对多表 查询 插入
1 插入字典表数据
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#1 obj = UserType(caption="管理员") obj.save() #1 UserType.objects.create(caption="普通管理员") #1 user_dict={"caption":"超级管理员"} UserType.objects.create(**user_dict)
2 一对多插入数据 重要
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# user_dict = { # "username":"alex", # 'email':'alex@qq.com', # 'pwd':123, # 'user_type':UserType.objects.get(nid=1), #这里是类名 val是对象 # } # UserInfo.objects.create(**user_dict) # #2 制定数据库字段 # user_dict = { # "username":"erice", # 'email':'erice@qq.com', # 'pwd':123, # 'user_type_id':1, #这里是数据库字段名 # } # UserInfo.objects.create(**user_dict)
3 正向反向查询(一对多,连表)
正向: item.外键字段.caption 与 外键字段__caption
反向: obj(根据get获取字典表对象).外键表名_set.all() 与 字典表.objects.all().values('外键表名__user')
连表(一对多): 正向查找: ret = UserInfo.objects.all() for item in ret: item.id item.外键字段.caption # 这里的外键字段是model类对应字段不是表字段 Tb.objects.filter(字段=‘’,外键字段__caption=‘’).values('外键字段__caption') 反向查找: obj = UserType.objects.get(nid=1) obj.nid obj.caption result = obj.表名_set.all() # 当前管理员相关的所有用户 这里的表名是有外键的表(通过字典表对象obj反向查外键表) UserType.objects.all().values('nid', '表名__user') # 第二种查找
(3.1)正向查询普通的字段查询不是在filter中查询的方式用表.字段,即使是外键字段也是这样 莫与filter内部外键字段__字典表字段 混淆
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 3 ret = UserInfo.objects.all() print(type(ret),ret.query,ret) # queryset类型 可迭代 #<class 'django.db.models.query.QuerySet'> SELECT `app01_userinfo`.`id`, `app01_userinfo`.`username`, `app01_userinfo`.`email`, `app01_userinfo`.`pwd`, `app01_userinfo`.`user_type_id` FROM `app01_userinfo` <QuerySet [<UserInfo: UserInfo object>, <UserInfo: UserInfo object>]> for item in ret: print(type(item),item.user_type.caption) #这里的外键要写model的对应类的字段而不是数据库的表字段user_type_id是不对的 # < class 'app01.models.UserInfo'> 管理员 # < class 'app01.models.UserInfo'> 管理员
(3.2)查询时候values 与 value_list用法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 3 values # ret =UserInfo.objects.all().values('username','pwd') # 集合 内为 字典 key为 username pwd <QuerySet [{'pwd': '123', 'username': 'alex'}, {'pwd': '123', 'username': 'erice'}]> # print(type(ret),ret,ret.query) # ret = UserInfo.objects.all().values_list('username','pwd') #<QuerySet [('alex', '123'), ('erice', '123')]> # print(ret)
(3.3)正向查询 这个是在filter内实现连表查询与(3.1)呼应
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#4 连表 外键字段__字典表字段 就是连表 (语句内部需要用__来找 其他时候for循环对象 obj.外键字段.字典表的字段 ) # ret = UserInfo.objects.all().values("user_type__caption") # #<QuerySet [{'user_type__caption': '管理员'}, {'user_type__caption': '管理员'}]> SELECT `app01_usertype`.`caption` FROM `app01_userinfo` INNER JOIN `app01_usertype` ON (`app01_userinfo`.`user_type_id` = `app01_usertype`.`nid`) # # print(ret,ret.query) #
(3.4)反向查询:通过get获取对象.外键表_set.all() 或者直接字典表名.all().value('外键表__字段')
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# obj = models.UserType.objects.filter(caption= '管理员').first() # print(obj.nid) # print(obj.caption) # print(obj.user_type_set()) # 表名_set.all() # print(obj.userinfo_set.all()) # obj = models.UserType.objects.get(nid=1) # obj.userinfo_set # ret = models.UserType.objects.all().values('nid','caption','userinfo__user') # print(ret)
3.3 models 创建 一对一表 查询 方式看上面的笔记
(1 )两种创建方式 :1 两个表都已唯一索引的字段 2 利用 OneToOneField
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class UserInfo(models.Model): user = models.CharField(max_length=32) email = models.EmailField(max_length=32) pwd = models.CharField(max_length=64) # user_type = models.ForeignKey("UserType", unique=True) # user_type = models.OneToOneField('UserType') user_type = models.ForeignKey("UserType") class UserType(models.Model): nid = models.AutoField(primary_key=True) caption = models.CharField(max_length=16,unique=True)
3.4 model 创建 多对多 三种方式
(1)三种方式:原始方式 与 django自己的方式
创建表: 直接使用m2m 自已定义第三张表 自已定义第三张表 + m2m + through
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 传统多对多 """ class HostToGroup(models.Model): hgid = models.AutoField(primary_key=True) host_id = models.ForeignKey('Host') group_id = models.ForeignKey('Group') class Host(models.Model): hid = models.AutoField(primary_key=True) hostname = models.CharField(max_length=32) ip = models.CharField(max_length=32) class Group(models.Model): gid = models.AutoField(primary_key=True) name = models.CharField(max_length=16) """
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Host(models.Model): hid = models.AutoField(primary_key=True) hostname = models.CharField(max_length=32) ip = models.CharField(max_length=32) # h2g = models.ManyToManyField('Group') class Group(models.Model): gid = models.AutoField(primary_key=True) name = models.CharField(max_length=16) h2g = models.ManyToManyField('Host')
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class HostToGroup(models.Model): hgid = models.AutoField(primary_key=True) host_id = models.ForeignKey('Host') group_id = models.ForeignKey('Group') status = models.IntegerField() class Host(models.Model): hid = models.AutoField(primary_key=True) hostname = models.CharField(max_length=32) ip = models.CharField(max_length=32) # h2g = models.ManyToManyField('Group') # group_set class Group(models.Model): gid = models.AutoField(primary_key=True) name = models.CharField(max_length=16) h2g = models.ManyToManyField('Host',through="HostToGroup")
(2)第一种django自己方式(直接使用m2m)
直接使用m2m --- 获取值 add添加 remove删除,filter.delete() set设置(添加、删除) get_or_create update_or_create --- 补充
增:插入数据 注意: manytomany字段插入数据时候不用管 。表内无这个字段
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# Host插入数据 """ models.Host.objects.create(hostname='c1', ip='1.1.1.1') models.Host.objects.create(hostname='c2', ip='1.1.1.2') models.Host.objects.create(hostname='c3', ip='1.1.1.3') models.Host.objects.create(hostname='c4', ip='1.1.1.4') models.Host.objects.create(hostname='c5', ip='1.1.1.5') """ # Group插入数据 """ models.Group.objects.create(name='财务部') models.Group.objects.create(name='人事部') models.Group.objects.create(name='公关部') models.Group.objects.create(name='技术部') models.Group.objects.create(name='运营部') models.Group.objects.create(name='销售部') models.Group.objects.create(name='客服部') """
如果是传统的创建的表我们可以指定第三张表创建数据
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# models.TB.objects.create(hid=1,gid=1) # models.TB.objects.create(hid=1,gid=2) # models.TB.objects.create(hid=1,gid=3) # models.TB.objects.create(hid=2,gid=2) # models.TB.objects.create(hid=2,gid=3)
通过外键表和非外键表 向关系表插入关系数据
注意:
1 filter获取的是类似列表的可迭代对象,需要加* 而 get获取的是单个对象。可以直接add不用加*
2 正向的外键字段是类的字段不是表的字段
1 . 通过多对多字段 正向 添加 外键字段.add 方法添加 一个对象 或者 *[对象,对象]
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# obj = models.Group.objects.get(gid=1) # obj.h2g.add(*models.Host.objects.all()) # print(obj.gid,obj.name, obj.h2g.all()) # h2 = models.Host.objects.get(hid=2) # h1 = models.Host.objects.get(hid=1) # q = models.Host.objects.filter(hid__gt=3) # obj.h2g.add(*q)
2 . 另一个表反向添加 获取的另一张表对象.表_set.add 方法添加 一个对象 或者 *[对象,对象]
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 将一台机器,分给多个组 # h = models.Host.objects.get(hid=1) # obj = models.Group.objects.get(gid=1) # obj.h2g.add(h) # obj = models.Group.objects.get(gid=2) # obj.h2g.add(h) # h = models.Host.objects.get(hid=6) # h.hostname,h.hid,h.group_set # h.group_set.add(*models.Group.objects.filter(gid__gt = 2)) # h = models.Host.objects.get(hid=1) # h.group_set.add(*models.Group.objects.filter(gid__gt=12))
3 .注意: 添加的列表内部可以不是对象,可以直接是另一张表的id
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
h = models.Host.objects.get(hid=1) # h.group_set.add(1) # h.group_set.add(models.Group.objects.get(gid=1)) # h.group_set.add(*[1,2,3]) # h.group_set.add(*models.Group.objects.filter(gid__gt=1))
删: remove删除关系表只 delete 多表和关系表也删除 慎用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# h.group_set.remove(*models.Group.objects.filter(gid__gt=12)) # h.group_set.all().delete()
改 : set 你获取几条 添加,表里面多的部分会被删除,有的不变 没有的会增加 这里不需要加*
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# h.group_set.set(models.Group.objects.filter(gid__gt=18),clear=True)
其他: update_or_create 和 get_or_create 两个都加
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 两个都加 # r = h.group_set.update_or_create(name='人事部') # print(r) # r = h.group_set.get_or_create(name='技术部') # print(r)
练习
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# models.HostToGroup.objects.create(host_id=1,group_id=2,status=11) # h1 = models.Host.objects.get(hid=1) # ret = h1.group_set.all() # h1.group_set.add(*models.Group.objects.all()) # h1.group_set.set(models.Group.objects.all()) # print(ret)
补充:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# --- Django默认创建第三张表时,内容补充 ---- # h = models.Host.objects.get(hid=1) # h.group_set.add(1) # h.group_set.add(models.Group.objects.get(gid=1)) # h.group_set.add(*[2,3]) # h.group_set.add(*models.Group.objects.filter(gid__gt=1))
(3)第三种的创建多对多 指定manytomany+through
多对多关系中的额外字段
如果仅仅是处理像匹萨和装饰品的混合与搭配这样的简单情况,一个标准的ManyToMany字段完全可以满足你的需要。但有时候你可能需要处理用于描述两个模型之间的关系的数据。
例如,考虑一下这样的应用情况,将音乐家分类为不同的音乐组。一个人和他所属的组之间存在多对多的关系,所以我们可以使用ManyToManyField来表达这种关系。有时候我们可能需要搜集一些关于关系的一些细节,比如一个音乐家加入某音乐组的日期。
对于这样的情形,Django允许你指定一个用于管理多对多关系的中间模型。然后你就可以把额外的那些字段放在这个中间模型中。通过在ManyToMany字段中指定through参数可以指定用作中介的中间模型。对于上面提到的音乐家分组的例子,代码看起来就像这样:
class Person(models.Model): name = models.CharField(max_length=128) def __unicode__(self): return self.name class Group(models.Model): name = models.CharField(max_length=128) members = models.ManyToManyField(Person, through='Membership') #注意这里 def __unicode__(self): return self.name class Membership(models.Model): person = models.ForeignKey(Person) group = models.ForeignKey(Group) date_joined = models.DateField() invite_reason = models.CharField(max_length=64)
一旦你设定了中间模型,也就意味着明确地指出了多对多关系关联到的模型的外键。这个明确地声明定义了这两个模型是如何关联起来的。
以下是关于中间模型的一些限制:
中间模型必须有且仅有一个外键指向目标模型(也就是本例中的Person)。使用多于一个的外键将会引发验证错误。
中间模型必须有且仅有一个外键指向源模型(也就是本例中的Group)。使用多于一个的外键将会引发验证错误。
唯一例外的情况是一个模型通过中间模型与自身产生多对多关系。这种情况下,两个外键指向同一个模型是允许的,但是它们会被看作同一个多对多关系的两个(不同的)方面。
当定义模型通过中间模型与其自身产生的多对多关系时,你必须使用参数symmetrical=False(查看模型字段参考了解更多细节)。
到这里,你已经通过中间模型设置好了一个多对多字段,也就是说,你已经准备好创建一些多对多关系了。要做到这一点,需要创建中间模型的实例:
>>> ringo = Person.objects.create(name="Ringo Starr") >>> paul = Person.objects.create(name="Paul McCartney") >>> beatles = Group.objects.create(name="The Beatles") >>> m1 = Membership(person=ringo, group=beatles, ... date_joined=date(1962, 8, 16), ... invite_reason= "Needed a new drummer.") >>> m1.save() >>> beatles.members.all() [<Person: Ringo Starr>] >>> ringo.group_set.all() [<Group: The Beatles>] >>> m2 = Membership.objects.create(person=paul, group=beatles, ... date_joined=date(1960, 8, 1), ... invite_reason= "Wanted to form a band.") >>> beatles.members.all() [<Person: Ringo Starr>, <Person: Paul McCartney>]
与普通的多对多字段不同的是,你不能使用add,create命令,或者通过直接赋值(例如,beatles.members = […])的方式来创建关系:
#这个命令不会被运行 >>> beatles.members.add(john) #这个也不会运行 >>> beatles.members.create(name="George Harrison") #下面这个也不会运行 >>> beatles.members = [john, paul, ringo, george]
为什么呢?因为你需要通过模型Membership指出多对多关系的所有细节,所以不能直接创建Person和Group之间的关系。简单地使用add,create命令,或者通过直接赋值这些方式并不能指明这些细节。因此,在通过中间模型表达多对多关系的情形中,这些命令是被禁用的。创建这种类型的关系的唯一方式就是只能通过创建中间模型的实例来实现。
因为相同的原因,remove命令也是不允许被使用的。但是,可以使用clear( )方法来移除一个实例的所有多对多关系:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# Beatles have broken up >>> beatles.members.clear()
一旦通过创建中间模型的实例建立起了多对多关系,就可以执行查询了。就像对待普通的多对多关系一样,你可以使用多对多关系关联的模型的属性来执行查询:
# 找出所有的组,这些组中含有成员名字以'Paul'开头的记录
>>> Group.objects.filter(members__name__startswith='Paul') [<Group: The Beatles>]
使用一个中间模型时,你也可以直接查询它的属性:
# 找出1961年1月1日之后加入Beatles组的所有成员
>>> Person.objects.filter( ... group__name='The Beatles', ... membership__date_joined__gt=date(1961,1,1)) [<Person: Ringo Starr]
model补充 group by解释 上面有笔记
order by应用
直接不加符号是正序 加-号是 倒叙 # models.Tb1.objects.filter(name='seven').order_by('id') # asc # models.Tb1.objects.filter(name='seven').order_by('-id') # desc
group by --- values('id').annotate(c=Count('num'))
注意:如果不加 values ( id)是group by的所有字段。
# group by from django.db.models import Count, Min, Max, Sum # models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num')) # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"