【问题标题】:How to create "related_name" relation with parent models of "through" model (about related_name inheritance)如何与“through”模型的父模型创建“related_name”关系(关于related_name继承)
【发布时间】:2021-07-30 10:43:07
【问题描述】:

我有 4 个模型,包括一个 M2M“直通”模型,可以有一个索引:

class TargetShape(models.Model):
    pass
    
class Page(models.Model):
    target_shapes = models.ManyToManyField(TargetShape, through='PageElement', related_name='pages')
    
class PageElement(models.Model):
    target_shape = models.ForeignKey(TargetShape, related_name='page_elements')
    page = models.ForeignKey(Page, related_name='page_elements')
    index = models.PositiveIntegerField(verbose_name='Order')
    

class WorkingSession(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='working_sessions')

我定义了另一个模型Resolution,它使我能够将所有这些模型链接在一起,以创建以下related_name 关系:

working_session.resolutions
user.resolutions
target_shape.resolutions
page.resolutions
page_element.resolutions

为了让它工作,我必须声明:

class Resolution(models.Model):
    # relations that would be needed from a DRY perspective:
    page_element = models.ForeignKey(PageElement, related_name='resolutions')
    working_session = models.ForeignKey(WorkingSession, related_name='resolutions')
    
    # relations I want to exist to use user.resolutions, target_shape.resolutions, page.resolutions: 
    user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='resolutions')
    target_shape = models.ForeignKey(TargetShape, related_name='resolutions')
    page = models.ForeignKey(Page, related_name='resolutions')

但是,这不是很干燥。从 DRY 的角度来看,我应该能够将 Resolution 声明为仅链接到 PageElementWorkingSession,并推断/继承与父模型的关系:

class Resolution(models.Model):
    page_element = models.ForeignKey(PageElement, related_name='resolutions')
    working_session = models.ForeignKey(WorkingSession, related_name='resolutions')

但在这种情况下,我该如何创建以下关系:

user.resolutions
target_shape.resolutions
page.resolutions

没有经过:

user.working_sessions.resolutions
target_shape.page_elements.resolutions
page.page_elements.resolutions

【问题讨论】:

    标签: django django-models django-orm


    【解决方案1】:

    我能想到的就是:

    • 要么像我已经做的那样声明所有字段

    • 或者在 User、TargetShape 和 Page 模型中声明一个属性,分别返回:

      Resolution.objects.filter(working_session__user=self) Resolution.objects.filter(page_element__target_shape=self) Resolution.objects.filter(page_element__page=self)

    这肯定行得通,但这不是很优雅......而且不是很 Django-ish

    有人知道定义这种关系的更类似于 Django 的方式吗?

    【讨论】:

      【解决方案2】:

      我发现了另一种方法:在 User、TargetShape 和 Page 模型中声明一个返回查询集的属性:

      class Resolution(models.Model):
          page_element = models.ForeignKey(PageElement, related_name='resolutions')
          working_session = models.ForeignKey(WorkingSession, related_name='resolutions')
      
      class PageElement(models.Model):
          target_shape = models.ForeignKey(TargetShape, related_name='page_elements')
          page = models.ForeignKey(Page, related_name='page_elements')
          index = models.PositiveIntegerField(verbose_name='Order')
          
      
      class WorkingSession(models.Model):
          user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='working_sessions')
      
      
      
      class TargetShape(models.Model):
          @property
          def resolutions(self):
              return self.page_elements.resolutions 
      
          
      class Page(models.Model):
          @property
          def resolutions(self):
              return self.page_elements.resolutions 
      
          target_shapes = models.ManyToManyField(TargetShape, through='PageElement', related_name='pages')
          
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多