Django数据库:在相对数据库

时间:2015-09-16 14:19:28

标签: python django django-models

我在django中有两个数据库表:"设备"表存储实际设备和" DeviceTest"用于存储每个设备的测试检查的表(对一个设备进行多次测试)。

class Device(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    name = models.CharField(max_length=20)
    serial_number = models.CharField(max_length=20)

    def __unicode__(self):
        return self.name + " - " + self.serial_number

class DeviceTest(models.Model):
    device = models.ForeignKey(Device)
    created_at = models.DateTimeField(auto_now_add=True)

    TEST_OK = '+'
    TEST_ERROR = '-'
    TEST_RESULT_CHOICES = (
        (TEST_OK, 'Test Success'),
        (TEST_ERROR, 'Test Error'),
    )
    status = models.CharField(max_length=1, choices=TEST_RESULT_CHOICES, default=TEST_ERROR)

    comment = models.TextField(blank=True, default="")
    tester = models.CharField(max_length=255)
    action = models.CharField(max_length=255)

    def __unicode__(self):
        return  self.device.name + " - " + \
                self.device.serial_number + " - " + \
                unicode(self.created_at) + " - " + \
                u"Result (" + self.status + ")"

我已经制作了包含所有设备表格的HTML页面:

name | serial number | created_at | last_test_time | last_test_status | hyperlink to test table page

现在我想给用户所有的排序可能性。我通过GET参数为#34; name","序列号"和" created_at"领域。而现在,我仍然坚持使用" last_test_time"和" last_test_status"字段。

使用一些标准的Django函数可以解决这个问题吗?像Device.objects.all().filter(???).order_by(???)

这样的东西

1 个答案:

答案 0 :(得分:1)

您可以annotate使用最新created_at时间的查询集。

from django.db.models import Max

queryset = Device.objects.annotate(last_test_time=Max('devicetest__created_at'))

您可以为每个对象访问last_test_time

for obj in queryset
    print(obj.last_test_time)

您可以按此字段订购查询集

queryset = queryset.order_by('last_test_time')

但是,这只是部分答案,因为它无法帮助您获得该测试的状态。

您可以单独查找每个设备。

for device in queryset:
    device.latest_status = device.device_test.latest('created_at').status

如果设备数量很少,这是可以的,但这意味着每个设备有一个查询,这与设备数量的增加并不理想。

您可以使用prefetch_related在一个查询中获取所有相关的设备测试。 (下面的代码未经测试,我的语法可能略有错误。)

queryset = queryset.prefetch_related(Prefetch('devicetest', DeviceTest.objects.order_by('-created_at'))

然后,您可以通过第一次相关设备测试获取状态。

for obj in queryset:
    print obj.devicetest.all()[0].status 

请注意,这是低效的,因为您已加载所有相关项目,而不仅仅是最新项目。