zoukankan      html  css  js  c++  java
  • Peewee中join三张及以上的表时只能获取一张表的数据

    问题描述

    这里有三张表ProjectAlgorithmVersion(简称PAV)ProjectUserInfo, 关联关系为:

    PAV.project_id = Project.project_id
    PAV.create_by = UserInfo.user_id
    

    现在想查询一条PAV的数据(id=2), 并查到相关联的Project表中的Project_nameUserInfo表中的user_display_name, 当使用正常的join时:

    query_model = ProjectAlgorithmVersion.select(ProjectAlgorithmVersion.id, Project.project_name, UserInfo.user_display_name).join(Project, on=(ProjectAlgorithmVersion.project_id == Project.project_id)).join(UserInfo, on=(ProjectAlgorithmVersion.create_by ==UserInfo.user_id)).where(ProjectAlgorithmVersion.id == 2)
    for result in query_model:
        # 查看result的属性
        print(result.__dict__)
        print('id:', result.id)
        # 上面这种join model的写法, 在获取Project表和UserInfo表的数据时, 需要在对应字段前加上类名的小写, 默认小写, 也可以在join(attr=xxx)中新增attr参数, 指定该名称
        print('project_name:', result.project.project_name)
        print('user_display_name:', result.userinfo.user_display_name)
    

    但是运行结果发现报错: 说 result没有userinfo属性, 但是从``result.dict可以看出project`属性是有的

    Traceback (most recent call last):
      File "/mnt/d/work/cleartv/01.huarunai/ai/management_cloud/models/model_test.py", line 62, in <module>
        sync_fun()
      File "/mnt/d/work/cleartv/01.huarunai/ai/management_cloud/models/model_test.py", line 35, in sync_fun
        print('user_display_name:', result.userinfo.user_display_name)
    AttributeError: 'ProjectAlgorithmVersion' object has no attribute 'userinfo'
    {'__data__': {'id': 2}, '_dirty': set(), '__rel__': {}, 'project': <Project: None>}
    id: 2
    project_name: 上海线上项目01
    

    然后我尝试将两个join的顺序调换, 先join UserInfo表, 再join Project表:

    query_model = ProjectAlgorithmVersion.select(ProjectAlgorithmVersion.id, Project.project_name, UserInfo.user_display_name).join(UserInfo, on=(ProjectAlgorithmVersion.create_by ==UserInfo.user_id)).join(Project, on=(ProjectAlgorithmVersion.project_id ==Project.project_id)).where(ProjectAlgorithmVersion.id == 2)
    

    发现结果报错变成了没有project属性:

    Traceback (most recent call last):
      File "/mnt/d/work/cleartv/01.huarunai/ai/management_cloud/models/model_test.py", line 64, in <module>
        sync_fun()
      File "/mnt/d/work/cleartv/01.huarunai/ai/management_cloud/models/model_test.py", line 36, in sync_fun
        print('project_name:', result.project.project_name)
    AttributeError: 'ProjectAlgorithmVersion' object has no attribute 'project'
    {'__data__': {'id': 2}, '_dirty': set(), '__rel__': {}, 'userinfo': <UserInfo: None>}
    id: 2
    

    猜测peewee如果关联三张表的话, 在查询结果中的__dict__属性中只能查到第一个join的表, 其他表查不到. 这应该是一个bug

    解决

    在官网查到另一种join的写法, 可以解决这个问题, 就是在query_model的最后添加一个.objects()方法, 加上以后在获取结果的时候就不需要在字段面前加上小写的表名了

    query_model = ProjectAlgorithmVersion.select(ProjectAlgorithmVersion.id, Project.project_name, UserInfo.user_display_name).join(Project, on=(ProjectAlgorithmVersion.project_id == Project.project_id)).join(UserInfo, on=(ProjectAlgorithmVersion.create_by ==UserInfo.user_id)).where(ProjectAlgorithmVersion.id == 2)
    for result in query_model.objects():
        # 查看result的属性
        print(result.__dict__)
        print('id:', result.id)
        # 上面这种join model的写法, 在获取Project表和UserInfo表的数据时, 需要在对应字段前加上属性的小写
        print('project_name:', result.project_name)
        print('user_display_name:', result.user_display_name)
    

    可以看到执行结果,Project表和UserInfo表的数据都能获取到了:

    {'__data__': {'id': 2}, '_dirty': set(), '__rel__': {}, 'project_name': '上海线上项目01', 'user_display_name': '龚'}
    id: 2
    project_name: 上海线上项目01
    user_display_name: 龚
    

    补充

    • 加上.objects()以后query_model的类型同样是<class 'peewee.ModelSelect'>, 因此该方法在peewee的异步查询中也可以使用
    query_model = ProjectAlgorithmVersion.select(ProjectAlgorithmVersion.version_id, Project.project_name, UserInfo.user_display_name).join(Project, on=(
    ProjectAlgorithmVersion.project_id == Project.project_id)).join(UserInfo, on=(
    ProjectAlgorithmVersion.create_by == UserInfo.user_id)).where(ProjectAlgorithmVersion.id == 2)
    result_list = await ProjectAlgorithmVersion.objects.execute(query_model.objects())
    for result in result_list:
        print(result.__dict__)
        print(result.version_id)
        print(result.project_name)
        print(result.user_display_name)
    
    • join()时, 默认情况下获取结果的字段属性的时候, 需要在字段前面加上小写的表模型类名, 如果想自己指定这个名称, 可以在join()中添加attr=xxx属性, 这样在获取结果的时候, 可以把小写类名改成xxx

      • 加之前:
      query_model = ProjectAlgorithmVersion.select(ProjectAlgorithmVersion.id, Project.project_name).join(Project, on=(ProjectAlgorithmVersion.project_id == Project.project_id)).where(ProjectAlgorithmVersion.id == 2)
      for result in query_model:
          # 查看result的属性
          print(result.__dict__)
          print('id:', result.id)
          # 使用 .project.
          print('project_name:', result.project.project_name)
      

      输出结果:

      # 输出, 属性为project
      {'__data__': {'id': 2}, '_dirty': set(), '__rel__': {}, 'project': <Project: None>}
      id: 2
      project_name: 上海线上项目01
      
      • attr='p'之后:
      query_model = ProjectAlgorithmVersion.select(ProjectAlgorithmVersion.id, Project.project_name).join(Project, on=(ProjectAlgorithmVersion.project_id == Project.project_id), attr='p').where(ProjectAlgorithmVersion.id == 2)
      for result in query_model:
          # 查看result的属性
          print(result.__dict__)
          print('id:', result.id)
          # 上面加上attr='p'后, 则使用 .p.
          print('project_name:', result.project.project_name)
      

      输出结果:

      # 输出, 属性为p
      {'__data__': {'id': 2}, '_dirty': set(), '__rel__': {}, 'p': <Project: None>}
      id: 2
      project_name: 上海线上项目01
      

  • 相关阅读:
    Codeforces 1265A Beautiful String
    1039 Course List for Student (25)
    1038 Recover the Smallest Number (30)
    1037 Magic Coupon (25)
    1024 Palindromic Number (25)
    1051 Pop Sequence (25)
    1019 General Palindromic Number (20)
    1031 Hello World for U (20)
    1012 The Best Rank (25)
    1011 World Cup Betting (20)
  • 原文地址:https://www.cnblogs.com/gcxblogs/p/14669543.html
Copyright © 2011-2022 走看看