Home > Enterprise >  Serializer for writing Foreign Keys as integer id but reading them as object
Serializer for writing Foreign Keys as integer id but reading them as object

Time:07-01

I have two models - Users and UserAccessLogs:

class Users(AbstractUser):
    email = models.EmailField()
    name = models.Charfield()
    etc.

class UserAccessLogs(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
    anotherField = models.Charfield()
    etc.

with serializers:

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = Users
        fields = '__all__'

    def validate_email(self, value):
        # validations here

    def update(self, instance, validated_data):
        instance.email = validated_data['email'] 
        etc.
        instance.save()
        return instance

class UserAccessLogsSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserAccessLogs
        fields ='__all__'

In my views function I would like to retrieve the actual user class when fetching UserAccessLogs i.e. I would like:

UserAccessLogs = {
   user : {
           email: myEmail,
           name: myName, 
           etc.
          }
}

instead of

UserAccessLogs = {
   user : 1
}

in my views:

access_logs = UserAccessLogs.objects.all()
serializer = UserAccessLogsSerializer(access_logs, many = True)
return Response(serializer.data, status.HTTP_200_OK)

I tried adding user = UserSerializer() to UserAccessLogsSerializer class. It works, but then when I try and save a new instance of the UserAccessLogs I get errors related to User model from the validators. If I set read_only = True then it leaves user = null in the database. The below works in my views class but it doesn't seem efficient and needs to be repeated every time I want to get full UserAccessLogs.

for data in serializer.data:
      data['user'] = UserSerializer(User.objects.get(id = data['user'])).data

CodePudding user response:

create two serializers in serializer.py

class User_serializer(serializers.ModelSerializer):
    class Meta:
        model = Users
        fields = '__all__'
    
class User_access_serializer(serializers.ModelSerializer):
    class Meta:
        model = UserAccessLogs
        fields = '__all__'
    user = User_serializer()
    

in you API:

UserAccessLogs_queryset = UserAccessLogs.objects.all()
serializer_class = User_access_serializer(UserAccessLogs_queryset ,many=True)
return Response(serializer_class.data)

it will create nested API as you needed

Also i assume you have an error doing class UserAccessLogs by (AbstractUser) it looks like you need class UserAccessLogs(models.Model):

CodePudding user response:

try this

user = UserSerializer(read_only=True)
user_id = serializers.PrimaryKeyRelatedField(queryset=User.objects.all(), source='user')
  • Related