我正在使用Django Rest Framework构建API。主要要求是它应允许在呼叫中灵活地包含额外字段。基于POST调用,我想在Django中创建一个新记录,其中一些字段(名称和数字不同)应添加到JSON字段(lead_request)。
我怀疑是否应该使用ModelSerializer,因为我不知道如何处理应该作为JSON合并到一个字段中的各个字段。在create方法中,我无法将其他字段合并到JSON中,因为它们未经过验证。
class Leads(models.Model):
campaign_id = models.ForeignKey(Campaigns, on_delete=models.DO_NOTHING)
lead_email = models.EmailField(null=True, blank=True)
lead_request = JSONField(default=dict, null=True, blank=True)
class LeadCreateSerializer(serializers.ModelSerializer):
def get_lead_request(self):
return {key: value for key, value in self.request.items() if key.startswith('rq_')}
class Meta:
model = Leads
fields = ['campaign_id',
'lead_email',
'lead_request']
def create(self, validated_data):
return Leads.objects.create(**validated_data)
文档主要讨论分配validated_data,但这里不可能。任何指针都是有用的,因为我是一个没有经验的程序员,我看到解决方案的潜力,但不知道从哪里开始。
如果我理解正确并且你想通过URL接收参数,这里有一个如何实现你想要的例子:
class LeadViewSet(viewsets.ModelViewSet):
def create(self, request, *args, **kwargs):
data = request.data
lead_request = generate_lead_request(request)
data['lead_request'] = lead_request
serializer = self.get_serializer(data=data)
serializer.is_valid(raise_exception=True)
...
在generate_lead_request
上,您可以解析可能通过request.data
(正文)以及request.query_params
发送的所有其他字段。
如果我理解这个问题正确主要障碍这里是我们不知道JSON
的确切lead_request
数据格式。我正在考虑这个问题的两种可能的解决方案模型。我不确定它们中的任何一个是否合适。只想分享我的意见。
让我们假设数据以这种格式传递给LeadCreateSerializer
data = {
'campaign_id': campaign_id,
'lead_email': lead_email,
'lead_request': {
# lead_request
}
}
然后这很容易,正常模型序列化器应该能够做到这一点。如果数据格式不正确,并且可以在传递给序列化程序之前进行组织,那么这些视图或函数应该负责使其格式正确。
让我们假设在LeadCreateSerializer
中传递数据之前无法组织数据,那么我们需要在验证或获取lead_request期间获取相关值。因为这个serializer
的责任是创建新实例并且为了验证字段所以我们假设在self.context
中存在整个self.context.request
。
class LeadCreateSerializer(serializers.ModelSerializer):
def generate_lead_request(self, data):
# do your all possible validation and return
# in dict format
def get_lead_request(self):
request = self.context.request
lead_request = self.generate_lead_request(request.data)
return lead_request
class Meta:
model = Leads
fields = ['campaign_id',
'lead_email',
'lead_request']