Skip to main content
 首页 » 编程设计

python之Django:TypeError:实例(模型对象)之间不支持 ''

2024年09月07日33zfyouxi

我正在尝试将我的 Django 项目从 Python 2.7/Django 1.11 迁移到 Python 3.7/Django 2.1。

我发现了一个问题,我想了解其原因。

我的项目中有 3 个模型:

class DeviceModel(models.Model): 
    name = models.CharField(max_length=255) 
    pirsh = models.CharField(max_length=255) 
 
    def __str__(self): 
        return self.name + " - " + self.pirsh 
 
class Device(models.Model): 
    created_at = models.DateTimeField(auto_now_add=True) 
    device_model = models.ForeignKey(DeviceModel, on_delete=models.CASCADE) 
    serial_number = models.CharField(max_length=255) 
 
 
    def __str__(self): 
        return self.device_model.name + " - " + self.device_model.pirsh + " - " \ 
                + self.serial_number 
 
class DeviceTest(models.Model): 
    device = models.ForeignKey(Device, on_delete=models.CASCADE) 
    created_at = models.DateTimeField() 
 
    TEST_OK = '+' 
    TEST_ERROR = '-' 
    TEST_PENDING = '?' 
    TEST_RESULT_CHOICES = ( 
        (TEST_OK, 'Success'), 
        (TEST_ERROR, 'Fail'), 
        (TEST_PENDING, 'Not checked'), 
    ) 
    status = models.CharField(max_length=1, choices=TEST_RESULT_CHOICES, default=TEST_PENDING) 
 
    comment = models.TextField(blank=True, default="") 
    tester = models.CharField(max_length=255) 
    action = models.CharField(max_length=255) 
 
    def save(self, *args, **kwargs): 
        ''' On save, update timestamps ''' 
        if not self.created_at: 
            self.created_at = timezone.now() 
        return super(DeviceTest, self).save(*args, **kwargs) 
 
    def __str__(self): 
        return  self.device_id.device_model.name + " - " + \ 
                self.device_id.device_model.pirsh + " - " + \ 
                self.device_id.serial_number + " - " + \ 
                str(self.created_at) + " - " + \ 
                "Result (" + self.status + ")" 

这是我根据最新测试状态对 Device 对象进行排序的代码('dev_filter'、'field' 和 'order' 参数从 GET 请求中解析):

if (dev_filter!="") and (dev_filter!="-1"): 
    device_list = Device.objects.all().filter(device_model = dev_filter) 
else: 
    device_list = Device.objects.all() 
 
dev_status_list = [] 
for dev in device_list: 
    try: 
        dev_status_list.append(DeviceTest.objects.filter(device_id=dev.pk).latest('created_at').status) 
    except: 
        dev_status_list.append("Not checked") 
 
device_list = [device_list for (dev_status_list, device_list) in sorted(zip(dev_status_list, device_list))] 
 
if (order == '-'): 
    device_list.reverse() 

此代码在 Python 2.7/Django 1.11 中运行良好,但在 Python 3.7/Django 2.1 中运行不正常

Django 标记为错误 sorted(zip(dev_status_list, device_list)) 函数:

TypeError: '<' not supported between instances of 'Device' and 'Device' 

我看到这个问题有两种解决方案:要么使用

device_list = [device_list for (dev_status_list, device_list) in sorted(zip(dev_status_list, device_list), key=lambda x: (x[0],x[1].__str__()))] 

或者添加__lt__方法到Device模型:

def __lt__(self, other): 
    return self.__str__() < other.__str__() 

我的问题是 - 改变了什么?出现这个错误是因为Python升级还是Django升级? Python 2.7/Django 1.11 框架中 Device 对象的默认排序方法是什么?我是正确的,它是字符串表示吗?我的哪个解决方案是首选?

请您参考如下方法:

Python 3 引入了新的 ordering comparison :

The ordering comparison operators (<, <=, >=, >) raise a TypeError exception when the operands don’t have a meaningful natural ordering.

在 Python2 中打印 True 并在 Python3 中引发 TypeError 的简单示例

class A: 
    pass 
 
print(A() < A())