【问题标题】:Django Rest Framework: Accessing validated_data outside of def create() methodDjango Rest Framework:在 def create() 方法之外访问 valid_data
【发布时间】:2020-11-04 13:45:28
【问题描述】:

所以我知道我的问题写得很糟糕,但我不确定最好的表达方式。让我解释一下。

我正在尝试让我的序列化程序类处理特定字段的多个值类型。例如,我需要将名为“Temp (C)”、“Humidity(%)”等的项目的 JSON 值都发布在我的序列化程序类中名为“value”的特定字段下。当然,我在 models.py 中也有一个名为“value”的模型。

这是我目前所拥有的:

models.py

class DataValueTable(models.Model):
    timestamp = models.FloatField()
    sensorName = models.TextField(null=True)
    value = models.FloatField()

views.py

class DataValueTableList(APIView):

    parser_classes = [JSONParser]
    authentication_classes = []
    permission_classes = []

    def post(self, request, format=None):

        serializer = DataValueTableSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

serializer.py

class DataValueTableSerializer(serializers.ModelSerializer):
    class Meta: 
        model = DataValueTable
        fields = ['id', 'System Time', 'Node ID', 'Temp (C)', 'Humidity(%)', 'Pyra (WPM)',]
        extra_kwargs = {
            "Node ID": {"source": "sensorName"},
            "System Time": {"source": "timestamp"},
            "Temp (C)": {"source": "value"},
            "Humidity(%)": {"source": "value"},
            "Pyra (WPM)": {"source": "value"},
        }

    def create(self, validated_data):
        return DataValueTable.objects.create(**validated_data)

对于 serializer.py: 我作为 JSON 发布的值与 models.py 中的模型名称不同,因此我使用“extra_kwargs”将 JSON 名称映射到模型。

这是我要发布的内容:

{
    "Node ID": "2",
    "Temp (C)": "22.6",
    "Humidity(%)": "29.67",
    "Pyra (WPM)": "118.9",
    "System Time": "1592287220"
}

回复如下:

{
    "id": 126,
    "System Time": 1592287220.0,
    "Node ID": "2",
    "Temp (C)": 2.69,
    "Humidity(%)": 2.69,
    "Pyra (WPM)": 2.69,
}

我能够将所有这些 JSON 项目发布到 Post,但每个项目的值都相同,这并不好。我知道出了什么问题,“def create”方法中的“validated_data”只跟踪数据,直到“value”的第一个实例,然后它停止。在这种情况下,它会遍历我的 DataValueTableSerializer 类中的“字段”列表,并在“Temp (C)”处停止,因为这是“值”的第一个实例。

所以这是我的问题: 有没有办法在 DataValueTableSerializer 类的“def create”方法中截断这个被发布的 JSON 数据之前访问它?我希望如果我可以访问数据,我可能会手动映射我需要的值,类似于我在“extra_kwargs”中所做的那样。或者,如果有人知道比我尝试做的更好的方法,那就太棒了!

【问题讨论】:

    标签: python json django django-rest-framework serialization


    【解决方案1】:

    我不确定您要做什么。但是您正在寻找的是save() 方法。覆盖保存方法并在保存之前执行您需要做的事情。

    class DataValueTableSerializer(serializers.ModelSerializer):
        class Meta: 
            model = DataValueTable
            fields = ['id', 'System Time', 'Node ID', 'Temp (C)', 'Humidity(%)', 'Pyra (WPM)',]
            extra_kwargs = {
                "Node ID": {"source": "sensorName"},
                "System Time": {"source": "timestamp"},
                "Temp (C)": {"source": "value"},
                "Humidity(%)": {"source": "value"},
                "Pyra (WPM)": {"source": "value"},
            }
        
        def save(self):
            #self.validated_data contains you data
    

    注意: 您不能在同一字段中保存多个值。即使您访问或修改数据,您的值字段也只会获得一个值。 如果你想保存三个不同的值,你需要在模型中使用三个不同的字段。

        class DataValueTable(models.Model):
            timestamp = models.FloatField()
            sensorName = models.TextField(null=True)
            temp = models.FloatField()
            humidity = models.FloatField()
            pyra = models.FloatFiled()
    

    对应的序列化器是

    class DataValueTableSerializer(serializers.ModelSerializer):
    class Meta: 
        model = DataValueTable
        fields = ['id', 'System Time', 'Node ID', 'Temp (C)', 'Humidity(%)', 'Pyra (WPM)',]
        extra_kwargs = {
            "Node ID": {"source": "sensorName"},
            "System Time": {"source": "timestamp"},
            "Temp (C)": {"source": "temp"},
            "Humidity(%)": {"source": "humidity"},
            "Pyra (WPM)": {"source": "pyra"},
        }
    
    

    【讨论】:

    • 啊,是的,我忘了提到我的任务是在不更改模型的情况下执行此操作。我认为这个想法是在未来拥有更多/不同的值类型,而不必每次都更改模型然后必须迁移。所以这种方法肯定会奏效,但不幸的是我不能使用它。我的顾问似乎认为可以在同一个字段中保存多个值,但我花了超过 15 个小时试图弄清楚如何去做,我认为你是对的,你只是不能保存多个值到同一个领域。
    • @LukeyP 您无法在单个“FloatField”中保存多个值。如果您的传感器名称指示保存的值(湿度、温度、高温),您可以将每个值保存在不同的行中并进行相应的解析。如果有帮助,请考虑接受/支持答案。谢谢:)
    • 哦,实际上,这也很有用。你知道我会怎么做吗?或者我可以用谷歌搜索更多关于如何做的信息?我也投了赞成票,但我的声誉太低而无法显示:(
    • 实际上它只是简单的数据库插入/解析。只需将每个值保存在新行中并根据 sensorName 进行解析。虽然,我认为这与这个问题无关。考虑接受这个答案(如果你认为它是正确的),如果你自己找不到答案,就创建一个新的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-10
    • 1970-01-01
    • 1970-01-01
    • 2021-04-03
    • 2021-12-02
    • 1970-01-01
    • 2018-06-07
    相关资源
    最近更新 更多