2

Django プロジェクトを Python 2.7/Django 1.11 から Python 3.7/Django 2.1 に移行しようとしています。

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'

この問題には 2 つの解決策があります。

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 のアップグレードが原因で発生しますか? DeviceオブジェクトのPython 2.7/Django 1.11フレームワークのデフォルトのソート方法は何ですか? 文字列表現だったのは正しいですか?そして、私のソリューションのどれが好まれますか?

4

2 に答える 2

2

Python 3 では、新しい順序比較が導入されています。

順序比較演算子 (<、<=、>=、>)は、オペランドに意味のある自然順序付けがない場合、TypeError例外を発生させます。

Python2 で出力し、 Python3Trueで a を上げる簡単な例TypeError

class A:
    pass

print(A() < A())
于 2018-08-21T10:07:36.230 に答える