Combine models to get cohesive data

Question:

I’m writing app in witch I store data in separate models. Now I need to combine this data to use it.

The problem

I have three models:

class User(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(unique=True)
    first_name = models.CharField(max_length=50, blank=True)
    ...

class Contacts(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="user")
    contact_user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="contact_user")

class UserPhoto(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    url = models.CharField(max_length=220)

How can I get the current user contacts with their names and pictures like this (serialized)

{
 {
   "contact_user":"1",
   "first_name":"Mark ",
   "url":first picture that corresponds to contact_user id
 },
 {
   "contact_user":"2",
   "first_name":"The Rock",
   "url":first picture that corresponds to contact_user id
 }
}

Now I’m querying the Contacts model to get all contacts_user id’s that he has connection to.

class MatchesSerializer(serializers.ModelSerializer):

    class Meta:
        model = Contacts
        fields = '__all__'
        depth = 1

class ContactViewSet(viewsets.ModelViewSet):
    serializer_class = ContactsSerializer
    
    def get_queryset(self):
        return Contacts.objects.filter(user__id=self.request.user.id)
Asked By: rafaelHTML

||

Answers:

The thing you need to is to serialize the Contacts queryset to include the related User and UserPhoto objects for each contact.

Try to create a custom serializer for the Contacts model so:

class ContactSerializer(serializers.ModelSerializer):
    contact_user = serializers.SerializerMethodField()

    def get_contact_user(self, obj):
        user = obj.contact_user
        photo = user.userphoto_set.first()
        return {
            "id": user.id,
            "first_name": user.first_name,
            "url": photo.url if photo else None
        }

    class Meta:
        model = Contacts
        fields = ("contact_user",)

Then, modify the ContactViewSet to use this newly created serializer so:

class ContactViewSet(viewsets.ModelViewSet):
    serializer_class = ContactSerializer
    
    def get_queryset(self):
        return Contacts.objects.filter(user__id=self.request.user.id)

Note: Generally, Django models don’t require s to be added as suffix since it is by default added, so it is better to modify it as Contact from Contacts.

Answered By: Sunderam Dubey