zoukankan      html  css  js  c++  java
  • day 69 orm操作之表关系,多对多,多对一(wusir总结官网的API)

     对象  关系  模型

     wusir博客地址orm官网API总结

     django官网orm-API

    orm概要:

    ORM 跨表查询
        class Book(models.Model):    
            title = models.CharField( max_length=32)
            
            publish=models.ForeignKey(to="Publish",to_field="id")
            authors=models.ManyToManyField(to='Author',related_name='bookList') 
            
        class Publish(models.Model):
            name=models.CharField( max_length=32)
            
     
        class Author(models.Model):
            name=models.CharField( max_length=32)
            ad=models.OneToOneField("AuthorDetail")
     
        class AuthorDetail(models.Model):
            
            telephone=models.BigIntegerField()
          
    
        基于对象查询(sql:子查询)
        
        
              一对多的关系  (Publish--Book)
                      正向查询,按字段:
                      
                      查询python这本书的出版社所在的名称
                      book_obj=Book.objects.filter(title="python").first()
                      #print(book_obj.publish.name)
                      
                      反向查询,按表名小写_set:
                      
                      人民出版社出版过的所有书籍名称
                      
                      publish_obj=Publish.objects.filter(name="人民出版社出版").first()
                      print(publish_obj.book_set.all())  
                      for obj in publish_obj.book_set.all():
                           print(obj.title)
                                    
              
              多对多的关系
                    正向查询,按字段:
                        python这本书所有作者的名字
                            book_obj=Book.objects.filter(title="python").first()
                            book_obj.authors.all()
                        
                    反向查询,按表名小写_set:
                        alex出版过的所有书籍名称
                        alex=Author.objects.filter(name="alex").first()
                        alex.bookList.all()
                    
              一对一的关系
                    正向查询,按字段:
                        查询alex的手机号
                        alex=Author.objects.filter(name="alex").first()
                        alex.ad.telephone
                        
                    反向查询:按表名小写
                        以151开头的手机号的作者的名字
                        ad=AuthorDetail.objects.get(telephone__startswith="151")
                        ad.author.name        
        
        
        基于Queryset和 __(sql:join语句):
              
              正向查询,按字段
              反向查询,按表名小写
              
              一对多的关系  (Publish--Book)
                      
                      
                      查询python这本书的所在出版社的名称
                      Book.objects.filter(title="python").values("publish__name")
                      for obj in Book.objects.filter(title="python"):
                          temp={}
                          temp["publish__name"]=obj.publish.name
                          
                      人民出版社出版过的所有书籍名称          
                      Publish.objects.filter(name="人民出版社出版").values("book__title")
                      
                                    
              
              多对多的关系
                    
                        python这本书所有作者的名字
                            Book.objects.filter(title="python").values("authors__name")
                            
                   
                        alex出版过的所有书籍名称
                            Author.objects.filter(name="alex").values("book__title")
                            
                    
              一对一的关系
                    
                        查询alex的手机号
                            Author.objects.filter(name="alex").values("ad__telephone")
                                
                        以151开头的手机号的作者的名字
                        AuthorDetail.objects.filter(telephone__startswith="151").values("author__name")
                        
        
             扩展:
                    练习1:
                    查询python这本书的所在出版社的名称
                    Book.objects.filter(title="python").values("publish__name")             
                    Publish.objects.filter(book__title="python").values("name")
                    
                    练习2:
                    手机号以151开头的作者出版过的所有书籍名称以及出版社名称
        
                    Book.objects.filter(authors__ad__telephone__startswith="151").values("title","publish__name")
                    
                    
                
        分组查询:
        
                查询每一个出版社出版过的书籍个数
                
                Publish.objects.annotate(Count("book__id"))
                
            
                select count(*) from publish  group by id 
                
    
     SELECT 
     
         "app01_publish"."name", COUNT("app01_book"."id") AS "c" 
         
         FROM "app01_publish" LEFT OUTER JOIN "app01_book" ON ("app01_publish"."id" = "app01_book"."publish_id") 
         
         GROUP BY "app01_publish"."id", "app01_publish"."name" 
    
    
                      publish:                         book:
                      
                      id   name                         id       title    publish_id
                      1     A                            1       python        1
                      2     B                            2       go            1
                      3     C                             3       linux         2
                                                         4       php           3
                                                         5       java          3
                                                         
                                                         
            publish-book:
                    
            nid        publish_id  publish_name     book_id book_title  publish_id
              1          1            A              1       python        1
              2          1            A                2       go            1
              3          2            B              3       linux         2
              4          3            C              4       php           3
              5          3            C              5       java          3
        
    View Code

    多对一/一对多,

    多对多{类中的定义方法}

    三种方式建表

    day69
    
    1. 昨日内容回顾
    
        1. 单表增删改查
        2. 单表查询API
            返回QuerySet对象的:
                1. .all()
                2. .filter()
                3. .values()
                4. .values_list()
                5. .exclude()
                6. .order_by()
                7. .reverse()
                8. .distinct()
            
            返回单个数据对象:
                1. .first()
                2. .last()
                3. .get()
                
            返回布尔值的:
                1. .exists()
            返回数字的:
                1. .count()
                
        3. 神奇的双下划线:
            配合filter()来做各种查询。
                1. id__gt=1
                2. id__lt=3
                3. id__in=[1,2,3]
                4. id__range=[1,5]
                
                5. name__contains="s"
                6. name__icontains="s"
                7. name__startwith="a"
                8. name__endswith="x"
                
                9. first_day__year="2018"
                
                10. cname__isnull=True *!
                
                
        4. Django日志配置
    
    2. 今日内容
        表之间的关系
        
        1. 一对多
        2. 一对一
        如下所示:
        class Student(model,Model):
        sname = models.CharField(max_length=23,verbose_name='学生姓名)
        the_class=models.ForeignKEy(to=Class,to_field='id',
        on_delete=models.CASCADE, related_name='students')
        detail = models.OneToOneField(to='StudentDetail', null=True)
        
        
        class StudentDetail(models.Model):
        hetght=models.PositiveIntegerField()
        weitht=models.PositiveIntegerField()
        email=models.EmailField()
        
            对应关系:
                类           -->        表
                类的属性     -->        字段
                实例对象     -->        一条数据(数据行)
    
    
                
            数据库层面:
                外键 对应 另外一个表的一条记录
                cid_id
            ORM层面:
                外键对应 另外一个表的一个对象
                student_obj.cid_id  --> 具体的值
                
                为什么? Django把关系包装成一个具体的对象
                cid  
            正向查找:
    student_obj=models.Student.objects.first()        
    student_obj.detail.email
            反向查找:
                默认是表名_set.all()
                detail_obj=models.StudentDetail.objects.get(id=1)
                detail_obj.student.sname
                如果在外键的字段中加了related_name属性,则按照该属性的值来反向查找
                
            
        3. 多对多
            老师 和 班级
            
            通过第三张表关联
            
            Teacher表
            id   tname
            
            1    Alex
            2    Egon
            3    yuan
            
            
            Class表
            
            id   cname
            1    1班
            2    2班
            3    3班
            
            
            TeacherToClass
            
            id   teacher_id     class_id
            1    1              1
            2    1              2
            3    1              3
            4    2              1
            5    2              3
            6    1              1
            
            
            
            
            多对多三种方式创建表格:
            
            第一种:(没有使用到ManyToMany的格式去创建,使用不到它内部封装好的一些便捷用法,但是可扩展性强便于理解)
            class Course(models.Model):
            id=models.AutoField(primary_key=True)  # 主键
            cname=models.CharField(max_length=20)  # 班级名称
            first_day=models.DateField()  # 开班时间
            
            class Teacher(models.Model):
            tname=models.CharField(max_length=20)
            
            # 自定义三张表格,通过外键去关联上面两张表格
            class Teacher2Class(models.Model):
            teacher=models.ForeignKey(to='Teacher)
            the_class=models.ForeignKey(to='Course')
            
            class Meta:  # 这里是指定我们的表格里面的这两个字段不可以有重复的,不可以同时出现重复,也就是我们说的联合主键
            unique_together=("teacher", 'the_class')
            
            第二种方式:(我们这里只是定义了两个类,course和teacher,没有定义第三个类,但是我们运行程序的时候系统会自动给我们生成第三张表格出来用于建立我们的 多对多的关系,但是注意了,我们上面提到了我们并没有建立第三张表格,它系统给我们生成的,我们不能够对这个自动生成的表格进行操作,这就是不够遍历的地方,优势当然是我们在不适用第三张表格的前提下,另外两张表格的操作会更加便捷)
            通过manyToManyField去创建
            class  Course(models.Model):
            id=models.AutoField(primary_key=True)
            cname=models.CharField(max_length=20)
            first_day=models.DateField()
            
            class Teacher(models.Model):
            tname=models.CharFirld(max_length=30)
            cid=models.ManyToManyField(to='Course,relate_name='teachers)
            
            
            第三种方式:(优劣自己体会)
            通过外键和ManyToManyField创建
            class Course(models.Model):
            id=models.AutoField(primary_key=True)
            cname=models.CharField(max_length=30)
            first_day=models.DateField()
            
            class Teacher(models.Model):
            tname=models.CharField(max_length=40)
            # 通过manyToManyField和手动去创建第三张表格
            cid=models.ManyToManyField(to='Class',through='Teacher2Class',through_fields=('teacher', 'the_class'))
            
            class Teacher2Class(models.Model):
            teacher=models.ForeignKey(to='Teacher')
            the_class=models.ForeignKey(to='Course')
            
            class Meta:  # 建立联合主键
            unique_together=('teacher', 'the_class')
            
            多对多操作
            正向查询(从老师表格查询班级表格)
            teacher_obj=models.Teacher.objects.first()
            teacher_obj.cid.all()  # 查询该老师授课的所有班级
            
            反向查询(由班级表格反向查询老师表格)
            class_obj=models.Course.objects.first()
            class_obj.teachers.all()  # 此处用到的是related_name,如果不设置的话就用默认的表名_set
            
            常用方法:
            create()
            创建一个新的对象,保存对象,并将它添加到关联对象集中,返回新创建的对象
            import datetime
            teacher_obj.cid.create(cname='num9_class',first_day=datetime.datetime.now())
            
            add()
            把指定的models对象添加到关联对象集中
            添加对象
            class_obj=models.Course.objects.filter(id__lt=3)
            models.Teacher.objects.first().cid.add(*class_obj)
            
            添加id
            models.Teacher.objects.first().cid.add(*[2,3,5])
            
            set()
            更新model对象的关联对象
            teacher_obj=models.Teacher.objects.first()
            teacher_obj.cid.set([2,3,4])
            
            remove()
            从关联对象集中移除执行的model对象
            teacher_obj=models.Teacher.objects.first()
            teacher_obj.cid.remove(3)
            
            clear()
            从关联对象集中移除一切对象
            teacher_obj=models.Teacher.objects.first()
            teacher_obj.cid.clear()
            
        
        4. 了不起的双下划线:
            找学生名字里面带龙字的班级
            sname__contains=""
            models.Class.objects.filter(students__sname__contains="")
            双下划线表示跨表
                    
        
        
    3. 今天作业
        1. 今天上课的例子要写完,博客整理好
        
    
        2. 自己设计图书管理系统的表结构,用咱们今天上课学到的内容,做查询的练习
        
        书和作者    多对多
        书和出版社  多对一
        
        使用双下划线练习跨表查询
        
    
        
        
        
        
        
        
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
            
            
            
            
            
                
                
                
                
        
    View Code

    中介模型第三种方式,两头都占上:

    class Author(models.Model):
         name=...
         
         
         
    class Book(models.Model):
         title=...
         authors=models.ManyToManyField("Author")
    
    
    author
    
    
    id   name
    1    alex
    2    egon
    3    wu
    
    
    book 
    
    id   title
    1    linux     
    2    python
        
    book_authors
    
    
    id   book_id    author_id
    
    1      2            1
    2      2            2
    3      2            3
    
    
     
    book_obj=Book.objects.create(title="python")    
    book_obj.authors.all()  # 与这本书关联的所有作者对象集合
    
    alex=models.Author.get(name="alex")
    egon=models.Author.get(name="egon")
    wu=models.Author.get(name="wu")
    
    author_list=models.Author.objects.all()
    book_obj.authors.add(*[alex,wu,egon])
    book_obj.authors.add(*author_list)
    book_obj.authors.remove(alex)
    book_obj.authors.clear()
    book_obj.authors.set()
    
    ######################################################
    
    
    中介模型:
    
    
    
    class Student(models.Model):
          name=...
          courses=models.ManyToManyField("Course",through="Student2Course")
          
    class Course(models.Model):
          name=...
          
    class Student2Course(models.Model):
          student=models.ForeignKey("Student")
          course=models.ForeignKey("Course")
          score=models.IntegerField()
    
    扩展关系表:
     
        teacher
        
        course
        
        student
        
        
        score
        
        
        id     student_id    course_id     score
         1        1             1            90
         2        1             2            80
         3        2             1            80
         4        1             3    
    
    注意事项:
    
        失效: 
        alex=Student.objects.get(name="alex")
        yuwen=.....
        alex.courses.add(yuwen)
        how:
           Student2Course.objects.create(student_id=1,course_id=3,score=100)
    View Code

    代码级别实现:

    from django.db import models
    
    # Create your models here.
    
    一对一关系:
    
    class Class(models.Model):
        id = models.AutoField(primary_key=True)
        cname = models.CharField(max_length=32, null=True)
        first_day = models.DateField()
    
        def __str__(self):
            return self.cname
    
    
    class Student(models.Model):
        id = models.AutoField(primary_key=True)
        sname = models.CharField(max_length=32)
    
        cid = models.ForeignKey(to="Class", to_field="id", related_name="students")  # 表里面:student_obj.cid_id=Class对象.id ;  student_obj.cid=Class对象
        # detail = models.ForeignKey(to="StudentDetail", unique=True)
        detail = models.OneToOneField("StudentDetail", null=True)
    
    
        def __str__(self):
            return self.sname
    
    
    class StudentDetail(models.Model):
        # id = models.AutoField(primary_key=True)
        # 正小整数
        height = models.PositiveSmallIntegerField()
        email = models.EmailField()
        memo = models.CharField(max_length=128, null=True)
    
    
    ==================================================================================
    
    # 多对多
    # 第一种
    # 不能用Django  ORM 多对多操作的语法
    # class Teacher(models.Model):
    #     tname = models.CharField(max_length=32)
    #
    #
    # class TeacherToClass(models.Model):
    #     tid = models.ForeignKey(to="Teacher")
    #     cid = models.ForeignKey(to="Class")
    #
    #     class Meta:
    #         unique_together = ("tid", "cid")
    
    # 第二种
    # 自动创建的第三张表,我没有类和它对应,也就是我不能通过ORM单独操作第三张表
    class Teacher(models.Model):
        tname = models.CharField(max_length=32)
        cid = models.ManyToManyField("Class", null=False)
    
    
    # 第三种
    # class Teacher(models.Model):
    #     tname = models.CharField(max_length=32)
    #     cid = models.ManyToManyField(to="Class", through="TeacherToClass", through_fields=("tid", "cid"))
    #
    #
    # class TeacherToClass(models.Model):
    #     tid = models.ForeignKey(to="Teacher")
    #     cid = models.ForeignKey(to="Class")
    #
    #     class Meta:
    #         unique_together = ("tid", "cid")

    注意的点是我们在关联外键的时候可以直接指定表名即可,不用写上to,然后如果不指定字段的话orm会自动给我们关联到那个表格的id字段上,然后我们建立表格的时候如果不写id字段,不写主键的话,orm会自动给我们生成一个id字段并且自动指定i自动生成的这个id字段为主键

    如果设置了related_name="students",反向查询时可直接使用students进行反向查询。

    我们的related_name就是相当于我们的url路由设置里面的反向解析的原理,我们在查询数据的时候会用到这个功能,在反向解析里面我们直接使用别名就可以倒推出我们的url地址配置,

    在表格关联外键的场景里面也是一样的,我们在查询的时候,通过一个表格去查他的外键的关联表格,

    比如我关联你,那么我查询你的时候就是正向查询,而你查询我的话就属于反向查询,在反向查询里面我们就需要使用到了我们自定义的那个related_name值

    那么我们的related_name放到哪里呢,

    我们的A表格需要关联到B表格的一个字段作为外键,那么我们的related_name参数就放到我们的A表格的需要建立外键的那个字段里面,作为一个参数,以=赋值的形式放进去,要赋值给一个变量,用引号引起来的变量名,如下:

    class Student(models.Modes):
    sname=models.CharField(max_length=20,verbose_name='学生姓名')
    the_class=models.ForeignKey(to=Class, to_field='id', on_delete=models.CASCADE,
    related_name='students') detail=models.OneToOneField(to='StudnetDetail',null=True) class StudentDetail(models.Model): height=models.PositiveIntegerField() weight=models.PositiveIntegerField() email=models.EmailField()

    这里我们来针对一对多的具体事例进行一点解析:

    <table border="1">
        <thead>
        <tr>
            <th>#</th>
            <th>ID</th>
            <th>学生姓名</th>
            <th>所在班级</th>
            <th>操作</th>
        </tr>
        </thead>
        <tbody>
        {% for student in student_list %}
            <tr>
            <td>{{ forloop.counter }}</td>
            <td>{{ student.id }}</td>
            <td>{{ student.sname }}</td>
            <td>{{ student.cid.cname }}</td>
    {# 我们这里的student.cid.cname它的场景是我们在student表格里面建立了一个外键cid用它去关联我们的class表格里面的id字段#}
    (# 我们这样写就是通过我student的这个外键的设置去找到了我们的class表格里面的cname字段并取到它的值,#)
    {# 我们之所以可以这样操作是基于我们的orm里面的语法,通过类去创建表格然后根据类的属性去创建表格里面的字段,使用了面相对象编程的方式,极大地减少了代码的冗余#}
    {# 我们的对应关系是 类---表 ;类的属性----字段 ; 实例化的对象---表格里面的一条数据行;#}
    <td> <a href="{% url 'delete_student' student.id %}">删除</a> {# <a href="{% url 'edit_class' %}?class_id={{ class.id }}">编辑</a>#} <a href="{% url 'edit_student' student.id %}">编辑</a> </td> </tr> {% endfor %} </tbody> </table>

    上面是前端部分,我们再来看看我们的后端代码是如何实现的,与之对应上,

    def student_list(request):

      student_list=models.Student.objects.all()

      return render(request, 'student_list.html',{"student_list": student_list}

    具体解析部分:

    这里的student是一个类,student_list是一个queryset(查询结果的集合,里面存储了一个或者多个对象),{%for student in student_list %}是从一个queryset中循环取出每个对象

    student.cid是取出这一个对象的属性,(也就是类的属性,对应这个数据库中的这个表的字段,请参考上面注释部分的对应关系,),而此时这个cid是一个外键,对应着class那个类[也就是class那个表格]的id(数据库的id字段)对象,所以可以直接通过student.cid.cname去取出class表中对应的那一行数据的cname字段的值,

    也就是说我们通过我们自己的表格的名字[student]加上.关联外键的字段名[cid]加上.想要查询的外键表格里面的字段[cname...]就可以实现我们在本表格里面去查找我们所关联外键的那个表格里面的字段.{这就有点类似于死记硬背了,固定格式,.....尽力去理解吧}

    一对一

    正向查询

    student_obj=models.Student.objects.first()

    student_obj.detail.email

    反向查询:

    detail_obj=models.StudentDetail.objects.get(id=2)

    detail_obj.student.sname  # 我们一对一的时候反向查询只需要用得到对象.表名就可以拿到我们的结果了

    多对多操作

    正向查询

    teacher_obj=models.Teacher.objects.first()

    teacher_obj.cid.all()

    反向查询

    class_obj=models.Class.objects.first()

    class_obj.teachers.all()  # 此处我们设置了related_name,我们的related_name值是teachers,如果我们没有设置它的话就是用使用我们的表格名字Teacher_set.all()去取到所有的值

    我们在这里把正向和反向总结一下,我们的一对一关系里面,和一对多的关系里面,要理清一个概念就是我们的关系里面谁要关联谁,这个是关键点,理清了之后我们建立表格的时候谁的字段里面需要添加外键,然后谁就是主动方,然后就可以分清被动方,这样我们顺着思路就可以理清了正向和反向的概念

    在多对多关系里面我们无所谓谁关联谁,反正是一样的概念,但是我们依然需要分清正向和反向,正反向涉及到我们后续需要使用的方法,所以,跟上面一样我们的多对关系中,外键设定在谁的表格里面,那么谁就掌握了主动发方,谁就是正向,反之则是反向,所以,一句话总结,我们的一对一关系,一对多关系,多对多关系,都是需要区分正向和反向的.这样我们后续使用查询方法的时候便于区分哪些是正向哪些是反向的.

    对于object对象的增删改查方法:

    查询:

    get()

    first()

    last()

    增加:

    obj=models.Author(name="fred",age=29)

    obj.save()

    删除:

    models.AuthorDetail.objects.get(addr="大理").delete()  # 直接使用过滤方式找到那个objects对象,然后使用delete()即可删除

    修改:

    obj=models.Author.objects.get(id=2)

    obj.name="亮晶晶"

    obj.save()

    =================================================================================================

    多对多关系的常用方法:

    create()  创建

    创建一个新的对象,保存对象,并将它添加到关联对象集中,返回新创建的对象

    import datetime

    teacher_obj.cid.create(cname='9班',first_day=datetime.datetime.now())

    add() 增加

    把指定的model对象添加到关联对象集中

    添加对象

    class_objs=models.Class.objects.filter(id__lt=3)  # 这里使用到了双下线的方法,__lt,小于

    models.Teacher.objects.first().cid.add(*class_objs)

    添加id

    models.Teacher.objects.first().cid.add(*[2,4,3,1])  # 这里需要打散之后一个个添加

     book_obj=Book.objects.create(title="python")

    author_list=models.Author.objects.all()

    book_obj.author.add(*author_list)

    book_obj.author.add(*["wusir","alex","pete"])

    book_obj.author.add("fred")

    set()  # 仅限于多对一或者多对多 修改

    更新model对象的关联对象

    teacher_obj=models.Teacher.objects.first()

    teacher_obj.cid.set([2,1,4,5])

    示例:

     我们在models里面把表格定义成多对多的关系:

    class Course(models.Model):
    id = models.AutoField(primary_key=True)
    cname = models.CharField(max_length=30)
    first_day = models.DateField(null=True)

    def __str__(self):
    return self.cname


    class Teacher(models.Model):
    tname = models.CharField(max_length=20)
    cid = models.ManyToManyField(to='Course', related_name='teachers')

    def __str__(self):
    return self.tname
    然后我们在演示set效果的时候,这样操作:

    from api_app import models

    a=models.Teacher.objects.first()  # 我们这里必须要是object对象才可以使用我们的set方法,如果是jqueryset则不具备这个方法,

    set的用法就是我们得到一个object对象然后我们通过我们的对象去.关联字段名.set([可迭代数据类型])   # 这里如果是字典的话,我们的修改只是取到了我们的key的值,那么我们的value里面的值就没有意义了,所以没有必要去浪费多余的内存空间,我们一般都是写成列表和元祖还有集合的形式,
    a.cid.set(2,3,8)我们的set方法是直接覆盖掉原来的值,不论我们之前有没有值,是什么值,都一刀切,直接替换掉,我们之前写的学生系统的增删改查,

    在里面我们的 改 操作,里面包含了很多的可能性,有5种,增加,减少,更改,不更改,还有一个不记得了,总之都是封装到了我们的set用法里面了,
    我们的add是直接在原来的基础上进行增加,不做修改,只管增加

    update()修改我本张表格的具体数值内容

    models.Book.objects.filter(title="自由#$%num one#$%").update(title="自由")  # 这里是queryset的修改方法,对我自己的这张表格的具体数据进行修改,就使用update,

    remove()

    从关联对象集中移除执行的model对象

    teacher_obj=models.Teacher.objects.first()  # 我们先取到这个对象,

    teacher_obj.cid.remove(5)  # 然后再移除它

     clear()

    从关联对象中移除一切对象

    teacher_obj=models.Teacher.objects.first()  # 先得到一个对象

    teacher_obj.cid.clear()  # 我们再拿这个对象去到它的关联的外键的表格里面去清空那个表格里面的数据

    我们在使用remove()或者clear()方法操作的时候,如果我们关联的那个表格---专业术语叫做对象集,对象集为空的话,必须要满足null=True,

    也就是说我们如果清空了一组数据,而那组数据又在一开始设定的时候被设定为不能够为空,那么我们的程序是会报错的,你不能够清空一个不可以为空的字段值,也就是类属性,这是矛盾的,系统无法识别你的操作,不会执行操作的

    对于所有类型的关联字段,add(),create(),remove()和clear(),set()都会马上更新数据库,换句话说,在关联的任何一端都不需要再调用save()方法,

    这个是老师很潦草的笔记,如果不明白就不建议看它了,如果有比较清晰的对该知识点的理解,可以参考一下,类似于找毛病的作用,如果你能看出他的内容有不严谨的地方,那么你就理解了重点内容

    day67
    
    ORM
    
    
    特殊的语法
        一个简单的语法  --翻译成--> SQL语句
        
        
        
    语法:
        1. 操作数据库表 创建表、删除表、修改表
        
        2. 操作数据库行 增、删、改、查
        
        
        怎么连数据库:
            需要手动创建数据库
            手写一段代码
            告诉Django连哪个数据库
            告诉Django用pymysql代替默认的MySQLdb
        发命令:
            python manage.py makemigrations
            python manage.py migrate
            
            
        总结详细步骤:
            1. 手动创建数据库
            2. 在app/models.py里面写上一个类,必须继承models.Model这个类 (注意启动Django项目)
            3. 在Django 项目的settings.py 里面 配置上数据库的相关信息
            4. 在Django项目里的__init__.py里面写上 两句话 import pymysql pymysql.install_as_MySQLdb()
            5. 给Django发布命令 
                1. python manage.py makemigrations  # 相当于去你的models.py 里面看一下有没有改动
                2. python manage.py migrate  # 把改动翻译成SQL语句,然后去数据库执行
            
        
            models.py  -->  Django翻译成SQL --> pymysql  --> MySQL(4p)
        
            哪吒老师ORM思想:
                五步四部分
                
                
                
        目前为止学到的特殊语法之操作数据表部分:
            1. 通过建一个类(继承models.Model)  --> 相当于创建了一个数据库中的表  --> 类 - 数据表
            2. 字段:
                1. models.AutoField(primary_key=True)  --> int 自增的 主键
                2. models.CharField(max_length=32, null=True)     --> varchar(32)
                3. models.IntegerField() # int
    
        
        总结一下:
             models.py                  MySQL
            类           对应            数据表
            类的属性     对应           数据库里面的字段(列)
            对象         对应           一行数据(一条数据)
            
            
        ORM到底是什么?
        
            对象关系映射
            
            
        数据行的操作:
            增:两种
                1. models.User.objects.create(**{}) 直接创建并且提交到数据库
                2. user = models.User(**{})  user.save()
                
            删:
                找到对象删除
                models.User.objects.filter().delete()
            
            改:
                更新 两种
                1. models.User.objects.filter().update(username="一枝花")
                2. user = models.User.objects.get(id=1)   user.username="梁志华" user.save()
            
            查:
                models.User.objects.all()
                models.User.objects.get(条件)  不满足条件就报错|返回的是一个对象
                models.User.objects.filter(条件) 不满足条件不报错,但是返回的结果是一个对象的列表
                models.User.objects.filter().first()
                models.User.objects.filter().last()
                
                models.User.objects.exclude(条件) 
            
    3. 今日作业
        整理今天的内容
        
    4. 周末作业
        班级表和学生表 增删改查 再写一遍(最素的页面)
        
    5. 下周内容
        1. ORM版学员管理系统
        cookie和session
        AJAX(模态框版增删改查)
        中间件(有时间)
        
    
    
    
    
    
    
    
    
            
            
        
        
        
    View Code
    day68
    
    Django
    
        安装
        创建项目
        配置(3个:settings.py:1 模板,2静态文件 3 csrf)
        创建APP  python manage.py startapp app01
        三部分:
            urls.py 
                1. 普通正则
                2. 分组正则        url(r'/blog/(d+)/(d+)', views.blog)  blog(request, arg1, arg2) 传位置参数
                3. 分组命名           url(r'/blog/(?P<year>d+)/(?P<month>d+)', views.blog)  blog(request, year, month) 传关键字参数
                4. 用name指定别名  url(r'/blog/(?P<year>d+)/(?P<month>d+)', views.blog, name="blog")  blog(request, year, month)
                    涉及到了反向解析URL:
                        1. HTML里面:{% url ‘blog’ 2017 12 %}
                        2. views里面:from django.urls import reverse  reverse("blog", arg=(2017, 12))
                        
                5. 用namespace指定命名空间
                    url(r'^app01/', include(app01.urls, namespace="app01")),
                    url(r'^app02/', include(app02.urls, namespace="app02"))
                    
                    涉及到了反向解析URL:
                        1. HTML里面:{% url ‘app01:blog’ 2017 12 %}
                        2. views里面:from django.urls import reverse  reverse("app01:blog", arg=(2017, 12))
                        
            views.py
                request对象
                response对象
                FBV和CBV
                
            xxx.html
            
        模板语言
            {{变量}}
            {{变量.}}
            
            {% for %}循环
            {% if %}判断
            
            过滤器(filter)  {{ 变量名|filter_name:参数 }}   {{时间对象|date:‘Y-m-d’}}
            {% url %}
            {% load static %}
            {% static "img/1.png" %}
            
            母版、继承、块、组件
            
        连接数据库(ORM)
        
        五步四部分
            
            五步:
                1. 创建数据库
                2. 在app下的models.py里面创建model类,继承models.Model
                3. 在settings.py里面配置数据库连接信息
                4. 在项目(project)的__init__.py里面写上 import pymysql, pymysql.install_as_MySQLdb()
                5. 发命令:
                    python manage.py makemigrations   收集变更 
                    python manage.py migrate           翻译成SQL语句,执行
            四部分:
                1. models.py
                2. Django
                3. pymysql
                4. MySQL
                
            
            ORM:
                类           --->           数据表
                类的属性     --->           数据列(表里的字段)
                对象         --->           数据行
            
            
            增删改查:
                查:
                    models.类名.objects.all()         取所有
                    models.类名.objects.get()         取一个, 取不到就报错
                    models.类名.objects.filter(条件)  根据条件查找,返回的是[object1, objdect2 ...]
                    models.类名.objects.exclude(条件) 排除满足条件的
                    models.类名.objects.first()
                    models.类名.objects.last()
                增加:
                    models.类名.objects.create(name="王永飞", age=18)
                    
                    obj = models.类名(name="王永飞", age=18)
                    obj.save()
                删除:
                    models.类名.objects.filter(age=18).delete()
                
                修改:
                    models.类名.objects.filter(age=18).update(name="装嫩")
                    
                    单个对象不能调用update
                    obj = models.类名.objects.get(id=2)
                    obj.name = "一枝花"
                    obj.save()
                    
        引申:
            SQLAlchemy Flask
            
                
    2. 今日内容
    
        单表的增删改查
        单表查询的API介绍
            13条:
                返回的是QuerySet对象:
                    1. all()
                    2. filter()
                    3. exclude()
                    4. valus()
                    5. values_list()
                    6. order_by()
                    7. reverse()
                    8. distinct()
                返回数字的:
                    1. count()
                返回布尔值的:
                    1. exists()
                返回具体的数据对象的:
                    1. get()
                    2. first()
                    3. last()
                
                
            logging配置参数:
            
            LOGGING = {
        'version': 1,  # 目前为止有且只有这一个值
        'disable_existing_loggers': False,  # 不禁用已经存在的logger实例
        # 定义一些日志的处理方式
        'handlers': {
            'console': {
                'level':'DEBUG',  # handle的日志级别
                'class':' logging.StreamHandler',
            },
        },
        'loggers': {
            'django.db.backends': {
                'handlers': ['console'],
                'propagate': True,  # 向上传导
                'level':' DEBUG',  # logger实例的日志级别
            },
        }
    }
    
    
    
        表之间的关系
            一对一
            一对多
                外键通常设置在多的那个表里面
            多对多
            
    
        
        
    View Code
    day69
    
    1. 昨日内容回顾
    
        1. 单表增删改查
        2. 单表查询API
            返回QuerySet对象的:
                1. .all()
                2. .filter()
                3. .values()
                4. .values_list()
                5. .exclude()
                6. .order_by()
                7. .reverse()
                8. .distinct()
            
            返回单个数据对象:
                1. .first()
                2. .last()
                3. .get()
                
            返回布尔值的:
                1. .exists()
            返回数字的:
                1. .count()
                
        3. 神奇的双下划线:
            配合filter()来做各种查询。
                1. id__gt=1
                2. id__lt=3
                3. id__in=[1,2,3]
                4. id__range=[1,5]
                
                5. name__contains="s"
                6. name__icontains="s"
                7. name__startwith="a"
                8. name__endswith="x"
                
                9. first_day__year="2018"
                
                10. cname__isnull=True *!
                
                
        4. Django日志配置
    
    2. 今日内容
        表之间的关系
        
        1. 一对多
        2. 一对一
        如下所示:
        class Student(model,Model):
        sname = models.CharField(max_length=23,verbose_name='学生姓名)
        the_class=models.ForeignKEy(to=Class,to_field='id',
        on_delete=models.CASCADE, related_name='students')
        detail = models.OneToOneField(to='StudentDetail', null=True)
        
        
        class StudentDetail(models.Model):
        hetght=models.PositiveIntegerField()
        weitht=models.PositiveIntegerField()
        email=models.EmailField()
        
            对应关系:
                类           -->        表
                类的属性     -->        字段
                实例对象     -->        一条数据(数据行)
    
    
                
            数据库层面:
                外键 对应 另外一个表的一条记录
                cid_id
            ORM层面:
                外键对应 另外一个表的一个对象
                student_obj.cid_id  --> 具体的值
                
                为什么? Django把关系包装成一个具体的对象
                cid  
            正向查找:
    student_obj=models.Student.objects.first()        
    student_obj.detail.email
            反向查找:
                默认是表名_set.all()
                detail_obj=models.StudentDetail.objects.get(id=1)
                detail_obj.student.sname
                如果在外键的字段中加了related_name属性,则按照该属性的值来反向查找
                
            
        3. 多对多
            老师 和 班级
            
            通过第三张表关联
            
            Teacher表
            id   tname
            
            1    Alex
            2    Egon
            3    yuan
            
            
            Class表
            
            id   cname
            1    1班
            2    2班
            3    3班
            
            
            TeacherToClass
            
            id   teacher_id     class_id
            1    1              1
            2    1              2
            3    1              3
            4    2              1
            5    2              3
            6    1              1
            
            
            
            
            多对多三种方式创建表格:
            
            第一种:(没有使用到ManyToMany的格式去创建,使用不到它内部封装好的一些便捷用法,但是可扩展性强便于理解)
            class Course(models.Model):
            id=models.AutoField(primary_key=True)  # 主键
            cname=models.CharField(max_length=20)  # 班级名称
            first_day=models.DateField()  # 开班时间
            
            class Teacher(models.Model):
            tname=models.CharField(max_length=20)
            
            # 自定义三张表格,通过外键去关联上面两张表格
            class Teacher2Class(models.Model):
            teacher=models.ForeignKey(to='Teacher)
            the_class=models.ForeignKey(to='Course')
            
            class Meta:  # 这里是指定我们的表格里面的这两个字段不可以有重复的,不可以同时出现重复,也就是我们说的联合主键
            unique_together=("teacher", 'the_class')
            
            第二种方式:(我们这里只是定义了两个类,course和teacher,没有定义第三个类,但是我们运行程序的时候系统会自动给我们生成第三张表格出来用于建立我们的 多对多的关系,但是注意了,我们上面提到了我们并没有建立第三张表格,它系统给我们生成的,我们不能够对这个自动生成的表格进行操作,这就是不够便利的地方,优势当然是我们在不使用第三张表格的前提下,另外两张表格的操作会更加便捷)
            通过manyToManyField去创建
            class  Course(models.Model):
            id=models.AutoField(primary_key=True)
            cname=models.CharField(max_length=20)
            first_day=models.DateField()
            
            class Teacher(models.Model):
            tname=models.CharFirld(max_length=30)
            cid=models.ManyToManyField(to='Course,relate_name='teachers)
            
            
            第三种方式:(优劣自己体会)
            通过外键和ManyToManyField创建
            class Course(models.Model):
            id=models.AutoField(primary_key=True)
            cname=models.CharField(max_length=30)
            first_day=models.DateField()
            
            class Teacher(models.Model):
            tname=models.CharField(max_length=40)
            # 通过manyToManyField和手动去创建第三张表格
            cid=models.ManyToManyField(to='Class',through='Teacher2Class',through_fields=('teacher', 'the_class'))
            
            class Teacher2Class(models.Model):
            teacher=models.ForeignKey(to='Teacher')
            the_class=models.ForeignKey(to='Course')
            
            class Meta:  # 建立联合主键
            unique_together=('teacher', 'the_class')
            
            多对多操作
            正向查询(从老师表格查询班级表格)
            teacher_obj=models.Teacher.objects.first()
            teacher_obj.cid.all()  # 查询该老师授课的所有班级
            
            反向查询(由班级表格反向查询老师表格)
            class_obj=models.Course.objects.first()
            class_obj.teachers.all()  # 此处用到的是related_name,如果不设置的话就用默认的表名_set
            
            常用方法:
            create()
            创建一个新的对象,保存对象,并将它添加到关联对象集中,返回新创建的对象
            import datetime
            teacher_obj.cid.create(cname='num9_class',first_day=datetime.datetime.now())
            
            add()
            把指定的models对象添加到关联对象集中
            添加对象
            class_obj=models.Course.objects.filter(id__lt=3)
            models.Teacher.objects.first().cid.add(*class_obj)
            
            添加id
            models.Teacher.objects.first().cid.add(*[2,3,5])
            
            set()
            更新model对象的关联对象
            teacher_obj=models.Teacher.objects.first()
            teacher_obj.cid.set([2,3,4])
            
            remove()
            从关联对象集中移除执行的model对象
            teacher_obj=models.Teacher.objects.first()
            teacher_obj.cid.remove(3)
            
            clear()
            从关联对象集中移除一切对象
            teacher_obj=models.Teacher.objects.first()
            teacher_obj.cid.clear()
            
        
        4. 了不起的双下划线:
            找学生名字里面带龙字的班级
            sname__contains=""
            models.Class.objects.filter(students__sname__contains="")
            双下划线表示跨表
                    
        
        
    3. 今天作业
        1. 今天上课的例子要写完,博客整理好
        
    
        2. 自己设计图书管理系统的表结构,用咱们今天上课学到的内容,做查询的练习
        
        书和作者    多对多
        书和出版社  多对一
        
        使用双下划线练习跨表查询
        
    
        
        
        
        
        
        
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
            
            
            
            
            
                
                
                
                
        
    View Code
  • 相关阅读:
    省市区三级联动
    VUE项目PC端实现自适应rem
    (课堂笔记)第十三章GLSB涉及负载均衡算法
    LTM理解及配置笔记记录
    实验演示---GSLB部分(DC1)
    F5实验模拟拓扑
    (课堂笔记)第十三章:DNS 全局站点
    AbstractList类_Iterator内部类
    Oracle 时间格式化异常:无效数字
    Maven库镜像
  • 原文地址:https://www.cnblogs.com/2012-dream/p/8336431.html
Copyright © 2011-2022 走看看