'TypeError: Field 'id' expected a number but got <django.contrib.auth.models.AnonymousUser object at 0x048C7E90>

Cannot cast AnonymousUser to int.
Are you trying to use it in place of User?

I am unsure how to adjust my code to stop generating this error when i make a post request to my url. I have attached code for my serializers, views and models.

class ActivitySessionSerializer(serializers.Serializer):
    activity_name = serializers.CharField(min_length=1, max_length=100)

    def create(self, validated_data):
        activity, created = Activity.objects.get_or_create(name=validated_data['activity_name'], 
        owner=self.context['request'].user)

        return ActivitySession.objects.create(activity=activity, start_time=datetime.datetime.now())



class StartSessionView(generics.CreateAPIView):
    serializer_class = serializers.ActivitySessionSerializer


    User = get_user_model()
    
    class ActivityType(models.Model):
        name = models.CharField(max_length=100)
        user = models.ForeignKey(User, on_delete=models.CASCADE)

    class Activity(models.Model):
        name = models.CharField(max_length=100)
        owner = models.ForeignKey(User, on_delete=models.CASCADE)
        activity_type = models.ForeignKey(ActivityType, on_delete=models.CASCADE, null=True, blank=True)

    class ActivitySession(models.Model):
        activity = models.ForeignKey(Activity, on_delete=models.CASCADE)
        start_time = models.DateTimeField()
        end_time = models.DateTimeField()


    urlpatterns = [
        path('starting_session/', views.StartSessionView.as_view()),
    ]

I believe i solved it by changing line

Activity.objects.get_or_create(name=validated_data['activity_name'], 
        owner=self.context['request'].user)

to

Activity.objects.get_or_create(name=validated_data['activity_name'], 
        owner=self.context['request'].user.id)

I had to add id field specifically instead of the total user object



Solution 1:[1]

For those who also come here, one possible bug is (and this is what I encountered):

you might call the anonymous user instance somewhere else through foreignkey or reverse foreignkey.

For example, in my code:

  1. I received the anonymous request in my CustomView like this:
class CustomView(RetrieveAPIView):
    serializer_class = CustomSerializer
    queryset =CustomModel.objects.all()
  1. The CustomModel of the CustomView has a reverse foreignkey-which_model, like this:
from django.contrib.auth import get_user_model
User = get_user_model()

class CustomModel(BaseModel):
    name = models.CharField(verbose_name="Custom name", max_length=256)
 
class CustomRecord(BaseModel):
    which_user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="related user")
    which_model = models.ForeignKey("CustomModel", on_delete=models.CASCADE, verbose_name="related model",related_name="user_record",)

  1. To get the related CustomRecord instance simultaneously when getting the CustomModel instance in the anonymous request, I used the SerializerMethodField in the CustomSerializer like this:
class CustomSerializer(ModelSerializer):
    related_user_record = SerializerMethodField(read_only=True, source="user_record")
    def get_related_user_record(self, obj):
        # This is where the problem is !!!!
        user_record = CustomRecord.objects.filter(
            which_model=obj.id, which_user=self.context["request"].user
        )
        if not user_record:
            return None
        else:
            return CustomRecordSerializer(user_record.get()).data

Because I used the self.context["request"].user in get_related_user_record function, django try to convert the id of user instance to int; However, like @Brad Solomon said, the anonymous user's id or pk is None., that's where the error comes from. And honestly, djano didn't do well in reporting the bug source when this error happens.

What I did to sovle this problem is that I added a check before using the user instance, to see if it's an anonymous user, like this:

def get_related_user_record(self, obj):
    # check if it's an anonymous user
    if not self.context["request"].user.pk:
        return None
    # This is where the problem is !!!!
    user_record = CustomRecord.objects.filter(
        which_model=obj.id, which_user=self.context["request"].user
    )
    if not user_record:
        return None
    else:
        return CustomRecordSerializer(user_record.get()).data

Solution 2:[2]

AnonymousUser has id=None and pk=None, so is not directly useable in this situation. Instead, the recommendation is to create an instance of user that reflects an anonymous user.

Solution 3:[3]

just need to add request.user.id /// this will solve for sure..

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Brad Solomon
Solution 3 Bharath Kumar