0

I've 2 models:-

class Users(models.Model):
    first_name = models.CharField(max_length=255)
    middle_name = models.CharField(max_length=255)


class UserAddress(models.Model):
    line1 = models.CharField(max_length=255)
    country = models.CharField(max_length=255)
    user = models.ForeignKey(Users)

The user model & user address model. Following are the 2 serializers.

class UserAddressSerializer(ModelSerializer):

    class Meta:
        model = UserAddress
        exclude = ('id', 'user')


class UserSerializer(ModelSerializer):
    address = UserAddressSerializer(many=True)

    class Meta:
        model = Users
        fields = '__all__'

    def create(self, validated_data):
        address = validated_data.pop('address', [])
        user = Users.objects.create(**validated_data)

        for ad in address:
            UserAddress.objects.create(user=user, **ad)

        return user

The data I receive from the client is

{
  "first_name": "string",
  "last_name": "string",
  "address": [{
     "line1": "asd",
     "country": "asd",
  }],
}

This is how I create a new user and its corresponding address.

class UserCreate(GenericAPIView):

    serializer_class = UserSerializer

    def post(self, request, *args, **kwargs):

        data = request.data
        serializer = UserSerializer(data=data)
        if not serializer.is_valid():
            return

        user = serializer.save()
        response = {
            'user_id': user.uuid
        }
        return

Now, upon getting the user details back, I receive an error saying

AttributeError: Got AttributeError when attempting to get a value for field `address` on serializer `UserSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `Users` instance.
Original exception text was: 'Users' object has no attribute 'address'.

This is how I get the details of the user, including the address.

class UserDetails(GenericAPIView):
    queryset = Users.objects.all()
    serializer_class = UserSerializer
    lookup_field = 'uuid'

    def get(self, request, uuid, *args, **kwargs):
        user = Users.get_user(uuid)
        if not user:
            return 

        serializer = UserSerializer(instance=user)
        return

I'd read this example of nested relationship, and am doing exactly the same way. why is the error coming up?

Also, can this code be shorten up more (in a nicer clean way) using some DRF mixins? If yes, then how?

1 Answer 1

1

I think the most simple solution for your case is: in model UserAddress add related_name='address'

class UserAddress(models.Model):
    line1 = models.CharField(max_length=255)
    country = models.CharField(max_length=255)
    user = models.ForeignKey(Users, related_name='address')
    #                                 ^^^^^^^^^^^^^^^

or you can add sourse property in serializer:

class UserSerializer(ModelSerializer):
    address = UserAddressSerializer(source='useraddress_set', many=True)

Serializer try to find attribute 'address' in the model User, but by default it is modelname underscore set (useraddress_set in your case), and you try other name, so you can set in the model or specify by source.

in the example you can look on models and find the related_name='tracks'

Sign up to request clarification or add additional context in comments.

5 Comments

Great!! Works like a charm. Thanks @Bear.
glad to help you!
Also, could you also recommend, if et all its possible, to write a much better code using DRF. Basically these CRUD operations.
may be you can use modelviewset instead of two times GenericAPIView.
@PythonEnthusiast You should accept the answer to let future searchers know it solved your problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.