Django annotate with other model attributes based on a common field

I have a User model,

class User(AbstractBaseUser):
    id = models.IntegerField(primary_key=True)
    email = models.EmailField(unique=True)

I have another model named Company. The Company model has a reference to User model via an Integer field.

class Company(models.Model):
    user_id = models.IntegerField(db_index=True)
    name = models.CharField(max_length=100)
    size = models.IntegerField(default=1)

I wanted to extract the company information along with user information. basically I want a user object dictionary like this {'id':1, 'email':'abc@gmail.com','name':'foobar.co','size':400}

I want to annotate the user objects with name and size. As of now, I tried in the serializer's to_representation method. However, for millions of users this is super slow.

class UserSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    email = serializers.EmailField(read_only=True)

    def to_representation(self, instance):
            response = super(UserSerializer, self).to_representation(instance)
            company = Company.objects.filter(user_id=instance.id)
            if company.exists():
                company = company.first()
                response['name'] = company.name
                response['size'] = company.size
            return response

How can I achieve this annotation in the query itself.

If the links in the comment do not help you, You can use SerializerMethodField for name, and size

class UserSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    email = serializers.EmailField(read_only=True)
    name = serializers.SerializerMethodField()
    size = serializers.SerializerMethodField()
    
    def get_name(self, obj):
        # get name from DB using the User object(obj)
        return name

    def get_size(self, obj):
        # get size from DB using the User object(obj)
        return size 
Back to Top