我有一个简单的ModelSerializer
,如下所示:
class DBaaSOrderSerializer(serializers.ModelSerializer):
class Meta:
model = DBaaSOrder
fields = '__all__'
以上还有一些validate
方法与此问题无关。
现在,我在基于类的视图中使用上面的序列化程序,如下所示:
class DBaaSOrderView(generics.ListCreateAPIView):
serializer_class = DBaaSOrderSerializer
permission_classes = (permissions.IsAuthenticated,)
def get_queryset(self):
usd = UsdDBActions()
orders = DBaaSOrder.objects.filter(user=self.request.user).order_by('updated_at')
for change_ref, change_status, updated_at in orders.values_list('change_ref', 'change_status', 'updated_at'):
usd_change_status = usd.get_rfc_status(change_ref)
usd_change_updated_at = usd.get_last_mod_date(change_ref)
if change_status != usd_change_status:
orders.filter(change_ref=change_ref).update(change_status=usd_change_status)
if updated_at != usd_change_updated_at:
orders.filter(change_ref=change_ref).update(updated_at=usd_change_updated_at)
return orders.filter(change_status__in=VALID_USD_STATUSES)[:MAX_ORDERS]
@staticmethod
def get_dns(value):
dns_records = DNS.objects.all()
for dns in dns_records:
if dns.server in value and dns.domain in value:
return dns
@staticmethod
def get_backup_plan(value):
backup_plans = BackupPlan.objects.all()
for backup_plan in backup_plans:
if backup_plan.customer_policy_name in value and backup_plan.retention in value:
return backup_plan
def post(self, request, *args, **kwargs):
data = request.data
data['user'] = request.user.pk
dns_record = self.get_dns(data['dns'])
backup_plan = self.get_backup_plan(data['backup'])
dns_record_pk = dns_record.pk
backup_plan_pk = backup_plan.pk
data['dns'] = dns_record_pk
data['backup'] = backup_plan_pk
serializer = DBaaSOrderSerializer(data=data)
if serializer.is_valid():
usd = UsdDBActions()
data = request.data
usd_data = {
'organization': int(data['organization_pk']),
'category': 'SSC.DBM.DB.ADD',
'assignee': request.user.username,
}
response = usd.create_rfc(usd_data)
try:
result = response.json()
if result['code'] == 200:
change_ref = int(response.json()['reference_number'])
data['user'] = request.user
data['change_ref'] = int(response.json()['reference_number'])
data['change_status'] = usd.get_rfc_status(change_ref)
data['dns'] = dns_record
data['backup'] = backup_plan
DBaaSOrder.objects.create(**data)
return Response({
'message': f"The RFC {data['change_ref']} has been successfully created!",
'code': 200
})
一切都按预期工作但我不喜欢的是我有2个方法get_dns()
和get_backup_plan()
来获取dns
或{{的实际模型对象1}}字段。有没有更简单的方法来做到这一点?
这样做的原因是:
backup
,serializer = DBaaSOrderSerializer(data=data)
应包含该字段的data
; pk
,DBaaSOrder.objects.create(**data)
应包含模型字段的实例; 更多,data
和dns
是外键:
backup
主要模型如下:
class DNS(models.Model):
server = models.CharField(max_length=64)
domain = models.CharField(max_length=64)
def __str__(self):
return f'{self.server} - {self.domain}'
class BackupPlan(models.Model):
customer_policy_name = models.CharField(max_length=64)
retention = models.CharField(max_length=64)
def __str__(self):
return f'{self.customer_policy_name} - {self.retention}'
答案 0 :(得分:1)
这里有两个相关的问题。首先是你把逻辑转向" 192.168.0.1 - test.domain.com"进入DNS的一个实例。其次是你如何进行数据库查找。
这种东西总是属于序列化器;这是负责将接收的数据转换为正确格式的代码。该特定逻辑属于验证方法;这些名称为validate_<fieldname>
,因此我们需要validate_dns
和validate_backup
。
目前进行数据库查找的方式效率很低。我们可以通过拆分输入然后使用该数据进行直接数据库查询来更简单地完成它。
为了完成所有这些工作,我们需要覆盖这些字段的定义以使它们成为CharFields,以便它们接受任意数据。然后,validate方法将把它们转换为实际的模型实例。
所以:
class DBaaSOrderSerializer(serializers.ModelSerializer):
dns = serializers.CharField()
backup = serializers.CharField()
class Meta:
model = DBaaSOrder
fields = '__all__'
def validate_dns(self, value):
try:
server, domain = value.split(' - ')
except ValueError:
raise serializers.ValidationError('not in correct format')
try:
instance = DNS.objects.get(server=server, domain=domain)
except DNS.DoesNotExist:
raise serializers.ValidationError('no matching DNS')
return instance
def validate_backup(self, value):
... similar to above...
现在你可以摆脱post
中的自定义逻辑。