代码之家  ›  专栏  ›  技术社区  ›  pyprism

Django动态字段注释时的强制转换

  •  1
  • pyprism  · 技术社区  · 2 年前

    假设我想将此数据保存到数据库中:

    {
            "fields": [
                {
                    "field_type": "number",
                    "name": "field_1",
                    "value": 8223,
                },
                {
                    "field_type": "string",
                    "name": "field_2",
                    "value": "demo"
                  
                },
                {
                    "field_type": "bool",
                    "name": "field_3",
                    "value": true
                  
                }
            ],
            "blockchain_id": 47,
            "name": "event",
            "block_number": 3916102,
        }
    

    在这里 value 基于 field_type 价值这是我的模型:

    class Event(models.Model):
        blockchain_id = models.IntegerField()
        name = models.CharField(max_length=100)
        block_number = models.IntegerField()
        fields = models.ManyToManyField(EventField)
    
    class EventField(models.Model):
        TYPE_CHOICES = (
            ('number', 'Number'),
            ('string', 'String'),
            ('bool', 'Boolean'),
        )
        field_type = models.CharField(max_length=6, choices=TYPE_CHOICES)
        name = models.CharField(max_length=100)
        value = models.CharField(max_length=100)
    

    我正在保存动态 价值 作为性格(你可以提出更好的建议)。然后,当我重新获得我想要基于的价值观时 字段类型 价值到目前为止,我的问题是:

    Event.objects.filter(id=_id).annotate(fields_value=Case(
                When(fields__field_type='number', then=Cast('fields__value', output_field=models.IntegerField())),
                When(fields__field_type='string', then=Cast('fields__value', output_field=models.CharField())),
                When(fields__field_type='bool', then=Cast('fields__value', output_field=models.BooleanField())),
                output_field=Case(When(fields__field_type='number', then=models.IntegerField()))))
    

    现在我收到这个错误消息 Cannot resolve expression type, unknown output_field 。也许我错过了什么。如何使用基于field_type的强制转换返回值?

    1 回复  |  直到 2 年前
        1
  •  0
  •   willeM_ Van Onsem    2 年前

    不能使用这种动态转换:对于SQL,每一列都有一个特定的类型,并且所有记录都对该列使用相同的类型。

    您需要在Django/Python层执行此操作,例如:

    class EventField(models.Model):
        TYPE_CHOICES = (
            ('number', 'Number'),
            ('string', 'String'),
            ('bool', 'Boolean'),
        )
        field_type = models.CharField(max_length=6, choices=TYPE_CHOICES)
        name = models.CharField(max_length=100)
        value = models.CharField(max_length=100)
    
        @property
        def typed_value(self):
            if self.field_type == 'number':
                return int(self.value)
            if self.field_type == 'string':
                return self.value
            if self.field_type == 'bool':
                return self.value.casefold() == 'true'
            raise ValueError('Invalid field type.')

    然后可以使用检查值 my_event_field.typed_value