Django - 选择相关或加入两个不同的基本模型

时间:2018-01-08 13:13:59

标签: python django

我有两个基本型号SiteData和Showoroom Service,它们具有如下所示的模型结构。

我需要SiteData信息,但如果有匹配的ID,我也想从展示厅服务模型中获取link_type。

到目前为止,我已经尝试了一些事情,没有人得到我需要的东西,实现这个目标的最佳途径是什么?

由于

选择相关的

>>> nd = ShowroomService.objects.select_related('site').all()
>>> nd
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py", line 229, in __repr__
    return '<%s %r>' % (self.__class__.__name__, data)
  File "/usr/local/lib/python3.6/site-packages/django/db/models/base.py", line 590, in __repr__
    u = six.text_type(self)
TypeError: __str__ returned non-string (type SiteData)

结合:

>>> complete_data = site_data | monitoring_data
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py", line 310, in __or__
    combined.query.combine(other.query, sql.OR)
  File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/query.py", line 529, in combine
    "Cannot combine queries on two different base models."
AssertionError: Cannot combine queries on two different base models.

链接

>>> final_data = chain(monitoring_data, site_data)
>>> for i in final_data:
...  '{} {}'.format(i.location,i.link_Type)
...
Traceback (most recent call last):
  File "<console>", line 2, in <module>
AttributeError: 'ShowroomService' object has no attribute 'location'

sites.models.py

class SiteData(models.Model):
    location = models.CharField(max_length=50)
    site_type = models.ForeignKey(SiteTypes, verbose_name="Site Type", \
                on_delete=models.PROTECT)
    subnet = models.GenericIPAddressField(protocol='IPv4')
    routed_subnet = models.GenericIPAddressField(protocol='IPv4', \
                    verbose_name="Routed Link Subnet", blank=True, null=True)
    bgp_as = models.CharField(max_length=6, verbose_name="BGP AS Number")
    opening_date = models.DateField(verbose_name="Showroom opening date")
    last_hw_refresh_date = models.DateField(verbose_name="Date of latest hardware refresh", \
                           blank=True, null=True)
    is_live = models.BooleanField(default=False, verbose_name="Is this a live site?")
    tel = models.CharField(max_length=20, blank=True, null=True)
    address = models.CharField(max_length=255, blank=True, null=True)
    town = models.CharField(max_length=255, blank=True, null=True)
    ...
    class Meta:
        verbose_name = "Site Data"
        verbose_name_plural = "Site Data"
        ordering = ('location',)
        permissions = (
            ("can_view", "Can View"),
            ("can_view_mgmt", "Can View Management"),
        )

    def __str__(self):
        return self.location

monitoring.models.py

from sites.models import SiteData

class ShowroomService(models.Model):
    site = models.ForeignKey(SiteData, verbose_name="Site", \
        on_delete=models.PROTECT)
    link_type = models.CharField(max_length=200, blank=True, null=True)
    preference = models.CharField(max_length=200, blank=True, null=True)
    timestamp = models.DateTimeField(auto_now_add=True, blank=True, null=True)
    dashboard = models.BooleanField(default=True, verbose_name="display on monitoring dashboard?")

    class Meta:
        verbose_name = "Showroom Service Data"
        verbose_name_plural = "Showroom Service Data"

    def __str__(self):
        return self.site

1 个答案:

答案 0 :(得分:2)

您可以使用django&#34; s&#34;相关经理&#34;来提取所有相关对象。文档可在此处获取:https://docs.djangoproject.com/en/2.0/ref/models/relations/#related-objects-reference

通过在showroom_service_set模型上调用SiteData,您可以获取每个SiteData的子记录集。

只是为了解释列出的尝试失败的原因:

  1. 您的模型上的__str__方法需要才能返回字符串。如果他们不这样做,你就会得到那个例外。
  2. 管道运算符|用于OR django中的查询。这段代码试图将查询组合成两种不同类型的模型。
  3. 通过连锁尝试,您创建了一个包含两种不同类型模型的列表。其中一个没有location属性。
  4. 这是获取附加到SiteData模型的所有ShowroomService模型的链接类型的一大块代码:

    for site_data in SiteData.objects.all():
        for showroom in site_data.showroom_service_set.all():
            print showroom.link_type
    

    我不确定django如何使用相关对象处理骆驼套管,所以showroom_service_set是我最好的猜测。您可能需要对此进行一些小工作以确定实际集合的调用方式。

    编辑:有一些名为prefetch_related的东西。这是一个关于它的SO答案;我认为它会让你找到你想要的东西:https://stackoverflow.com/a/13096423/769971