现在使用的是Djago的ORM,只能在Django中使用!!其他数据库不一样

  

1、Django中的ORM

  ORM -- 对象关系映射表!!  Django中,用对象对应表,成员变量映射表的字段

  一个实例就是一个记录。。所有对表的操作就变成了对对象得出操作

  功能:1、根据对象的数据类型生成表结构,2、将对象列表转化为SQL语句!3、将sql查询的结果转化为对象,列表

2、在pycharm中配置

  django 默认的数据库是:SQLite(轻量级数据库,android 也曾用过)

  2.1、在项目的_init_.py中配置默认

## 把mysql作为默认的数据库-- 否则Django还是把SQLite作为默认数据库
import pymysql

pymysql.install_as_MySQLdb()

  2.2 、在全局配置settings中:

    注释掉原来的默认数据库,添加上SQL的用户名、密码等信息

  注释:

  

  添加内容:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'django',  # 你的数据库名称
        'USER': 'root',  # 你的数据库用户名
        'PASSWORD': '111111',  # 你的数据库密码
        'HOST': '',  # 你的数据库主机,留空默认为localhost
        'PORT': '3306',  # 你的数据库端口
    }
}

  2.3 在models中,创建表对象

 1 # Create your models here.
 2 
 3 # create table book(
 4 #     name varchar(20),
 5 #     price float(4,2)
 6 # )
 7 ## 创建表 -- 必须要继承models.Model,django才知道这个类是表
 8 ##       -- 这个表必须要有主键,没有的话,默认也会加上ID主键
 9 class Boook(models.Model):
10     name = models.CharField(max_length=20)
11     price = models.FloatField()
12     pub_time = models.DateField()
13 
14 class Author(models.Model):
15     name = models.CharField(max_length=32)

  2.3 配置完成后:

         执行:  python3 manage.py makemigrations   --  (因为我安装了py2和py3) 生成对应的表py文件   ## 用沙盒啊!笨蛋!

         再执行:python3 manage.py migrate      ----- 真正在数据库中生成表    

3、(单表)记录的增删改查:

  3.1表数据的添加:

 1 --------------- views--------------
 2 def addbook(req):
 3 # 添加一条记录的方式
 4     # 方式1:
 5     ## 1、实例化表对象
 6      b = Book(name="python基础",price=99,author="dyl",pub_time="2018-4-1")
 7     # 2、保存到数据库
 8      b.save()
 9 
10     # 方式2: 这个方式不用保存!创建就可以了
11     # data : 事件格式必须是2010-9-1,否则直接报错!!
12     Book.objects.create(name="算法导论",price=128,author="图灵",pub_time="2010-9-1")
13 
14     return HttpResponse("保存成功")

  3.2、数据的修改:

 1 def update(req):
 2     #方法1:
 3     ##先找到,把作者是图灵的所有书籍价格改为9999, QuerySet 有update对象
 4     # Book.objects.filter(author="图灵").update(price=9999) 
 5 
 6     # 修改数据集的单个数据!!
 7     # b = Book.objects.filter(author="图灵")
 8     # 
 9     # print(b)#<QuerySet [<Book: Book object (2)>]>  QuerySet数据类型
10     # # 意味着b  并不是一个对象,是一个数据集合
11     # print(type(b)) #<class 'django.db.models.query.QuerySet'>
12     #
13     # ## 取出集合中的第一个对象,就是我们想要的对象
14     # b[0].price=123
15     # b[0].save() ## 一定要保存!! ,否则无效 --- 
16 
17     ## 方法2:
18     b = Book.objects.get(author="图灵")
19     ## 取出集合中的第一个对象,就是我们想要的models对象
20     print(type(b)) #<class 'app01.models.Book'>
21     b.price=123    # 没有update方法!!models
22     b.save() ## 一定要保存!! ,否则无效
23     return HttpResponse("修改成功")

   注意的问题:

    1、使用对象.objects.filter(条件)的时候返回的是一个QuerySet数据集合,意味着数据不止一个!!

    2、get方法返回的是一个models对象,它没有update方法,只能使用:对象.save()

    3、我们推荐使用的是update方法,因为save方法,会把所有数据重新全部写一遍,效率很低!!

  3.3、删除记录

1 def delete(req):
2     Book.objects.filter(author="dyl").delete()
3     return HttpResponse("删除成功")

   3.4、查询记录

# 查询相关API:

#  <1>filter(**kwargs):      它包含了与所给筛选条件相匹配的对象

#  <2>all():                 查询所有结果

#  <3>get(**kwargs):         返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。

#-----------下面的方法都是对查询的结果再进行处理:比如 objects.filter.values()--------

#  <4>values(*field):        返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 model的实例化对象,而是一个可迭代的字典序列
                                     
#  <5>exclude(**kwargs):     它包含了与所给筛选条件不匹配的对象

#  <6>order_by(*field):      对查询结果排序

#  <7>reverse():             对查询结果反向排序

#  <8>distinct():            从返回结果中剔除重复纪录,但是主键相同,才是同一本书!!所以主要的用途是筛选相同的字段!!

#  <9>values_list(*field):   它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列

#  <10>count():              返回数据库中匹配查询(QuerySet)的对象数量。

# <11>first():               返回第一条记录

# <12>last():                返回最后一条记录

#  <13>exists():             如果QuerySet包含数据,就返回True,否则返回False。

   实例:

 1 def select(req):
 2     #1、取出所有数据
 3     # BooKList = Book.objects.all()
 4     # print(BooKList[0]) ##得到Qquery集合,里面是对象 ---<QuerySet [ <Book: Book object>,<Book: Book object> ....] >
 5     
 6     #2、取出前3条数据-- 切片 -- 跟python一毛一样!!
 7     BooKList = Book.objects.all()[:3] 
 8 
 9     #3、取第一个或者最后一个,可以用切片实现
10     # BooKList = Book.objects.last()
11     # BooKList = Book.objects.first()
12 
13     #4、get 只能取出一条结果,才不会报错 --  若是得到多条,或者不存在都会报错!!慎用!
14     # BooKList = Book.objects.get(id=1) ## 成功时,直接得到Book对象
15 
16     #5、只取某个条件下的结果vaues -- 作者是图灵的书名!!
17     ret = Book.objects.filter(author="图灵").values("name")
18     print(ret) ##输出:  得到一个字典   <QuerySet [{'name': '算法导论'}, {'name': '数据结构'}]>
19 
20     # 6、只取某个条件下的结果values_list -- 作者是图灵的书名!!
21     ret2 = Book.objects.filter(author="图灵").values_list("name")
22     print(ret2) ##输出:  得到一个元祖 <QuerySet [('算法导论',), ('数据结构',)]>
23 
24     # 7、查询出除条件以外的书籍
25     ret3 = Book.objects.exclude(author="图灵").values()
26     ret4 = Book.objects.exclude(author="图灵")
27     print(ret4)## 输出:<QuerySet [<Book: GO>, <Book: 骆驼样子>, <Book: 悲惨世界>]>
28 
29 
30     #8、筛选或者过滤出的结果,去掉重复的数据
31     ret5 = Book.objects.all().values("name").distinct()
32     print('ret5 == ',ret5)
33     for i in ret5:
34         print(i)
35     return render(req,"index.html",{"BooKList":BooKList})

  3.5 模糊查询--万能的双下划线 ,单表、多表都适用

##1、书本价格大于50
    BooKList = Book.objects.filter(price__gt=50).values('name','price')
    BooKList = Book.objects.filter(name__icontains='g').values('name','price')


#---------------了不起的双下划线(__)之单表条件查询----------------

#    models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值
#
#    models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据
#    models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in
#
#    models.Tb1.objects.filter(name__contains="ven")
#    models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
#
#    models.Tb1.objects.filter(id__range=[1, 2])   # 范围bettwen and
#
#    startswith,istartswith, endswith, iendswith,

4、多表查询--一对多

 

  4.1 添加外键,产生主表和从表的关系

    a、在创建表的时候,就添加外键

       外键都是,建在多的那一方!!(这里出版社可以出版多本书,这里外键建在书的表中!)

 1 class Book(models.Model):
 2     name=models.CharField(max_length=20)
 3     price=models.IntegerField()
 4     pub_date=models.DateField()
 5     publish=models.ForeignKey("Publish",models.DO_NOTHING)#外键,这里的第二个参数!!不知道是啥??
 6                                     #这个外键加上以后,publish字段变成了public_id字段!!      
                                     #Django会把publish外键关联到从表的主键上,publish变成了publish_id--- 不要手残加id!! ^-^        8 def __str__(self): 9 return self.name 10 11 class Publish(models.Model): 12 name=models.CharField(max_length=32) 13 city=models.CharField(max_length=32) 14 15 def __str__(self): 16 return self.name

    

 

 

  b、其他方式添加:

    

  4.2 添加一个包含外键的记录

## 方法1、添加包含外键的记录
def addbook(req):
    # 方法1: publish_id数据库的字段值
    # Book.objects.create(name="算法导论",price=88,pub_date="2018-8-8",publish_id=1)#表的外键字段!!

    #方法2:
    # 添加从表出版社对象给主表
    public_obj = Publish.objects.filter(name="人民出版社")[0]
    Book.objects.create(name="Django",price=23,pub_date="2018-8-8",publish=public_obj) ## 从表对象
    return HttpResponse("OKOK")

  4.3 正向查询 -基于对象

    直接通过主表外键关系,拿到从表的数据!

1     # 查数据的出版社信息!
2
# 1对多的关系,查询到的结果是一个对象!!! 3 # 主表找从表的数据! 4 # 获得书名python的信息-- 若是有两本书为python,报错! 5 book_obj = Book.objects.get(name="python")# get只能获得1个对象,否则报错!!! 6 print(book_obj.name) 7 print(book_obj.pub_date) 8 print(book_obj.publish.city) ## 直接. 查到数据 9 print(book_obj.publish.name)

  4.4 反向查询-基于对象

     从表通过主键反向查询主表的数据!!

 1 ## 3、反向查询
 2     # 人民出版社,出版的所有书籍
 3     # 写法1:
 4     pub_obj = Book.objects.filter(publish=1)  ## 不适用!
 5     print(pub_obj)
 6 
 7     # 写法2: 比较复杂
 8     # 在Publish表中取出一个出版社对象!!一个!!
 9     pub_obj = Publish.objects.filter(name="人民出版社")[0]
10     #在Book表中过滤出与出版社对象相同的数据
11     ret = Book.objects.filter(publish=pub_obj).values("name","price")
12     print(ret)
13 
14     ##写法3: ---- 推荐使用!!
15     # 从表 找主表的数据
16     ## 1、拿到出版社对象
17     pub_obj = Publish.objects.filter(name="人民出版社")[0]
18     # 2、出版社对象.book_set.all 反向拿到所有=出版社对象的书籍
19     #    从表对象.主表名_set.all  通过外键,反向拿到主表的数据 ## 这个名字可以改!!
20     print(pub_obj.book_set.all())#<QuerySet [<Book: 算法导论>, <Book: 数据结构>]> ##related_name
21   print(type(pub_obj.book_set))

   4.5 查询记录-- 双下划线查找

 1 ##1、查找人民出版出的书
 2     ## 分析:结果在主表,条件在从表
 3     ## 正向查找:
 4     set = Book.objects.filter(publish__name="人民出版社") ##最简单!
 5     print(set)
 6 
 7     #2、查询pyhton的出版社
 8     # 分析:最终是从表  条件在主表
 9     ## 反向查找:
10     p1 = Publish.objects.filter(book__name="python").values("name")
11     print(p1)
12 
13     #另外一种写法
14     p2 =Book.objects.filter(name='python').values("publish__name")
15     print(p2)
16 
17 
18     ##在北京的出版社,出版的所有书?
19     p3 = Book.objects.filter(publish__city="北京").values('name',"publish__name")
20     print(p3)
21 
22     ##2018年初过多少本书?
23     ret4 = Book.objects.filter(pub_date__lt="2018-7-1",pub_date__gt="2018-01-01").values("name")
24     print(ret4)
25     return HttpResponse("OKOK")

5、多对多

  5、1自动生成第三张表

  通过第三个表(Django自动创建,写上多对多),这个表处理自己的主键外,另外两个字段是另外两个表的主键:

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

第三张表:

  这个表虽然真实存在在数据库,但是我们不能通过ORM操作它。。。只能通过对象!!

  但是,但是,我们这个表自家创建的情况下,就可以用ORM的方法,去操作了!!

  5.1.1 写入多对多的记录

 1 ## 1、添加多对多的记录--只能通过对象
 2     # 一本书有三个作者
 3     book_obj = Book.objects.get(id=4)
 4 
 5     # author_obj = Author.objects.get(id=1) # 取一个作者
 6     # book_obj.authors.add(author_obj) #添加
 7 
 8     author_obj = Author.objects.all()##取出3个作者信息
 9     book_obj.authors.add(*author_obj)## 把作者信息放到这本书的关系中,加*号
10 
11  #2、删除记录-- 多对多关系
12     # book_obj.authors.remove(*author_obj)#移除多对多的关系,移除一条同理!
13     # book_obj.authors.remove(id =1)  ## 移除表中第一条多对多的关系

  #3、查询
  
ret2 = Book.objects.filter(authors__name="alex").values("name","price") ##因为Book表中有外键这个字段,所有可以这样查!
  print(ret2)

  5.2手动创建第三张表

    先去掉   ManyToManyField,

    再手动创建之后就可以用ORM的方法,添加记录

1 ## 手动创建第三张表
2 class Book_Author(models.Model):
3     book = models.ForeignKey("Book",models.DO_NOTHING)
4     author=models.ForeignKey("Author",models.DO_NOTHING)

    再执行 python3 manage.py makemigrations 和   python3 manage.py migrate 重新生成表!!

    

 1 ## 给手动创建的表添加记录
 2     Book_Author.objects.create(book_id=2,author_id=3)
 3 
 4 #1、 对象查询
 5 #     obj = Book.objects.get(id=2)
 6 #     print(obj.book_author_set.all()[0].author)
 7 
 8 #2、使用__查询
 9     # alex 出的书籍名称和价格
10     # book_author:是表名,第三张表
11     #book_author__author:关联的作者表
12     #book_author__author__name:作者的名字
13 
14     ret = Book.objects.filter(book_author__author__name="alex").values("name","price")## 因为没有关联字段(外键),只能通过第三张表,这样查询数据
15     print(ret)

 

 

 

主要是有点乱!作为补充 

 ##########################################################################################################################################

首先创建3张表:

 1 # Create your models here.
 2 # 1、班级表
 3 class Classes(models.Model):
 4     title = models.CharField(max_length=32)
 5     m = models.ManyToManyField("Teachers")  # 自动创建第三张表
 6 
 7 
 8 # 2、老师表
 9 class Teachers(models.Model):
10     name = models.CharField(max_length=32)
11 
12 ## 3、学生表
13 class Student(models.Model):
14     username = models.CharField(max_length=32)
15     age = models.IntegerField()
16     gender = models.BooleanField()  ##男或者女
17     cs = models.ForeignKey("Classes",related_name='s')  ## 外键约束,cs_id列名 ,cs本身是代表Classes类的一个对象!!!!
18    ## 可以将student_set的名字改为其他,通过 related_name

1、单表操作

 1 ## 1、添加记录的方式
 2     #1、直接写入数据,等同于下面两句话
 3 Teachers.objects.create(name="周老师")
 4     #2、创建对象在保存数据!!
 5 obj = Teachers(name='周老师')
 6 obj.save() # 必须保存
 7 
 8 ## 2、删除数据
 9 Teachers.objects.filter(id=1).delete()
10 
11 ## 3、改变数据
12     # 1、更新所有数据
13 Teachers.objects.all().update(name='大傻子')
14     #2、更新一个数据
15 Teachers.objects.filter(id=1).update(name='大傻子2')
16 
17 #4、查询数据
18 Teachers.objects.filter(id=1,name='周老师')
19     ## 神器的双下划线!!? 
20 Teachers.objects.filter(id__gt=1)  ## id大于1
21 Teachers.objects.filter(id__gt=1).first()  ## id大于1,只取第一个

2、一对多跨表操作

 1 # 一对多表 !!! -- 跨表查询,外键条件
 2 # 这个外键代表的是,约束表的一个对象,通过这个外键才能做跨表查询!!!
 3 # 自身表这个外键在数据库的真实字段名是:外键名_id
 4 # 1、增加数据-- 要么增加一个外键关联的对象,要么是外键名_id
 5 Student.objects.create(username='大傻子', age=12, gender='', cs_id=1)  ##cs_id列名!! 关键
 6 Student.objects.create(username='大傻子', age=12, gender='', cs=Classes.objects.filter(id=1).first())  ##cs 对象!! 关键
 7 
 8 # 取出全部数据
 9 # 但凡是all或者filter都是一个QuerySet集合,集合里面全部是对象!!
10 # 2、查找数据- 跨表查询l
11 ret = Student.objects.all()
12 for i in ret:  ## 遍历QuerySet集合,用点!!!!!! 在filter中,跨表查询用双下划线!!
13     print(i.username)
14     print(i.age)
15     print(i.gender)
16     print(i.cs_id)  ##一个数  对应表的一个橘绿
17     print(i.cs.id)  # 一个对象.id!!!
18     print(i.cs.title)  # 一个对象.title!!!
19 
20 # 3、删除数据
21 Student.objects.filter(id= 1).delete()   ## 删除id=1 的学生
22 Student.objects.filter(cs_id=1).delete()  ## 把三班的人全部删除
23 
24 
25 # 样例:
26 # 方法1: 输入班级的id,删除对应的学生
27 # cid = input("请输入班级的id")
28 # Student.objects.filter(id=cid).delete()
29 #
30 # # 方法2:输入班级的名称,删除对应的学生
31 # sid = input('请输入班级的名称')
32 # Student.objects.filter(cs__name=sid).delete()  ##若是filter做跨表查询,就一定要用双下划线!!规定!!若是遍历!!
33 # Student.objects.filter(cs=Classes.objects.filter(title=sid)).delete()

 

3、多对多的跨表操作

 1 ## 多对多的操作
 2 '''
 3 班级:
 4 id  title
 5 1    1班
 6 老师:
 7 id   title
 8 1    abc
 9 
10 mmanytomany:不会生成一个字段!! 生成多对多的表,字段为两个表的id
11 
12 多对多的表:
13  id   班级id   老师id
14 
15 
16 ## 这个第三张表,不能直接操作!!,只能间接操作,只能通过manytomany那个字段操作!!
17 '''
18 ## 操作第三张表
19 obj = Classes.objects.filter(id=1).first()  ##取出id=1 的对象
20 
21 ## 1、添加
22 obj.m.add(2)  ## obj.m 表示第三张表 obj.m.add: 表示在第三张表添加一条记录
23 ## 执行完成,就是第三张表  班级id=1  老师id=2
24 
25 # 同时加多个
26 obj.m.add([3, 4, 5])  ##班级id=1  老师id=[3,4,5] 一个班安排3个老师!!
27 
28 ## 2、删除
29 obj.m.remove([3, 4])  ##删除班级id=1的老师id为3、4的老师
30 obj.m.clear()  ##班级id=1 的所有老师,全部删除!!
31 
32 obj.m.set([1, 2, 3])  ##班级id=1 的老师,更新为id为1、2、3的老师; 原来存在老师被清除
33 
34 ##3、查找 某个班级的所有老师
35 ## 相当于join,联表查询!!!
36 obj = Classes.objects.filter(id=1).first()
37 ret = obj.m.all()  ## obj.m:第三张表,把全部取出来,得到的老师的对象集合!!
38 ## manytomany 关联的是老师 ret=<QuerySet[obj().....]> ##
39 
40 
41 # 总结:
42 1、ORM中,类代表数据库的一张表,对象代表一条记录
43 2、FK字段,代表关联表的一行数据(类的对象)
44 3、manytomany,自动生成第三张表,依赖关联表对第三张表进行操作!!
45 4、正向查询: 通过__(双下划线跨表查询)--- 有外键关系
46 5、反向查询: 通过  --小写类名_set---   (正向反向,也是通过外键的关系的,隐约)-- 无外键  但是,这个小写类名_set可以更改!!

 

 4、取出数据的类型

 1 # 取出的数据一种是集合、一种是字典、一种是元祖 ,都是QuerySet
 2 
 3 # 实例: 所有学生以及所在的班级
 4 # 1、
 5 obj_list = Student.objects.all() ## 等价于 select * from Student 这个集合 [obj,obj,obj]
 6 for row in obj_list:
 7     row.username, row.cs_id, row.cs.title  ## 里面是对象
 8 # 2、
 9 stu_list = Student.objects.all().values("id","username") ##v alues()表示要取某些字段
10 ## values():# 里面是字典!! [{'id':1 ,'username':'xx'}]
11 
12 # 3、
13 stu_list = Student.objects.all().values_list()
14 ## [(1,'root')]  #里面是元祖
15 
16 # 取出姓名,以及所在的班级
17 stu_list = Student.objects.all().values("username","cs__name")
18 for row in stu_list:
19     print(row['username'],row['cs__name '])

5、理论上的正向查询和反向查询

 1 ##########################重点的重点!!!#####################################
 2 
 3 ## 拿到3班的学生
 4 ## 1、正向查找
 5     ret = Student.objects.filter(cs__title='2班') ## 拿到对象__ 正向跨表     正向跨表和模糊查询用双下划线!! 反向查询用:没有外键的表名_set
 6     print(ret)
 7 
 8 ## 2、反向查找 -- 反向跨表
 9     # student有个外键class,class直接拿不到student,但是可以通过隐藏的student_set方法@@!!反向
10     obj =Classes .objects.filter(title='2班').first()
11     print(obj.id)
12     print(obj.title)
13     ##小写的类名_set,也可以related_name='s' ,改变student_set = s
14     # print(obj.student_set.all()) ## 拿到反向的queryset的对象!!!! 等价于上面那个!!
15     print(obj.s.all()) ## 改成了s 等价于上面这个一句!!
16 
17 
18     ret = Classes.objects.all().values('id','title')
19     print(ret)
20     ret = Classes.objects.all().values('id','title','s') ## s是隐藏字段, student_set
21     ## 就相当于sql里面join,谁在前面,谁是主表!!
22     print(ret)
23 
24 ##
25     Student.objects.all().values('username','cs__title') #Student 主表
26     Classes.objects.all().values('title','s__username')  #Classes 主表

 
posted on 2018-05-07 21:08  虫子小孩  阅读(1078)  评论(0编辑  收藏  举报