Python Day20

Django 表操作

1、基本操作

    # 增
    #
    # 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、进阶操作

# 获取个数
    #
    # 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"
# 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()

4、连表操作

models.py
#_*_coding:utf-8_*_
from django.db import models

# Create your models here.

class Colors(models.Model):
    colors=models.CharField(u'颜色',max_length=10)
    def __unicode__(self):
        return self.colors

class Ball(models.Model):
    color=models.OneToOneField("Colors")  #与颜色表为一对一,颜色表为母表
    description=models.CharField(u'描述',max_length=10)
    def __unicode__(self):
        return self.description

class Clothes(models.Model):
    color=models.ForeignKey("Colors")   #与颜色表为外键,颜色表为母表
    description=models.CharField(u'描述',max_length=10)
    def __unicode__(self):
        return self.description    
    
class Child(models.Model):
    name=models.CharField(u'姓名',max_length=10)   
    favor=models.ManyToManyField('Colors')    #与颜色表为多对多

一对一

#子表查询母表,找到红球对应的颜色
#写法1:
print(models.Ball.objects.get(description="红球").color.colors)  #返回红,通过子表查询母表,写法:"子表对象.母表表名的小写.母表字段名" ;通过Ball表查到description为"红球",查找到对应colors
#写法2,反向从母表入手:
print(models.Colors.objects.get(ball__description="红球").colors) #返回红,通过子表查询母表,但形式上是从母表对象自身直接获取字段,写法:"母表.objects.get(子表名小写__子表字段="xxx").母表字段名" ;效果和上边完全一致,另一种形式


#母表查询子表,找到红色对应的球的名字
#写法1:
print(models.Colors.objects.get(colors="红").ball.description)  #返回红球,通过母表查询子表,写法:"母表对象.子表表名的小写.子表字段名";找到颜色为红色的Ball的description
#写法2,反向从子表入手:
print(models.Ball.objects.get(color__colors="红").description)  #返回红球,通过母表查询子表,但形式上是从子表对象自身直接获取字段,写法:"子表.objects.get(一对一的子表字段__母表字段="xxx").子表字段";效果和上边完全一致,另一种形式
#添加一种颜色黑,并添加黑球
color_obj=models.Colors.objects.create(colors="黑")  #先在母表中创建颜色,并实例化给颜色表对象
models.Ball.objects.create(color=color_obj,description="黑球")  #更新Ball表,color字段为颜色表对象,添加description字段

#增添数据的三种写法:
#写法1:
color_obj=models.Colors.objects.create(colors="黑")
models.Ball.objects.create(color=color_obj,description="黑球")
#写法1补充:
color_id=models.Colors.objects.create(colors="黑").id
models.Ball.objects.create(color_id=color_id,description="黑球")
#写法2:
color_obj=models.Colors.objects.create(colors="黑")
ball_obj=models.Ball(color=color_obj,description="黑球")
ball_obj.save()
#写法3(字典导入):
color_obj=models.Colors.objects.create(colors="黑")
ball_dic={'description':"黑球"}
models.Ball.objects.create(color=color_obj,**ball_dic)
color_obj=models.Colors.objects.get(colors="黑") #.get()等同于.filter().first()
color_obj.colors="灰"
color_obj.save()
models.Ball.objects.filter(description="黑球").update(color=color_obj,description="灰球") #update(),delete()是QuerySet的方法


#更新一条数据
color_obj=models.Colors.objects.get(colors="黑")
color_obj.colors="灰"
color_obj.save()
#更新多条数据,把满足条件的球的description都变为灰球
#写法1:
models.Ball.objects.filter(color__colors="红").update(description="灰球")
#写法2:
up_dic={"description":"灰球"}
models.Ball.objects.filter(id__gt=0).update(**up_dic)
models.Ball.objects.get(description="灰球").delete() #对象和QuerySet都有方法delete()
models.Colors.objects.filter(colors="灰").delete()

models.Colors.objects.all().delete() #清空一张表

一对多(外键)

#外键表联合查询:

#外键子表查询母表,与一对一子表查询母表形式一致
#找到红裤衩所属的颜色表中的颜色--返回:红
#写法1:
print(models.Clothes.objects.get(description="红内裤").color.colors)  #返回红,通过子表查询母表,写法:"子表对象.母表表名的小写.母表字段名" ;通过Clothes表查到description为"红内裤",查找到对应colors
#写法2,反向从母表入手:
print(models.Colors.objects.get(clothes__description="红内裤").colors)  #返回红,通过子表查询母表,但形式上是从母表对象自身直接获取字段,写法:"母表.objects.get(子表名小写__子表字段="xxx").母表字段名" ;效果和上边完全一致,另一种形式

#外键母表查询子表,与一对一形式不同,因为母表为"多",不能像一对一一样通过.get().子表.子表字段的方式获取,但与多对多母表查询子表一致
#找到颜色为红的所有服装--返回:[<Clothes: 红内衣>, <Clothes: 红内裤>]
#写法1:
color_obj=models.Colors.objects.get(colors="红")
print(color_obj.clothes_set.all())  #注意:子表小写_set的写法,它实际上是一个QuerySet,可以用update,delete,all,filter等方法
#写法2:
print(models.Clothes.objects.filter(color=models.Colors.objects.get(colors="红")))
#写法2简便写法(推荐):
print(models.Clothes.objects.filter(color__colors="红"))  #写法:filter(子表外键字段__母表字段='过滤条件')
#写法3:
color_id=models.Colors.objects.get(colors="红").id  #通过母表获取到颜色为红的id
print(models.Clothes.objects.filter(color_id=color_id))  #filter得到QuerySet,写法:filter(子表外键字段_母表主键=母表主键对象)

 备注:通过QuerySet的.values()方法,将QuerySet转化为ValuesQuerySet

print(models.Clothes.objects.filter(color=models.Colors.objects.get(colors="红")).values('color__colors','description'))  #获取子表的description字段,和母表的colors字段,获取母表字段写法: 子表外键字段名__母表字段名--适用于values()或filter()
#简写形式补充:
print(models.Clothes.objects.filter(color__colors="红").values('color__colors','description'))
#返回:
[{'description': u'\u7ea2\u5185\u8863', 'color__colors': u'\u7ea2'}, {'description': u'\u7ea2\u5185\u88e4', 'color__colors': u'\u7ea2'}]
#如果不加values(),返回的是[<Clothes: 红内衣>, <Clothes: 红内裤>]这样一个QuerySet集合,通过values可以形成一个列表,列表中的每一个元素是一个字典,可以通过list()将ValuesQeurySet转化为列表,之后返回给templates


#另外可通过.values_list()将QuerySet转化为ValuesListQuerySet。返回:[(u'\u7ea2', u'\u7ea2\u889c\u5b50'), (u'\u7ea2', u'\u7ea2\u889c\u5b50')]
#得到的是一个列表,列表中是多个元组,每个元组是ValuesQuerySet中字典的value,常用于从models里将数据取出后动态添加到前端模板中的select选项中。
#通过forms.py从models取值传给前端select选项,需重启django后,select选项才能更新,可在定义form时,添加如下关键字保障动态更新select选项
#forms.py
from django import forms
from test1 import models
class ClothesForm(forms.Form):
    color=forms.IntegerField(required=True,widget=forms.Select(),)
    def __init__(self,*args,**kwargs):  #定义这个关键字段,当使用form时,colors表新增了颜色,前端ClothesForm的color字段的选项会自动更新
        super(ClothesForm, self).__init__(*args,**kwargs)
        self.fields['color'].widget.choices=models.Colors.objects.all().order_by('id').values_list('id','colors')
#增添子表数据,形式与一对一一致
#添加颜色为绿的服装:绿裤头
#方法1:
models.Clothes.objects.create(color=models.Colors.objects.get(colors="绿"),description="绿裤头")
#方法1补充:
models.Clothes.objects.create(color_id=models.Colors.objects.get(colors="绿").id,description="绿裤头")
#方法2:
c_obj=models.Clothes(color=models.Colors.objects.get(colors="绿"),description="绿裤头")
c_obj.save()
#方法3:字典方式录入..参考一对一
#颜色为红的服装,description都更新为红袜子
#写法1:
models.Clothes.objects.filter(color__colors="红").update(description="红袜子")
#写法2:
models.Clothes.objects.filter(color_id=models.Colors.objects.get(colors="红").id).update(description="红袜子")
#写法3:
colors_obj=models.Colors.objects.get(colors="红")
colors_obj.clothes_set.filter(id__gte=1).update(description="红袜子")
#其他写法参照一对一的修改和外键的查询
 models.Clothes.objects.get(description="灰裙子").delete() #对象和QuerySet都有方法delete()
models.Colors.objects.filter(colors="灰").delete()

多对多

#多对多子表查询母表,查找小明喜欢哪些颜色--返回:[<Colors: 红>, <Colors: 黄>, <Colors: 蓝>]
#与一对多子表查询母表的形式不同,因为一对多,查询的是母表的“一”;多对多,查询的是母表的“多”
#写法1:
child_obj=models.Child.objects.get(name="小明")  #写法:子表对象.子表多对多字段.过滤条件(all()/filter())
print(child_obj.favor.all())
#写法2,反向从母表入手:
print(models.Colors.objects.filter(child__name="小明")) #母表对象.filter(子表表名小写__子表字段名="过滤条件")


#多对多母表查询子表,查找有哪些人喜欢黄色--返回:[<Child: 小明>, <Child: 丫蛋>]
#与一对多母表查询子表的形式完全一致,因为查到的都是QuerySet,一对多和多对多,都是在查询子表的“多”
#写法1:
color_obj=models.Colors.objects.get(colors="黄")
print(color_obj.child_set.all())
#写法2:
print(models.Child.objects.filter(favor=models.Colors.objects.get(colors="黄")))
#写法2简便写法(推荐):
print(models.Child.objects.filter(favor__colors="黄"))  #写法:filter(子表外键字段__母表字段='过滤条件')
#写法3:
color_id=models.Colors.objects.get(colors="黄").id  #通过母表获取到颜色为红的id
print(models.Child.objects.filter(favor=color_id))  #filter得到QuerySet,写法:filter(子表外键字段=母表主键对象),此处和一对多略有不同,是子表外键字段而不是外键字段_母表主键
增与改(增添子表或母表数据参照一对一的增,多对多重点在于关系表的对应关系变更)
#添加子表关联关系
#添加小呆并让他喜欢所有颜色
#写法1:
child_obj=models.Child.objects.create(name="小呆")  #如果是已有用户,使用.get()
colors_obj=models.Colors.objects.all()  #创建颜色表的所有颜色QuerySet对象
child_obj.favor.add(*colors_obj)  #添加对应关系,将小呆和所有颜色进行关联,写法:子表对象.子表多对多字段.add(*QuerySet对象)
#写法2:
child_obj=models.Child.objects.get(name="小呆")
colors_obj=models.Colors.objects.all()
child_obj.favor=colors_obj
child_obj.save()
#让小呆喜欢黄色和蓝色(2种写法和上边一致,只展示一种写法)
child_obj=models.Child.objects.get(name="小呆")
colors_obj=models.Colors.objects.filter(colors__in=["蓝","黄"])  #models默认只能用这种方式得到并集,如需更复杂的过滤逻辑,需使用模块Q
child_obj.favor.clear()  #清空小呆已经喜欢的颜色
child_obj.favor.add(*colors_obj)  #add是追加模式,如果当前小呆已经喜欢绿色,那么执行后,小呆会额外喜欢蓝,黄
#让小呆喜欢绿色(2种写法和上边一致,只展示一种写法)
child_obj=models.Child.objects.get(name="小呆")
colors_obj=models.Colors.objects.get(colors="绿")
child_obj.favor.clear()
child_obj.favor.add(colors_obj)  #此处没有*


#添加母表关联关系
#让喜欢蓝色的人里添加小呆,可以用上边的方法,一个效果,让小呆喜欢蓝色,下边介绍反向插入(从母表入手)的写法
child_obj=models.Child.objects.get(name="小呆")
colors_obj=models.Colors.objects.get(colors="蓝")
colors_obj.child_set.add(child_obj)  #从colors表插入小呆,写法:母表对象.子表名小写_set.add(子表对象)。 让喜欢蓝色的child_set集合添加name="小呆"
#让所有人都喜欢蓝色
children_obj=models.Child.objects.all()
colors_obj=models.Colors.objects.get(colors="蓝")
colors_obj.child_set.add(*children_obj)
#关于_set写法,是否已经有些晕了,究竟什么时候使用_set,简单记忆,只有子表才有"子表名小写_set"的写法,得到的是一个QuerySet集合,后边可以接.add(),.remove(),.update(),.delete(),.clear()
#另外备注一下,colors_obj.child_set.clear()是让所有人喜欢的颜色里去掉蓝色,colors_obj.child_set.all().delete()是删除.child_set的所有人
删:删除多对多表关系
#删除子表与母表关联关系
#让小呆不喜欢任何颜色
#写法1:
child_obj=models.Child.objects.get(name="小呆")
colors_obj=models.Colors.objects.all()
child_obj.favor=''
child_obj.save()
#写法2:
child_obj=models.Child.objects.get(name="小呆")
colors_obj=models.Colors.objects.all()
child_obj.favor.remove(*colors_obj)
#写法3:
child_obj=models.Child.objects.get(name="小呆")
child_obj.favor.clear()
#其他例子参照多对多的增与改案例,这里不做举例

#删除母表与子表关联关系
#让所有人不再喜欢蓝色
#写法1:
children_obj=models.Child.objects.all()
colors_obj=models.Colors.objects.get(colors="蓝")
colors_obj.child_set.remove(*children_obj)
#写法2:
colors_obj=models.Colors.objects.get(colors="蓝")
colors_obj.child_set.clear()
删除多对多表数据
#删除子表数据
#喜欢蓝色的所有人都删掉
colors_obj=models.Colors.objects.get(colors="蓝")
colors_obj.child_set.all().delete()  #注意有.all()
#删除所有child
models.Child.objects.all().delete()
posted @ 2016-12-22 23:05  邵林  阅读(142)  评论(0编辑  收藏  举报