Coder Social home page Coder Social logo

Comments (3)

ruscoder avatar ruscoder commented on September 16, 2024

@yinkanghong Hello! I'm not sure, but it could be possibly fixed in 4.0.2. It will be great if you can check your code with the latest version of the package and leave your feedback.

from drf-writable-nested.

yinkh avatar yinkh commented on September 16, 2024

My drf-nested-serializer version is 0.4.1,I updated it to 0.4.2 which is latest version now,and this issue still exist.I will try to write a PR this week.

from drf-writable-nested.

yinkh avatar yinkh commented on September 16, 2024

I find this is a issue for DRF(issue2403issue2996),In DRF validators/BaseUniqueForValidator this is a method exclude_current_instance code is:

def exclude_current_instance(self, attrs, queryset):
    """
    If an instance is being updated, then do not include
    that instance itself as a uniqueness conflict.
    """
    if self.instance is not None:
        return queryset.exclude(pk=self.instance.pk)
    return queryset

,when use drf-writable-nested,the validation is handle by DRF,the ModelSerializer or ListSerializer's child(which is nested ModelSerializer) only have id/pk in initial_data,but don't has instance object.So if we convert id/pk to instance object in ModelSerializer this issue will be solved.I find there ways to do this:

First way is convert id/pk to instance:

class StaffUserCreateSerializer(ModelSerializer):

    def to_internal_value(self, data):
        if 'pk' in data and 'pk' in self.fields:
            print(data)
            try:
                obj_id = self.fields['pk'].to_internal_value(data['pk'])
            except serializers.ValidationError as exc:
                raise serializers.ValidationError({'pk': exc.detail})
            self.instance = self.Meta.model.objects.get(id=obj_id)
        return super(StaffUserCreateSerializer, self).to_internal_value(data)

    class Meta:
        model = User
        fields = ('pk', 'name', 'tel',)

class StaffModifySerializer(WritableNestedModelSerializer):
    user = StaffUserCreateSerializer(label='User', partial=True)

    class Meta:
        model = Staff
        fields = ('user', 'job_state', 'bank_no', 'social_security_no', 'on_job')

Second way is change the queryset to exclued the pk:

class StaffUserCreateSerializer(ModelSerializer):

    def to_internal_value(self, data):
        if 'pk' in data and 'pk' in self.fields:
            print(data)
            try:
                obj_id = self.fields['pk'].to_internal_value(data['pk'])
            except serializers.ValidationError as exc:
                raise serializers.ValidationError({'pk': exc.detail})
            for field in self.fields.values():
                for validator in field.validators:
                    from rest_framework.validators import UniqueValidator
                    if type(validator) == UniqueValidator:
                        # Exclude id from queryset for checking uniqueness
                        validator.queryset = validator.queryset.exclude(id=obj_id)
        return super(StaffUserCreateSerializer, self).to_internal_value(data)

    class Meta:
        model = User
        fields = ('pk', 'name', 'tel',)

class StaffModifySerializer(WritableNestedModelSerializer):
    user = StaffUserCreateSerializer(label='User', partial=True)

    class Meta:
        model = Staff
        fields = ('user', 'job_state', 'bank_no', 'social_security_no', 'on_job')

Third way is convert id/pk to instance in WritableNestedModelSerializer:

class StaffUserCreateSerializer(ModelSerializer):
    class Meta:
        model = User
        fields = ('pk', 'name', 'tel',)

class StaffModifySerializer(WritableNestedModelSerializer):
    user = StaffUserCreateSerializer(label='User', partial=True)

   def __init__(self, *args, **kwargs):
        super(StaffModifySerializer, self).__init__(*args, **kwargs)
        import copy
        initial_data = copy.deepcopy(self.initial_data)
        relations, reverse_relations = self._extract_relations(initial_data)

        for field_name, (field, field_source) in relations.items():
            data = self.initial_data[field_name]
            model_class = field.Meta.model
            pk = self._get_related_pk(data, model_class)
            try:
                obj = model_class.objects.get(pk=pk, )

                self.fields[field_name] = self._get_serializer_for_field(
                    self.fields[field_name], instance=obj, data=data)
            except (model_class.DoesNotExist, ValueError):
                pass

    class Meta:
        model = Staff
        fields = ('user', 'job_state', 'bank_no', 'social_security_no', 'on_job')

Third way can't used for many_to_many fields which has unique=True.

I think all of this there solutions is not beautiful enough to write a PR,so i will close this issue.

Thank for this good library,drf-writable-nested really help me a lot. 😄

from drf-writable-nested.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.