JP *_*ura 3 python django django-models django-rest-framework
如何创建 和serializers.Patient并serializers.Temperature以这样的方式:
models.Patient与 具有一对多关系models.Temperaturesserializers.Patient是一个子类serializers.ModelSerializerserializers.Patient(反)将温度序列化为浮点数列表给定一个使用Django 框架实现的快速脏病人医疗记录 RESTful API 。
患者定义为models.Patient:
class Patient(models.Model):
created_at = models.DateField()
name = models.CharField(max_length=200)
updated_at = models.DateField()
Run Code Online (Sandbox Code Playgroud)
和models.Temperature:
class Temperature(models.Model):
created_at = models.DateField()
patient = models.ForeignKey(
Patient,
db_column='patient',
related_name='temperatures',
on_delete=models.CASCADE,
)
updated_at = models.DateField()
value = models.FloatField()
Run Code Online (Sandbox Code Playgroud)
CRUD 操作/patients(反)序列化为models.Temperature列表float,因此 aPOST应该只需要:
{
"name": "John Connor",
"temperatures": [36.7, 40, 35.9]
}
Run Code Online (Sandbox Code Playgroud)
GET进行手术时
{
"created_at": "1985-03-25",
"name": "John Connor",
"temperatures": [36.7, 40, 35.9],
"updated_at": "2021-08-29"
}
Run Code Online (Sandbox Code Playgroud)
但是端点处的操作/patients/<id>/temperatures/应返回所有属性:
[
{
"created_at": "1985-03-25",
"value": 36.7,
"updated_at": "2021-08-29"
},
{
"created_at": "1985-03-25",
"value": 40.0,
"updated_at": "2021-08-29"
},
{
"created_at": "1985-03-25",
"value": 35.9,
"updated_at": "2021-08-29"
}
]
Run Code Online (Sandbox Code Playgroud)
此功能可以通过子类化标准DRF序列化器来实现还是需要自定义serializers.Serializer子类?
小智 5
我们来尝试分析一下这里的情况。我们需要用列表输入温度数据。因此,让我们用于ListField此目的。所以,我们应该这样开始:
class PatientSerializer(ModelSerializer):
temperatures = ListField(child=FloatField())
Run Code Online (Sandbox Code Playgroud)
这样做的目的是期望用户提供一个浮点数列表。GET但是我们在使用操作的时候如何得到创建的病人的体温数组呢?为此,我们向该字段添加一个源。参数上写的任何内容source都会被转换为patient.field例如:
class PatientSerializer(ModelSerializer):
temperatures = ListField(child=FloatField(), source="temperature_list")
Run Code Online (Sandbox Code Playgroud)
这source="temperature_list将在序列化对象时使用patient.temperature_list并显示结果。现在让我们向原始模型添加一些属性,以便我们可以获得如下所示的干净温度数组:
class Patient(models.Model):
created_at = models.DateField()
name = models.CharField(max_length=200)
updated_at = models.DateField()
@property
def temperature_list(self):
return [temperature.value for temperature in self.temperatures.all()]
Run Code Online (Sandbox Code Playgroud)
我们快完成了。现在我们需要重写 的create方法,PatientSerializer以便它可以保存列表中存在的温度。现在,要从 中获取温度数据,validated_data我们需要使用source与 的参数中使用的相同字段ListField,即temperature_list。因此,我们需要弹出此数据,创建用户,验证温度列表项,创建与患者相关的温度对象。让我们创建一个TemperatureSerializer这样的:
class TemperatureSerializer(ModelSerializer):
class Meta:
model = Temperature
fields = ("created_at", "value", "updated_at", "patient")
extra_kwargs = {
"patient": {"write_only": True},
"created_at": {"required": False},
"updated_at": {"required": False},
}
Run Code Online (Sandbox Code Playgroud)
现在,我们需要做的就是编写 create 方法。我们可以这样写:
def create(self, validated_data):
temperatures = validated_data.pop("temperature_list")
now = datetime.now().strftime("%Y-%m-%d")
patient = Patient.objects.create(
created_at=now, updated_at=now, **validated_data
)
for temperature in temperatures:
now = datetime.now().strftime("%Y-%m-%d")
temperature_serializer = TemperatureSerializer(
data={
"value": temperature,
"created_at": now,
"updated_at": now,
"patient": patient.id,
}
)
temperature_serializer.is_valid(raise_exception=True)
temperature_serializer.save()
return patient
Run Code Online (Sandbox Code Playgroud)
最后,让我们将所有内容放在一起,文件如下所示serializers.py:
from rest_framework.serializers import ModelSerializer, ListField, FloatField
from datetime import datetime
from .models import Patient, Temperature
class TemperatureSerializer(ModelSerializer):
class Meta:
model = Temperature
fields = ("created_at", "value", "updated_at", "patient")
extra_kwargs = {
"patient": {"write_only": True},
"created_at": {"required": False},
"updated_at": {"required": False},
}
class PatientSerializer(ModelSerializer):
temperatures = ListField(child=FloatField(), source="temperature_list")
def create(self, validated_data):
temperatures = validated_data.pop("temperature_list")
now = datetime.now().strftime("%Y-%m-%d")
patient = Patient.objects.create(
created_at=now, updated_at=now, **validated_data
)
for temperature in temperatures:
now = datetime.now().strftime("%Y-%m-%d")
temperature_serializer = TemperatureSerializer(
data={
"value": temperature,
"created_at": now,
"updated_at": now,
"patient": patient.id,
}
)
temperature_serializer.is_valid(raise_exception=True)
temperature_serializer.save()
return patient
class Meta:
model = Patient
fields = ("created_at", "name", "temperatures", "updated_at")
extra_kwargs = {
"created_at": {"required": False},
"updated_at": {"required": False},
}
Run Code Online (Sandbox Code Playgroud)
views.py看起来是这样的:
from rest_framework.generics import ListCreateAPIView, ListAPIView
from .models import Patient, Temperature
from .serializers import PatientSerializer, TemperatureSerializer
class PatientListCreateView(ListCreateAPIView):
serializer_class = PatientSerializer
queryset = Patient.objects.all()
class TemperatureListView(ListAPIView):
serializer_class = TemperatureSerializer
def get_queryset(self, *args, **kwargs):
patient_id = self.kwargs["pk"]
return Temperature.objects.filter(patient_id=patient_id)
Run Code Online (Sandbox Code Playgroud)
和urls.py文件:
from django.urls import path
from . import views
urlpatterns = [
path("patients", views.PatientListCreateView.as_view(), name="patient-list"),
path(
"patients/<int:pk>/temperatures/",
views.TemperatureListView.as_view(),
name="patient-temperature-list",
),
]
Run Code Online (Sandbox Code Playgroud)
我希望这回答了你的问题。
| 归档时间: |
|
| 查看次数: |
510 次 |
| 最近记录: |