Search code examples
djangodjango-modelsdjango-rest-frameworkdjango-viewsdjango-orm

Ho to create serializer for model having foreign keys to access that foreign keys tables data also?


I want to rewrite the following API in a more efficient way using the serializer. In the following API, the user and group are foreign keys.

I want to return all matching data of group and user using Serializer.

How to design a serializer for this situation.

@api_view(['GET'])
def get_post(request, group_id, post_type, post_limit):
    if request.method == 'GET':
        print('group id = ')
        print(group_id)
        # data = GroupPostsModel.objects.filter(
        #     group_id=group_id) & GroupPostsModel.objects.filter(post_type=post_type).order_by('-time_stamp')

        try:
            data = GroupPostsModel.objects.filter(
                group_id=group_id, post_type=post_type).order_by('-time_stamp')[post_limit:post_limit+3]
            # data = data[0:3] model.objects.filter(book = 'bible')
            post_arr_obj = []
            for post in data:
                comments_count = GroupPostCommentsModel.objects.filter(
                post_id=post.id).count()
                print('post id = '+str(post.id))
                post_dict = {
                    'post_id': str(post.id),
                    'post_text': str(post.post_text),
                    'post_type': str(post.post_type),
                    'image': str(post.image),
                    'document': str(post.document),
                    'likes': str(post.likes),
                    'group_id': str(post.group.id),
                    'user_id': str(post.user.id),
                    'time_stamp': str(post.time_stamp),
                    'profile_pic': str(post.user.profile_pic),
                    'first_name': str(post.user.first_name),
                    'last_name': str(post.user.last_name),
                    'gender': str(post.user.gender),
                    'comments_count': str(comments_count)
                }
                post_arr_obj.append(post_dict)
        except Exception as e:
            print('get_post exception : '+str(e))

        resp = {
            'resp': post_arr_obj
        }
        # group_post_serializer = GroupPostsSerializer(data, many=True)
        return Response(resp)
    else:
        return Response({'msg': 'Only GET request allowed..!'})

Relationship

One user can join/create many groups

One group can have mane posts

One user can post many posts

UserModel

class UserModel(models.Model):
    first_name = models.CharField(max_length=20)
    last_name = models.CharField(max_length=20)
    gender = models.CharField(max_length=6)
    college_name = models.CharField(max_length=50)
    user_id = models.CharField(max_length=30,unique = True)
    user_password = models.CharField(max_length=20)
    profile_pic = models.ImageField(blank=True, null=True, upload_to='profile_pic/')

    class Meta:
        db_table = 'user'

GroupModel

class GroupsModel(models.Model):
    group_name = models.CharField(max_length=20, unique=True)
    group_description = models.CharField(max_length=50)
    group_joining_link = models.CharField(max_length=50, default='', unique=True)
    user_id = models.ManyToManyField(UserModel, through='UserModelGroupsModel', related_name='u_g')

    class Meta:
        db_table = 'groups'

GroupPostsModel

class GroupPostsModel(models.Model):
    post_text = models.CharField(max_length=1000)
    post_type = models.CharField(max_length=20)
    image = models.ImageField(blank=True, null=True, upload_to='post_images/')
    document = models.FileField(blank=True,null=True, upload_to='post_documents/')
    likes = models.IntegerField(default=0)
    time_stamp = models.DateTimeField(auto_now=True)
    group = models.ForeignKey(GroupsModel, on_delete=models.CASCADE)
    user = models.ForeignKey(UserModel, on_delete=models.CASCADE)

    def delete(self):
       if self.image:
          if os.path.isfile(self.image.path):
             os.remove(self.image.path)

       if self.document:
          if os.path.isfile(self.document.path):
             os.remove(self.document.path)
       
       super().delete()


    class Meta:
        db_table = 'group_posts'


Solution

  • You could use the Django Rest Framework ModelSerializer to do this. Create a serializer using the model GroupPostsModel

    class GroupPostsSerializer(serializers.ModelSerializer):
    
        id = IntegerField()
        post_text = CharField()
        ...
        group_id = IntegerField(source="group.id")
        ...
    
        class Meta:
            model = GroupPostsModel
            fields = [
                'id'
                'post_text'
                ...
            ]
    
    
    

    For comments_count you could use a SerializerMethodField() to define a method the serializer will use for that field.

    initialize the serializer with your posts

    serializer = GroupPostsSerializer(data, many=True)
    

    then to access data

    resp = {
                'resp': serializer.data
            }