DRF:如何在保存到数据库之前更改模型字段的值

2024-04-14

如果我需要在保存到数据库之前更改一些字段值,因为我认为模型方法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()

序列化器.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

views.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)

正如我从文档中了解到的

Django Rest Framework 序列化器在以下情况下不会调用 Model.clean 验证模型序列化器

在处理这个问题时,我找到了两种方法来解决。 1. 在序列化器中使用自定义方法。对于我的情况,它看起来像

类 VendorsSerializer(serializers.ModelSerializer): 联系人= VendorContactSerializer(许多= 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
  1. Using full_clean()方法。对我来说,它看起来像

类 VendorsSerializer(serializers.ModelSerializer): 联系人= VendorContactSerializer(许多= 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

但在这两种情况下,都不会调用 clean() 方法。我真的不明白我做错了什么。


对于 DRF,您可以在保存之前更改序列化器,如下所示...

首先,您应该检查一下serializer是否有效,如果有效valid然后更改所需的对象serializer然后保存serializer.

if serializer.is_valid():
    serializer.object.user_id = 15  # For example 
    serializer.save() 

UPD! views.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)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

DRF:如何在保存到数据库之前更改模型字段的值 的相关文章

随机推荐