• Django回顾之_04_模型关系及相关操作


    10. 模型类关系

    1) 一对多关系

    • 例:图书类-英雄类
      • models.ForeignKey() 定义在多的类中。

    2) 多对多关系

    • 例:新闻类-新闻类型类 体育新闻<->国际新闻
      • models.ManyToManyField() 定义在哪个类中都可以。
    # 新闻类型类
    class NewsType(models.Model):
        # 类型名
        type_name = models.CharField(max_length=20)
        # 关系属性,代表类型下面的信息
        type_news = models.ManyToManyField('NewsInfo')
    
    # 新闻类----这两个类是关联属性,定义在哪个类中都可以
    class NewsInfo(models.Model):
        # 新闻标题
        title = models.CharField(max_length=128)
        # 发布时间
        pro_date = models.DateTimeField(auto_now_add=True)
        # 信息内容
        content = models.TextField()
        # 关系属性,代表信息所属的类型
        news_type = models.ManyToManyField('NewsType')
    

    3) 一对一关系

    - 例:员工基本信息类-员工详细信息类. 员工工号
        - models.OneToOneField定义在哪个类中都可以。
    
    # 员工基本信息类
    class EmployeeBasicInfo(models.Model):
        name = models.CharField(max_length=20)
        # 性别
        gender = models.BooleanField(default=False)
        # 年龄
        age = models.IntegerField()
        # 关系属性,代表员工的详细信息
        employee_detail = models.OneToOneField('EmployeeDetailInfo')
    
    # 员工详细信息类---两个类之间,如果是一对一关系,定义在哪个类都可以,如果是一对多,只能定义在多的类中
    class EmployeeDetailInfo(models.Model):
        # 联系地址
        addr = models.CharField(max_length=256)
        # 教育经历
    

    11 模型_关联查询

    11.1 关联查询(一对多)

    11.1.1查询和对象关联的数据

    在一对多关系中,一对应的类我们把它叫做一类,多对应的那个类我们把它叫做多类,我们把多类中定义的建立关联的类属性叫做关联属性。
    
    • 例:查询id为1的图书关联的英雄的信息。
      • b=BookInfo.objects.get(id=1)
      • b.heroinfo_set.all()
    • 通过模型类查询:
      • HeroInfo.objects.filter(hbook__id=1)
      • 例:查询id为1的英雄关联的图书信息。
        • h = HeroInfo.objects.get(id=1)
        • h.hbook
    • 通过模型类查询:
      • BookInfo.objects.filter(heroinfo__id=1)
    • 格式:
    • 由一类的对象查询多类的时候:
      • 一类的对象.多类名小写_set.all() #查询所用数据
    • 由多类的对象查询一类的时候:
      • 多类的对象.关联属性 # 查询多类的对象对应的一类的对象
    • 由多类的对象查询一类对象的id时候:
      • 多类的对象.关联属性_id

    11.1.2 通过模型类实现关联查询

    注意:
        1. 对一个QuerySet实例对象,可以继续调用上面的所有函数。
        2. 通过模型类实现关联查询时,要查哪个表中的数据,就需要通过哪个类来查
        3. 写关联查询条件的时候,如果类中没有关系属性,条件需要写对应类的名字,如果类中有关系属性,直接写关系属性。
    
    • 例:查询图书信息,要求图书关联的英雄的描述包含'八'。
      • BookInfo.objects.filter(heroinfo__hcomment__contains='八')
        • 转换为---> booktest_bookinfo.bpub_date, booktest_bookinfo.bread, booktest_bookinfo.bcomment, booktest_bookinfo.isDeleteFROMbooktest_bookinfoINNER JOINbooktest_heroinfo ON (booktest_bookinfo.id=booktest_heroinfo.hbook_id) WHERE booktest_heroinfo.hcomment` LIKE BINARY '%八%' LIMIT 21
    • 例:查询图书信息,要求图书中的英雄的id大于3.
      • BookInfo.objects.filter(heroinfo__id__gt=3)
    • 例:查询书名为“天龙八部”的所有英雄。---此时()内不应再写BookInfo,因为在HeroInfo中有关联的属性hbook,所以直接写上hbook
      • HeroInfo.objects.filter(hbook__btitle='天龙八部')
    • 通过多类的条件查询一类的数据:
      • 一类名.objects.filter(多类名小写__多类属性名__条件名)
    • 通过一类的条件查询多类的数据:
      • 多类名.objects.filter(关联属性__一类属性名__条件名)

    12 插入、更新和删除

    • 调用一个模型类对象的save方法的时候就可以实现对模型类对应数据表的插入和更新
    • 调用一个模型类对象的delete方法的时候就可以实现对模型类对应数据表数据的删除

    13.自关联

    <jpg/png>
    自关联是一种特殊的一对多的关系。

    • 案例:显示广州市的上级地区和下级地区。
      • 地区表:id, atitle, aParent_id;
      • mysql终端中批量执行sql语句:source areas.sql;

    13.1. 实现步骤:

    • 1)模型中添加地区模型类:
    # test2/booktest/models.py
    class AreaInfo(models.Model):
        """地区模型类"""
        # 地区名称
        atitle = models.CharField(max_length=20)
        # 关系属性,代表当前地区的父级地区---self代表与自身关联
        aParent = models.ForeignKey('self', null=True, blank=True, on_delete=models.CASCADE,)
    
    > python manage.py makemigrations
    > python manage.py migrate
    
    • 2)视图中views.py中定义areas():
    def areas(request):
        """获取广州市的上级地区和下级地区"""
        # 1.获取广州市的信息
        area = AreaInfo.objects.get(atitle='广州市')
        # 2. 查询广州市的上级地区--由多查一, 故直接使用对象名.关系属性
        parent = area.aParent
        # 3. 查询广州市的下级地区
        childern = area.areainfo_set.all()
        # 4. 使用模板---创建areas.html, 将父级、子级结果都传给它。
        return render(request, 'booktest/areas.html', {'area':area, 'parent':parent, 'children':childern})
    
    • 2.1)创建模板文件areas.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>自关联案例</title>
        <style type="text/css">
    
    
        </style>
    </head>
    <body>
    <h1>当前地区</h1>
    {{  area.atitle }}<br/>
    <h1>父级地区</h1>
    {{ parent.atitle }}<br/>
    <h1>下级地址</h1>
    <ul>
        {% for child in children %}
            <li>{{ child.atitle }}</li>
        {% endfor %}
    </ul>
    </body>
    </html>
    

    -3)添加url到列表中

    urlpatterns = [
    ···
        url(r'^areas$', views.areas), # 自关联案例
    ···
    ] 
    

    14. 管理器

    BookInfo.objects.all()->objects是一个什么东西呢?
    

    答:objects是Django帮我自动生成的管理器对象,通过这个管理器可以实现对数据的查询。
    objects是models.Manger类的一个对象。自定义管理器之后Django不再帮我们生成默认的objects管理器。

    python manage.py shell
    >>> from booktest.models import BookInfo, HeroInfo
    >>> type(BookInfo.objects)
    <class 'django.db.models.manager.Manager'>
    >>> type(HeroInfo.objects)
    <class 'django.db.models.manager.Manager'>
    

    14.1 自定义模型管理器类

    1) 自定义一个管理器类,这个类继承models.Manger类。

    • book = models.Manager()
      • 一旦自己定义了管理类对象后,Django就不再提供默认的object类,就会报错,
      • 通常不会这么做,一般是自己去定义一个这样的类,继承models.Manager

    2) 再在具体的模型类里定义一个自定义管理器类的对象。

    class BookInfoManager(models.Manager):
        """图书模型管理器类"""
        # 1.改变查询的结果集
        def all(self):
            # 1.调用父类的all,获取所有数据
            books = super().all()   # Queryset,可以继续调用
            # 2.对数据进行过滤
            books = books.filter(isDelete=False)
            # 3.返回books
            return books
            
            
    class BookInfo(models.Model):
        """图书模型类"""
    ···
        objects = BookInfoManager() # 自定义一个BookInfoManager类的对象
    ···
    

    14.2 自定义管理器类的应用场景

    1) 改变查询的结果集。

    • 比如调用BookInfo.books.all()返回的是没有删除的图书的数据。---isDelete=1
    >>> from booktest.models import BookInfo
    >>> BookInfo.objects.all()
    <QuerySet [<BookInfo: BookInfo object (1)>, <BookInfo: BookInfo object (2)>, <BookInfo: BookInfo object (3)>, <BookInfo: BookInfo object (4)>, <BookInfo: BookInfo object (5)>]>
    

    2) 添加额外的方法。

    • 管理器类中定义一个方法帮我们操作模型类对应的数据表。
    • 使用self.model()就可以创建一个跟自定义管理器对应的模型类对象。
      • 但通常不定义在模型类中,而是定义在对应的模型管理器中
    class BookInfo(models.Model):
        """图书模型类"""
    ···
        @classmethod
        def create_book(cls, btitle, bpub_date):
            # 1.创建一个图书对象
            obj = cls()
            obj.btitle = btitle
            obj.bpub_date = bpub_date
            # 2.保存进数据库
            obj.save()
            # 3.返回obj
            return obj
            
    # 改为:
    class BookInfoManager(models.Manager):
        """图书模型管理器类"""
    ···
        # 2.封装函数:操作模型类对应的数据表(增删改查)
        def create_book(self, btitle, bpub_date):
            # 1. 创建一个图书对象
            # 获取self所在的模型类
            # >>> BookInfo.objects.model
            # <class 'booktest.models.BookInfo'>
            model_class = self.model    # 可以获取到类名
            # book = BookInfo()
            book = model_class()    # 即使下面的类名发生了变化,上面的model类名也不需要发生变化。
            book.btitle = btitle
            book.bpub_date = bpub_date
            # 2.保存进数据库
            book.save()
            # 3.返回book
            return book
    
    >>> from booktest.models import BookInfo
    >>> BookInfo.objects.create_book('test2', '1990-1-1')
    <BookInfo: BookInfo object (8)>
    
    实际上该create_book()方法已经在objects对象中定义了,但调用时,需要使用关键字参数调用
    
    >>> BookInfo.objects.create(btitle='test3', bpub_date='1990-1-1')
    <BookInfo: BookInfo object (10)>
    

    小结: 06_模型_模型管理器类和模型类关系

    • 1)BookInfo对象(模型类)和BookInfoManager对象(模型管理器类)之间如何起联系?
      • 通过创建objects = BookInfoManager()
      • BookInfo.objects.create_book()
    • 2)self.model获取self所在模型类的类名

    15. 元选项

    - 如果应用名修改后:booktest———>booktest2后,模型类对应的表名已经生成了,就会出报错,如何解决?
        - 将模型类对应的表名,不依赖这个应用名---通过元选项,指定表名。
    
    • Django默认生成的表名:
      • 应用名小写_模型类名小写。
    • 元选项:
      • 需要在模型类中定义一个元类Meta,在里面定义一个类属性db_table就可以指定表名。
    class BookInfo(models.Model):
        """图书模型类"""
    ···
        class Meta:
            db_table = 'bookinfo'   # 指定模型类对应的表名
    
  • 相关阅读:
    fork()
    定时器
    epoll函数
    select函数
    高性能服务器程序框架
    socker地址API
    点击选中/取消选中flag
    html5的视频和音频
    html5
    JavaScript的string方法(demo)
  • 原文地址:https://www.cnblogs.com/wangxue533/p/12369184.html
Copyright © 2020-2023  润新知