django 表操作(增删改查)

一:查看orm写的sq语句

如果对某个语句不清楚的话可以调用queryset的的query方法来查看sql。

1 obj=Hostinfo.objects.filter(id=val).values(id)
2 print(obj.query)

一:基本操作

包括增删改查

 1 # 增
 2     #
 3     # models.Tb1.objects.create(c1='xx', c2='oo')  增加一条数据,可以接受字典类型数据 **kwargs
 4 
 5     # obj = models.Tb1(c1='xx', c2='oo')
 6     # obj.save()
 7 
 8     # 查
 9     #
10     # models.Tb1.objects.get(id=123)         # 获取单条数据,不存在则报错(不建议)
11     # models.Tb1.objects.all()               # 获取全部
12     # models.Tb1.objects.filter(name='seven') # 获取指定条件的数据
13 
14     # 删
15     #
16     # models.Tb1.objects.filter(name='seven').delete() # 删除指定条件的数据
17 
18     # 改
19     # models.Tb1.objects.filter(name='seven').update(gender='0')  # 将指定条件的数据更新,均支持 **kwargs
20     # obj = models.Tb1.objects.get(id=1)
21     # obj.c1 = '111'
22     # obj.save()                                                 # 修改单条数据

 其中需要注意的是:django中的and用法:是用逗号, 比如说:models.Tb1.objects.filter(name='seven' ,id=2).delete()表示的是删除name='seven' 并且id=2.

这里的filter相当于where条件。

查询:

通常我们查询的出的语句是一个对象的列表,列表内的对象并不是python 的对象,是django的类的一个对象。queryset对象。

比如:

1 def test(request):
2     user_obj=models.Title.objects.filter(title='evil')
3     print(type(user_obj))
4     return  HttpResponse('ok')
5 <class 'django.db.models.query.QuerySet'>

modle的表的类的对象是数据库中的列的对象。

如果我们查询的时候不想要对象的列表,那我们使用values和value_list的参数进行查找。获取是不是对象,而是特殊的列表!

values:

1 def test(request):
2     user_obj=models.Title.objects.filter(title='evil').values('title')
3     print(user_obj)
4     return  HttpResponse('ok')
5 <QuerySet [{'title': 'evil'}, {'title': 'evil'}, {'title': 'evil'}]>#可以看做列表中嵌套字典形式。

可以进行循环输出:

 1 def test(request):
 2     user_obj=models.Title.objects.filter(title='evil').values('title')
 3     print(user_obj)
 4     for item in user_obj:
 5         print(item['title'])
 6     return  HttpResponse('ok')
 7 <QuerySet [{'title': 'evil'}, {'title': 'evil'}, {'title': 'evil'}]>
 8 evil
 9 evil
10 evil

values_list来查询的时候,数组的集合。也就是列表中嵌套元组形式!!可以获取多个字段!!

 1 def test(request):
 2     user_obj=models.Title.objects.filter(title='evil').values_list('title')
 3     print(user_obj)
 4     for item in user_obj:
 5         print(item)
 6     return  HttpResponse('ok')
 7 <QuerySet [('evil',), ('evil',), ('evil',)]>
 8 ('evil',)
 9 ('evil',)
10 ('evil',

 二:进阶操作 了不起的双下划线  __

 1 # 获取个数
 2     #
 3     # models.Tb1.objects.filter(name='seven').count()
 4 
 5     # 大于,小于
 6     #
 7     # models.Tb1.objects.filter(id__gt=1)              # 获取id大于1的值
 8     # models.Tb1.objects.filter(id__lt=10)             # 获取id小于10的值
 9     # models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值
10 
11     # in
12     #
13     # models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据
14     # models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in
15 
16     # contains
17     #
18     # models.Tb1.objects.filter(name__contains="ven")
19     # models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
20     # models.Tb1.objects.exclude(name__icontains="ven")
21 
22     # range
23     #
24     # models.Tb1.objects.filter(id__range=[1, 2])   # 范围bettwen and
25 
26     # 其他类似
27     #
28     # startswith,istartswith, endswith, iendswith,
29 
30     # order by
31     #
32     # models.Tb1.objects.filter(name='seven').order_by('id')    # asc
33     # models.Tb1.objects.filter(name='seven').order_by('-id')   # desc 倒序排列。
34 
35     # limit 、offset
36     #
37     # models.Tb1.objects.all()[10:20]##这个limit 不是去数据库取所有的数据。
38 
39     # group by
40     from django.db.models import Count, Min, Max, Sum
41     # models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num'))
42     # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"

需要注意的是:models.Tb1.objects.all()[10:20]  不是取所有的数据而是limit获取指定的列。。。。

1 models.Tb1.objects.filter(name='seven').order_by('id')    # asc
2 models.Tb1.objects.filter(name='seven').order_by('-id')   # desc 倒序排列。

需要注意的是:当参数前面加负号(-)的时候,表示的是倒序。!!!

了不起的双下划线:

一对多

增加:  没有外键的表。插入数据没有限制。而有外键的表,需要依赖另一个张表,在django中,含有外键的表的列,是另一个表的对象。有如下数据的插入,有如下的方法:

1、直接插入对象,但是这种方法有个弊端,需要多次的查询库。效率不高。

表结构:

 1 from django.db import models
 2 
 3 # Create your models here.
 4 class UserType(models.Model):
 5     name=models.CharField(max_length=32)
 6 
 7 class User(models.Model):
 8     username=models.CharField(max_length=32)
 9     pwd=models.CharField(max_length=32)
10     user_type=models.ForeignKey('UserType')

插入语句:

1 def test(request):
2     # models.UserType.objects.create(name='管理员')
3     models.User.objects.create(username='evil',pwd='123',user_type=models.UserType.objects.filter(id=1).first())
4     return  HttpResponse('ok')

需要查询2次库。效率不高,需要注意的插入的是对象,不是列表。需要加first()

2:直接插入,在django 中 含有外键的列,在实际数据库中是:列名_id

含有外键的表结构:

这个id的值和关联的表的id值是一致的。

插入语句:

表结构:

 1 from django.db import models
 2 
 3 # Create your models here.
 4 class UserType(models.Model):
 5     name=models.CharField(max_length=32)
 6 
 7 class User(models.Model):
 8     username=models.CharField(max_length=32)
 9     pwd=models.CharField(max_length=32)
10     user_type=models.ForeignKey('UserType')

 

1 from django.shortcuts import render,HttpResponse
2 from test_mo import models
3 # Create your views here.
4 def test(request):
5     # models.UserType.objects.create(name='管理员')
6     models.User.objects.create(username='tom',pwd='123',user_type_id=2)
7     return  HttpResponse('ok')

 

查询:对于一对多,跨表查询,比如上面的表结构:

 1 from django.db import models
 2 
 3 # Create your models here.
 4 class UserType(models.Model):
 5     name=models.CharField(max_length=32)
 6 
 7 class User(models.Model):
 8     username=models.CharField(max_length=32)
 9     pwd=models.CharField(max_length=32)
10     user_type=models.ForeignKey('UserType')

我现在想查询:用户类型为管理员的用户名和密码。

分析:常规的是:先查询UserType 这表的类型为“”管理员”的id,然后在查询User表中user_type_id=2的用户名。

这样查询:对数据库进行了2次查询。比较繁琐,通过双下划线可以进行简单的查询.

1 from django.shortcuts import render,HttpResponse
2 from test_mo import models
3 # Create your views here.
4 def test(request):
5     queyry_res=models.User.objects.filter(user_type__name='管理员').values_list('username','pwd')
6     print(queyry_res)
7     return  HttpResponse('ok')
8 <QuerySet [('tom', '123')]>#返回一个特殊的列表含有元组的。

通过含有外键的(列__name='xx')来筛选我们想要的数据。

虽然我们在执行多对一的查询的时候,都是正向查询。其实django 在多对一的情况下给咱们提供和多对多的反向查询提供的虚拟列 是一样都是:tablename_set(tablename为含有foreign key的表)来反向查询:

 modles:

1 class Person(models.Model):
2     name=models.CharField(max_length=32)
3 
4 class  Favor(models.Model):
5     fav_name=models.CharField(max_length=32)
6     p_fav=models.ForeignKey('Person')

需求:名字叫做evil的爱好是什么?进行反向查询:

1 def person(request):
2     per_obj=models.Person.objects.filter(name='evil').first()
3     print(per_obj.favor_set.all().first().fav_name)
4     return HttpResponse('ok')

注意:person是对多个favor 所以的查询的结果是集合。

同样favor_set 和多对多一样也有add 方法等。

虽然Person有这些方法,但是Favor没有这些方法(add、all等)!!!注意和多对多的区别!

注意:双下划线是参数!!django 只是通过双下划线来查找另一个张表。而在表结构中,外键列是他关联的表的对象可以直接通过点.属性获取!!!而不是双下划线!!!

1 def test(request):
2     queyry_res=models.User.objects.filter(user_type__name='管理员')
3     print(queyry_res)
4     print(queyry_res[0].user_type.name)
5     return  HttpResponse('ok')
6 <QuerySet [<User: User object>]>
7 管理员

 即查询的结果。不能通过双下划线来获取字段,而是通过点.属性来获取。

对于values和values_list  可以进行跨表的查询。语法如下:

1 from django.shortcuts import render,HttpResponse
2 from test_mo import models
3 # Create your views here.
4 def test(request):
5     query_res=models.User.objects.filter(id=2).values_list('user_type__name')
6     print(query_res)
7     return  HttpResponse('ok')
8 <QuerySet [('管理员',)]>

双下划线可以跨一张、多张表进行查询。。。。

有如下表结构:

 1 from django.db import models
 2 
 3 # Create your models here.
 4 class UserType(models.Model):
 5     name=models.CharField(max_length=32)
 6     gender=models.ForeignKey('Gender')
 7 
 8 class User(models.Model):
 9     username=models.CharField(max_length=32)
10     pwd=models.CharField(max_length=32)
11     user_type=models.ForeignKey('UserType',default=1)
12 
13 
14 class Gender(models.Model):
15     gender=models.CharField(max_length=32)

需求:查看用户的名为tom的对应的性别。

方法1:

1 def test(request):
2     res=models.User.objects.filter(username='tom').values_list('user_type__gender__gender')
3     print(res)
4     return  HttpResponse('ok')
5 <QuerySet [('',)]>

通过2个双下划线查找到第三张表的内的属性值。

方法2:因为双下划线是只是参数。因为外键对应的列是关联的表的对象实例。我们可以通过这个对象实现关联到另一个对象的实例以此类推。。。。来查找多个表的字段。

1 def test(request):
2     res=models.User.objects.filter(username='tom')
3     for item in res:
4         print(item.user_type.gender.gender)
5     # models.UserType.objects.create(name='游客',gender_id=1)
6     # models.Gender.objects.create(gender="")
7     return  HttpResponse('ok')
8 9

modle 类中外键对应列 实际上数据库中储存对应的列为:列名_id 比如上面user_type_id、gender_id。

插入数据的时候,在数据库层面上可以直接指定user_type_id=xxx,gender_id=xxx。

在modle类中,我们需要创建对应的外键的 user_type的对象、gender对象来插入。

查询的时候,需要借助django的双下划线参数或者根据插入的外键的时候是另一张表的对象,通过点.来获取我们想要的字段。

一个数据库的实际存储的情况。

一个django 给咱们提供相应的方法。查询的时候需要根据django提供的方法。而不是通过实际数据库存储的情况。当然也可以根据数据库实际存储情况来写原生的sql。

多对多表结构

 多对多关系,通过第三张表来建立关系,之前的博客中已经介绍了多对多的情况。如果我们不手动创建第三张表的话,默认django会自动创建第三张。如果我们手动创建的第三张表的话,用foreign key来建立关系。

1:django方式:从django的本质

code:

 1 class Gender(models.Model):
 2     gender=models.CharField(max_length=32)
 3 
 4 
 5 
 6 class Boy(models.Model):
 7     boyname=models.CharField(max_length=32)
 8 
 9 class Gril(models.Model):
10     gril_name=models.CharField(max_length=32)
11     btog=models.ManyToManyField('Boy')

 

执行:python  manager.py makemigrations    python manager.py migrate

我们查看下数据库中表的变化。我们可以看到除了boy和girl 表之外,django 为我们创建第三张表:gril_btog表。 表名是我们创建ManyToMany字段的和当前表的组合。表字段是:gril_id  和boy_id。

2:创建外键方式:

code:

1 class Man(models.Model):
2     man_name=models.CharField(max_length=32)
3 
4 class Woman(models.Model):
5     woman_name=models.CharField(max_length=32)
6 
7 class MantoWoman(models.Model):
8     to_man=models.ForeignKey('Man')
9     to_woman=models.ForeignKey('Woman')

 

上面是我们建立多对多关系的表结构。无论哪一种,都是通过第三张表建立关系。第三张表储存的数据结构都是对应的id,这和sqlalchemy是一样的。

那着重介绍第一种方法的查询:

django 为我们建立第三张表。我们建表的代码如下:

1 class Boy(models.Model):
2     boyname=models.CharField(max_length=32)
3 
4 class Gril(models.Model):
5     gril_name=models.CharField(max_length=32)
6     btog=models.ManyToManyField('Boy')

2张表中唯一和第三张有关系的只有:Gril表的btog字段有关。那我们先给这2个张表的插入数据。

插入数据代码:

 1 def boy(request):
 2     boy_1=request.GET.get('v1',None)
 3     if boy_1:
 4         models.Boy.objects.create(boyname=boy_1)
 5     return  HttpResponse(boy_1)
 6 def gril(request):
 7     gril_1=request.GET.get('v1',None)
 8     if gril_1:
 9         models.Gril.objects.create(gril_name=gril_1)
10     return  HttpResponse(gril_1)

通过get传入参数插入值:http://127.0.0.1:8000/gril/?v1=luc2

数据库:

由于第三张表没有插入值。boy表和gril表没有关系。

 

正向操作:

我们把通过含有ManyToMany的字段的表来操作第三张表我们叫做正向操作.

唯一有关系的是gril表中btog字段。

插入单行数据:

我们可以通过这个字段来给第三张表插入值。注意get查看获取的是单个queryset对象不是列表。

代码:

1 def boytogril(request):
2     girl_obj=models.Gril.objects.get(id=1)
3     print(girl_obj.gril_name)
4     boy_obj=models.Boy.objects.get(id=1)
5     girl_obj.btog.add(boy_obj)
6     return HttpResponse('ok') 

第三张表:

如上的girl_obj.btog 字段通过add()方法给第三张表插入数值。该字段有数据相关的操作(增删改查)所有方法。

我们可以通过all方法来查看第三张表。

1 def boytogril(request):
2     girl_obj=models.Gril.objects.get(id=1)
3     print(girl_obj.gril_name)
4     boy_obj=models.Boy.objects.get(id=1)
5     print(girl_obj.btog.all())
6     return HttpResponse('ok')

插入多行数据:

我们可以通过add()方法传入一个列表,来让girl表和boy表产生关系。而不是用多次或者for循环来添加 我们想要关联的数据。

code:

1 def boytogril(request):
2     girl_obj=models.Gril.objects.get(id=2)
3     print(girl_obj.gril_name)
4     boy_list=models.Boy.objects.all()
5     girl_obj.btog.add(*boy_list)
6     print(girl_obj.btog.all())
7     return HttpResponse('ok')

 

让id=2的女孩和所有的男孩产生一对多的关系。注意的是当我们传入的列表的时候,add()方法,参数需要加*

结果:

1 luc2
2 <QuerySet [<Boy: Boy object>, <Boy: Boy object>, <Boy: Boy object>, <Boy: Boy object>]>

 

第三张表:

我们也可以按照我们的筛选的条件进行数据的插入:

1 def boytogril(request):
2     girl_obj=models.Gril.objects.get(id=3)
3     print(girl_obj.gril_name)
4     boy_list=models.Boy.objects.filter(id__in=[2,4])
5     girl_obj.btog.add(*boy_list)
6     print(girl_obj.btog.all())
7     return HttpResponse('ok')

 

我们让id=3的lili 和 id为2 和4的男孩产生关系。注意双下划线条件的筛选!!

1 lili
2 <QuerySet [<Boy: Boy object>, <Boy: Boy object>]>

 

第三张表:

根据ID 插入数值:

从数据库本质:

我们观察到实际上第三张表插入的数值是数字。我们可以给add()方法传入数字进行插入。

和多对一不同的是:是在外键列对应数据库里是当前列名_id的字段列。我们可以直接给这个列赋值进行插入也外键列赋值关联表的对象

code:

1 def boytogril(request):
2     girl_obj=models.Gril.objects.get(id=4)
3     print(girl_obj.gril_name)
4     # boy_list=models.Boy.objects.filter(id__in=[2,4])
5     girl_obj.btog.add(*[1,3])
6     print(girl_obj.btog.all())
7     return HttpResponse('ok')
1 女帝
2 <QuerySet [<Boy: Boy object>, <Boy: Boy object>]>

 

第三张表:

我们给id为4的女帝和id为1、3的男孩产生关系。我们直接给add出入id的数字既可。

 反向操作

通过不含有ManyToMany的字段的表操作第三张表,我们叫做反向操作。

在django层面上,在不含有ManyToMany的字段的表,里隐式的给我们创建一列。这是一个虚拟的列,实际数据库中不存在,他的作用是让我们操作数据库更为方便。

这个列是以含有ManyToMany的字段的表名加上下划线和set组合成列名:tablename_set。

我们可以通过这个字段来操作第三张表。这个操作叫做反向操作。

数据的插入:

 

1 def boytogril(request):
2     boy_obj=models.Boy.objects.filter(id=5).first()
3     print(boy_obj.boyname)
4     boy_obj.gril_set.add(*[1,2])
5     return HttpResponse('ok')
6 jack

给id=5的jack和id为1或者2的女孩产生关系。默认在django给咱们创建虚拟列:gril_set列。我们可以通过这个列给操作第三张表。

第三张表:

当然也可以插入对象。

1 def boytogril(request):
2     boy_obj=models.Boy.objects.filter(id=5).first()
3     print(boy_obj.boyname)
4     gril_list=models.Gril.objects.filter(id__in=[3,4])
5     boy_obj.gril_set.add(*gril_list)
6     return HttpResponse('ok')

 

第三张表:

总结:

  1. 无论是正面操作,还是反面操作,其本质是一样:1:django上,是插入对象。2:数据库本质:对相应的字段进行赋值。
  2. 操作第三张表的方法都是一样的。相同的方法。add可以传入单个对象、数字、列表对象、列表数字。
  3. ManyToMany字段的表,直接操作含有ManyToMany列来操作第三张表。
  4. 不含有ManyToMany的表,直接操作django创建的虚拟列:tablename_set列来操作第三张表。注:tablename为含有ManyToMany字段的表名。在数据库中表名为django的类的名字小写!

删除操作:

删除包含remove()和clear()方法。

1 def boytogril(request):
2     boy_obj=models.Boy.objects.filter(id=5).first()
3     print(boy_obj.boyname)
4     boy_obj.gril_set.clear()
5     return HttpResponse('ok')

 

第三张表:

clear()是将所有和id=5的jack有关系的女孩,在第三张表中都删除。

remove()指定删除某个关系的列。

1 def boytogril(request):
2     boy_obj=models.Boy.objects.filter(id=1).first()
3     print(boy_obj.boyname)
4     boy_obj.gril_set.remove(1)
5     return HttpResponse('ok')

 

remove(num)指定删除id=1的tom和他有关系的id=1的女孩删除掉。

删除前:

删除后:

 同样可以给remove(*list)传列表。进行批量的删除。

1 def boytogril(request):
2     boy_obj=models.Boy.objects.filter(id=1).first()
3     print(boy_obj.boyname)
4     boy_obj.gril_set.remove(*[2,4])
5     return HttpResponse('ok')

 删除前:

 删除后:

多对多查询

 上面说过我们通过含有ManyToMany列:btog添加数据的时候,该列含有的方法中就有filter和all。我们可以通过他对第三张表进行查询。

code:

 1 def boytogril(request):
 2     gril_obj=models.Gril.objects.filter(id=2).first()
 3     res=gril_obj.btog.all()
 4     print(res)
 5     for item in res:
 6         print(item.boyname)
 7     return HttpResponse('ok')
 8 <QuerySet [<Boy: Boy object>, <Boy: Boy object>, <Boy: Boy object>]>
 9 evil
10 lili
11 luc

我可以通过这样可以直接查询,如果数据库的数据量较大,进行多次sql的查询,未免会给程序和数据库带来压力。

正向查询

在ManyToMany表中,对应的列btog其实是关系表对象:gril_btog,我们可以借助它来和表boy、gril建立关系。进行查询。由于ManyToMany字段在gril表中,我们从gril表查询叫做正向查询。

1 def boytogril(request):
2     gril_obj=models.Gril.objects.filter(id=2).values('id','gril_name','btog__boyname')
3     print(gril_obj)
4     return HttpResponse('ok')
5 <QuerySet [{'btog__boyname': 'evil', 'gril_name': 'luc2', 'id': 2}, {'btog__boyname': 'lili', 'gril_name': 'luc2', 'id': 2}, {'btog__boyname': 'luc', 'gril_name': 'luc2', 'id': 2}]>

 我们通过:btog__双下划线boyname 通过关系表gril_btog查询到boy表。进行跨2个表进行查询。

当然我们也可以在all,和filter里进行连表的查询。

1 def boytogril(request):
2     gril_obj=models.Gril.objects.filter(btog__boyname="evil")
3     for item  in gril_obj:
4         print(item.gril_name)
5     return HttpResponse('ok')
6 luc2
7 lili

 

反向查询

我们通过不含有ManyToMany的字段的表查询gril表的时候,我们叫做反向查询。

但是这时候,需要注意的是:我们通过的boy表中不是通过gril_set来进行查询。

那通过什么进行查询呢?

我们可以通过django的报错提示,来查看boy表中都有哪些字段。

通过伪造不存在的列:

1 def boytogril(request):
2     boy_obj=models.Boy.objects.filter(id=2).values('id','boyname','xxx')
3     print(boy_obj)
4     return HttpResponse('ok')

所以boy表中存在的字段是gril。我们可以通过他来进行反向查询。

1 def boytogril(request):
2     boy_obj=models.Boy.objects.filter(id=2).values('id','boyname','gril__gril_name')
3     print(boy_obj)
4     return HttpResponse('ok')
5 <QuerySet [{'id': 2, 'boyname': 'evil', 'gril__gril_name': 'luc2'}, {'id': 2, 'boyname': 'evil', 'gril__gril_name': 'lili'}]>

 

通过django 为我们构造的虚拟列gril ,通过她和关系表、gril表建立关系,进行查询。

总结:

  1. 多对多查询:是通过关系表和另一张表进行查询。
  2. 多对一查询:是通过foreign key(是另一张表的对象)来关联第二张表。
  3. 可以把多对多查询理解成:进行2次多对一的双下划线查询。
  4. 都是通过双下划线来查找另一张表。一个是直接关联到另一张表,一个是跨一张关系表进行查询另一张表。
  5. 需要注意的是:插入数据的时候,我们说boy表中有虚拟列gril_set。但是查询的时候变为gril。是不一样的。
  6. 注意:关联的列:foreignkey、ManyToMany、对应的列从django来说是另一张表或者关系表的对象。对于数据库来说,有可能该列只是存储id值 。

 update:

在多对多中,django 给咱们提供了一个更新的函数,但是这个

 

 

 

 

 

 

 

 

posted @ 2016-09-28 17:01  evil_liu  阅读(1180)  评论(0编辑  收藏  举报