Alex D
Alex D

Reputation: 828

Django-Rest-Framework 'str' object has no attribute 'id'

I am creating a call in DRF to POST to the site. I am a bit confused why I get this error. I do not understand why this expects it to be a str. I know there are similiar posts but they still elude be to the solution.

Error

AttributeError: 'str' object has no attribute 'id'
[03/Apr/2018 10:55:12] "POST /api/user/UserProfile/1/ HTTP/1.1" 500 83982

serializer.py looks like and if I remove instance.id i get the same error but just for the next line.

from rest_framework import serializers
from api.models import UserProfile
from django.contrib.auth.models import User


class UserProfileSerializer(serializers.Serializer):
    # id = serializers.UUIDField()
    class Meta:
        model = UserProfile

    def create(self, validated_data):
        return UserProfile.objects.create(**validated_data)

    def update(self, instance, validated_data):
        instance.id = validated_data.get('profile_id', str(instance.id))
        instance.user_id = validated_data.get('user_id', instance.user_id)
        instance.save()
        return instance

View

@csrf_exempt
def user_profile_list(request, user_id):
    try:
        userid = user_id
    except userid.DoesNotExist:
        return HttpResponse(status=404)

    if request.method == 'GET':
        uprofile = UserProfile.objects.all().values()
        list2 = list(uprofile)
        return JsonResponse(list2, safe=False)

    elif request.method == 'POST':
        data = JSONParser().parse(request)
        serializer = UserProfileSerializer(userid, data=data)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(serializer.data, status=201)
        return JsonResponse(serializer.errors, status=400)

urls.py

url(r'^api/user/UserProfile/(?P<user_id>[0-9]+)/$', userprofile.user_profile_list),

Upvotes: 3

Views: 2362

Answers (2)

Nader Alexan
Nader Alexan

Reputation: 2222

AttributeError

The issue lies in the line serializer = UserProfileSerializer(userid, data=data) where you're passing userid to the serializer instead of a user or user profile instance, I say or because the logic is not very clear to me (using a UserProfileSerializer but updating User instance?).

Improvements

What you are trying to accomplish with your code can be done in an easier way:

  1. Use a ModelSerializer instead of a Serializer
  2. Use a ModelViewSet instead of a function-based view (user_profile_list)

A generic version using ModelSerializer and ModelViewSet would be something along the following lines:

serializers.py

from rest_framework import serializers
from api.models import UserProfile


class UserProfileSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserProfile
        # preferably listing the fields to avoid any code breaking
        # if you add fields to the model later on
        fields = '__all__'

views.py

from rest_framework import viewsets

from api.serializers import UserProfileSerializer
from api.models import UserProfile


class UserProfileViewSet(viewsets.ModelViewSet):
    queryset = UserProfile.objects.all()
    serializer_class = UserProfileSerializer

I highly recommend going through DRF's official tutorial, it will save you alot of development time if you understand which parts of your app are already implemented in DRF and can be directly used with little code.

Upvotes: 1

neverwalkaloner
neverwalkaloner

Reputation: 47354

You passed to serializer userid instead of user object. To update object with serializer, you should pass instance as first argument. Change view to this:

elif request.method == 'POST':
    data = JSONParser().parse(request)
    user = User.objects.get(id=userid)
    serializer = UserProfileSerializer(user, data=data)
    ...

Upvotes: 3

Related Questions