繁体   English   中英

当在请求中的某个字段内建模数据时,如何使用具有多对多字段和外键的 Django Rest Framework 模型序列化创建?

[英]How to serialize creation with Django Rest Framework models with many-to-many field and foreign-key, when models data inside some field in request?

我正在尝试序列化这个 JSON

{
    "api_key": "<something key>",
    "contract_id": 3808,
    "params": {
        "contract_id": 3808,
        "title": "Глюкоза",
        "doctor_description": "Запрашивает у пациента уровень глюкозы в крови.",
        "patient_description": "Пожалуйста, измерьте уровень сахара в крови до еды с помощью глюкометра и укажите его в поле ниже.",
        "thanks_text": null,
        "fields": [
            {
                "category": "glukose",
                "description": "ммоль/л",
                "max": null,
                "min": null,
                "text": "Глюкоза",
                "type": "float",
                "uid": "24c2258b-d338-4184-a114-5cae3721bb16"
            },
            {
                "category": "information",
                "text": "Комментарий",
                "type": "textarea",
                "uid": "93722301-d652-4903-8404-e56da4d31ad7"
            }
        ]
    }
}

在 params 里面有一个模型MeasurementTask ( models.py ) 的实例:

class MeasurementTask(models.Model):
    title = models.CharField(max_length=255)
    doctor_description = models.TextField()
    patient_description = models.TextField()
    thanks_text = models.TextField(null=True)
    contract_id = models.ForeignKey(Contract, on_delete=models.CASCADE)
    fields = models.ManyToManyField(MeasurementTaskGeneric)

    is_sent = models.BooleanField(default=False)
    is_done = models.BooleanField(default=False)

它由 ManyToManyField 与MeasurementTaskGeneric相关:

class MeasurementTaskGeneric(models.Model):
    uid = models.CharField(max_length=255, unique=True)
    category = models.CharField(max_length=255)
    description = models.CharField(max_length=255, null=True)
    max_value = models.FloatField(null=True)
    min_value = models.FloatField(null=True)
    text = models.CharField(max_length=255)
    value_type = models.CharField(max_length=255)

并使用带有Contract外键:

class Contract(models.Model):
    contract_id = models.IntegerField(unique=True, primary_key=True)
    speaker_active = models.BooleanField(default=False)

    def __str__(self):
        return "Contract id - {}".format(self.contract_id)

随着请求,我需要创建MeasurementTask实例并创建(或获取,如果它已经存在)的MeasurementTaskGeneric实例,通过Contract.contract_id获取Contract的实例并将其添加到MeasurementTask.contract_id

我正在使用这个序列化器来序列化它( serializers.py ):

from rest_framework import serializers
from medsenger_agent.models import MeasurementTask, MeasurementTaskGeneric


class TaskGenericSerializer(serializers.ModelSerializer):
    class Meta:
        model = MeasurementTaskGeneric
        fields = '__all__'

    def get_fields(self):
        result = super().get_fields()
        type_ = result.pop('value_type')
        result['type'] = type_
        return result


class TaskModelSerializer(serializers.ModelSerializer):
    contract_id = serializers.ReadOnlyField(
        source='contract.contract_id', )
    fields = serializers.ListField(
        child=TaskGenericSerializer())

    class Meta:
        model = MeasurementTask
        fields = '__all__'


class TaskSerializer(serializers.Serializer):
    api_key = serializers.CharField()
    contract_id = serializers.IntegerField()
    params = TaskModelSerializer()

views.py

from rest_framework.generics import CreateAPIView
from medsenger_agent import serializers

class OrderApiView(CreateAPIView):
    serializer_class = serializers.TaskSerializer

最后我收到了这个错误

Traceback (most recent call last):
  File "/Users/tikhon/opt/anaconda3/lib/python3.8/site-packages/asgiref/sync.py", line 482, in thread_handler
    raise exc_info[1]
  File "/Users/tikhon/opt/anaconda3/lib/python3.8/site-packages/django/core/handlers/exception.py", line 38, in inner
    response = await get_response(request)
  File "/Users/tikhon/opt/anaconda3/lib/python3.8/site-packages/django/core/handlers/base.py", line 233, in _get_response_async
    response = await wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/tikhon/opt/anaconda3/lib/python3.8/site-packages/asgiref/sync.py", line 444, in __call__
    ret = await asyncio.wait_for(future, timeout=None)
  File "/Users/tikhon/opt/anaconda3/lib/python3.8/asyncio/tasks.py", line 455, in wait_for
    return await fut
  File "/Users/tikhon/opt/anaconda3/lib/python3.8/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/Users/tikhon/opt/anaconda3/lib/python3.8/site-packages/asgiref/sync.py", line 486, in thread_handler
    return func(*args, **kwargs)
  File "/Users/tikhon/opt/anaconda3/lib/python3.8/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/Users/tikhon/opt/anaconda3/lib/python3.8/site-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/Users/tikhon/opt/anaconda3/lib/python3.8/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "/Users/tikhon/opt/anaconda3/lib/python3.8/site-packages/rest_framework/views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/Users/tikhon/opt/anaconda3/lib/python3.8/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
  File "/Users/tikhon/opt/anaconda3/lib/python3.8/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "/Users/tikhon/opt/anaconda3/lib/python3.8/site-packages/rest_framework/generics.py", line 190, in post
    return self.create(request, *args, **kwargs)
  File "/Users/tikhon/opt/anaconda3/lib/python3.8/site-packages/rest_framework/mixins.py", line 19, in create
    self.perform_create(serializer)
  File "/Users/tikhon/opt/anaconda3/lib/python3.8/site-packages/rest_framework/mixins.py", line 24, in perform_create
    serializer.save()
  File "/Users/tikhon/opt/anaconda3/lib/python3.8/site-packages/rest_framework/serializers.py", line 205, in save
    self.instance = self.create(validated_data)
  File "/Users/tikhon/opt/anaconda3/lib/python3.8/site-packages/rest_framework/serializers.py", line 170, in create
    raise NotImplementedError('`create()` must be implemented.')
NotImplementedError: `create()` must be implemented.

我知道我需要提供.create()方法来创建序列化程序,但我不知道如何...

由于低代表,我无法发表评论,但这是来自classyDRF的功能

def create(self, request, *args, **kwargs):
    serializer = self.get_serializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    self.perform_create(serializer)
    headers = self.get_success_headers(serializer.data)
    return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

所以对你来说,这可能意味着:

from rest_framework.generics import CreateAPIView
from medsenger_agent import serializers

    class OrderApiView(CreateAPIView):
        serializer_class = serializers.TaskSerializer
        
        def create(self, request, *args, **kwargs):
            serializer = self.get_serializer(data=request.data)
            serializer.is_valid(raise_exception=True)
            self.perform_create(serializer)
            headers = self.get_success_headers(serializer.data)
            return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

编辑:classyDRF 不是官方文档。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM