Jek*_*son 7 python django django-rest-framework
如果我需要在保存到数据库之前更改一些字段值,因为我认为模型方法clear()是合适的。但尽管我竭尽全力,还是无法给他打电话。
例如,我需要将字段email设置为小写,将字段nda设置为null
模型.py
class Vendors(models.Model):
nda = models.DateField(blank=True, null=True)
parent = models.OneToOneField('Vendors', models.DO_NOTHING, blank=True, null=True)
def clean(self):
if self.nda == "":
self.nda = None
class VendorContacts(models.Model):
....
vendor = models.ForeignKey('Vendors', related_name='contacts', on_delete=models.CASCADE)
email = models.CharField(max_length=80, blank=True, null=True, unique=True)
def clean(self):
if self.email:
self.email = self.email.lower()
Run Code Online (Sandbox Code Playgroud)
序列化器.py
class VendorContactSerializer(serializers.ModelSerializer):
class Meta:
model = VendorContacts
fields = (
...
'email',)
class VendorsSerializer(serializers.ModelSerializer):
contacts = VendorContactSerializer(many=True)
class Meta:
model = Vendors
fields = (...
'nda',
'contacts',
)
def create(self, validated_data):
contact_data = validated_data.pop('contacts')
vendor = Vendors.objects.create(**validated_data)
for data in contact_data:
VendorContacts.objects.create(vendor=vendor, **data)
return vendor
Run Code Online (Sandbox Code Playgroud)
视图.py
class VendorsCreateView(APIView):
"""Create new vendor instances from form"""
permission_classes = (permissions.AllowAny,)
serializer_class = VendorsSerializer
def post(self, request, *args, **kwargs):
serializer = VendorsSerializer(data=request.data)
try:
serializer.is_valid(raise_exception=True)
serializer.save()
except ValidationError:
return Response({"errors": (serializer.errors,)},
status=status.HTTP_400_BAD_REQUEST)
else:
return Response(request.data, status=status.HTTP_200_OK)
Run Code Online (Sandbox Code Playgroud)
据我从文档中了解到
验证模型序列化器时,Django Rest Framework 序列化器不会调用 Model.clean
在处理这个问题时,我找到了两种方法来解决。1. 在序列化器中使用自定义方法。对于我的情况,它看起来像
类 VendorsSerializer(serializers.ModelSerializer): 联系人 = VendorContactSerializer(many=True)
class Meta:
model = Vendors
fields = (...
'nda',
'contacts',
)
def create(self, validated_data):
contact_data = validated_data.pop('contacts')
vendor = Vendors.objects.create(**validated_data)
for data in contact_data:
VendorContacts.objects.create(vendor=vendor, **data)
return vendor
def validate(self, attrs):
instance = Vendors(**attrs)
instance.clean()
return attrs
Run Code Online (Sandbox Code Playgroud)
full_clean()方法。对我来说,它看起来像类 VendorsSerializer(serializers.ModelSerializer): 联系人 = VendorContactSerializer(many=True)
class Meta:
model = Vendors
fields = (...
'nda',
'contacts',
)
def create(self, validated_data):
contact_data = validated_data.pop('contacts')
vendor = Vendors(**validated_data)
vendor.full_clean()
vendor.save()
for data in contact_data:
VendorContacts.objects.create(vendor=vendor, **data)
return vendor
Run Code Online (Sandbox Code Playgroud)
但在这两种情况下,都不会调用 clean() 方法。我真的不明白我做错了什么。
对于 DRF,您可以在保存之前更改序列化器,如下所示...
首先,您应该检查 是否serializer有效,如果有效,valid则更改 所需的对象serializer,然后保存该serializer.
if serializer.is_valid():
serializer.object.user_id = 15 # For example
serializer.save()
Run Code Online (Sandbox Code Playgroud)
更新! 视图.py
class VendorsCreateView(APIView):
"""Create new vendor instances from form"""
permission_classes = (permissions.AllowAny,)
serializer_class = VendorsSerializer
def post(self, request, *args, **kwargs):
data = request.data
if data['nda'] == '':
data['nda'] = None
for contact in data['contacts']:
if contact['email']:
print(contact['email'])
contact['email'] = contact['email'].lower()
serializer = VendorsSerializer(data=request.data)
try:
serializer.is_valid(raise_exception=True)
serializer.save()
except ValidationError:
return Response({"errors": (serializer.errors,)},
status=status.HTTP_400_BAD_REQUEST)
Run Code Online (Sandbox Code Playgroud)
就我而言,我遇到了同样的问题,但通过验证功能,我使用了下面的方法,它对我有用(不排除上面找到的方法):
class CustomViewClass(APIView):
def post(self, request, format=None):
prepared_data_variable = 'some data in needed format'
serializer = CustomSerializer(data=request.data)
if serializer.is_valid(self):
serializer.validated_data['field_name'] = prepared_data_variable
serializer.save()
return Response(data=serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Run Code Online (Sandbox Code Playgroud)
该字符串是我的解决方案的关键serializer.validated_data['field_name'] = prepared_data_variable