Search code examples
pythondjangodjango-rest-frameworkpydanticdjango-ninja

Pydantic: pass the entire dataset to a nested field


I am using django, django-ninja framework to replace some of my apis ( written in drf, as it is becoming more like a boilerplate codebase ). Now while transforming some legacy api, I need to follow the old structure, so the client side doesn't face any issue. This is just the backstory.

I have two separate models.

class Author(models.Model):
   username = models.CharField(...)
   email = models.CharField(...)
   ... # Other fields

class Blog(models.Model):
   title = models.CharField(...)
   text = models.CharField(...)
   tags = models.CharField(...)
   author = models.ForeignKey(...)
   ... # Other fields

The structure written in django rest framework serializer

class BlogBaseSerializer(serializers.Serializer):
   class Meta:
       model = Blog
       exclude = ["author"]

class AuthorSerializer(serializers.Serializer):
   class Meta:
       model = Author
       fields = "__all__"


class BlogSerializer(serializers.Serializer):
   blog = BlogBaseSerializer(source="*")
   author = AuthorSerializer()

In viewset the following queryset will be passed

class BlogViewSet(viewsets.GenericViewSet, ListViewMixin):
    queryset = Blog.objects.all()
    serializer_class = BlogSerializer
    ... # Other config

So, as I am switching to django-ninja which uses pydantic for schema generation. I have the following code for pydantic schema

AuthorSchema = create_schema(Author, exclude=["updated", "date_joined"])


class BlogBaseSchema(ModelSchema):
    class Meta:
        model = Blog
        exclude = ["author", ]


class BlogSchema(Schema):
    blog: BlogBaseSchema
    author: AuthorSchema

But as you can see, drf serializer has a parameter called source, where source="*" means to pass the entire original dataset to the nested field serializer. Is there any option to do the exact same with pydantic?

Except for creating a list of dictionaries [{author: blog.author, "blog": blog} for blog in queryset]


Solution

  • Resolved the problem with the following code

    class AuthorSchema(ModelSchema):
        class Meta:
            model = Author
            exclude=["updated", "date_joined"]
    
    class BlogBaseSchema(ModelSchema):
        class Meta:
            model = Blog
            exclude = ["author", ]
    
    
    class BlogSchema(Schema):
        blog: BlogBaseSchema
        author: AuthorSchema
    
        @staticmethod
        def resolve_blog(self, obj):
            return obj