from datetime import datetime from rest_framework import fields as drf_fields from rest_framework import serializers as drf_serilazers from rest_framework_json_api import relations, serializers from example.models import ( ArtProject, Author, AuthorBio, AuthorBioMetadata, AuthorType, Blog, Comment, Company, Entry, LabResults, Project, ProjectType, ResearchProject, TaggedItem ) class TaggedItemSerializer(serializers.ModelSerializer): class Meta: model = TaggedItem fields = ('tag',) class TaggedItemDRFSerializer(drf_serilazers.ModelSerializer): """ DRF default serializer to test default DRF functionalities """ class Meta: model = TaggedItem fields = ('tag',) class BlogSerializer(serializers.ModelSerializer): copyright = serializers.SerializerMethodField() tags = TaggedItemSerializer(many=True, read_only=True) include_serializers = { 'tags': 'example.serializers.TaggedItemSerializer', } def get_copyright(self, resource): return datetime.now().year def get_root_meta(self, resource, many): return { 'api_docs': '/docs/api/blogs' } class Meta: model = Blog fields = ('name', 'url', 'tags') read_only_fields = ('tags',) meta_fields = ('copyright',) class BlogDRFSerializer(drf_serilazers.ModelSerializer): """ DRF default serializer to test default DRF functionalities """ copyright = serializers.SerializerMethodField() tags = TaggedItemDRFSerializer(many=True, read_only=True) def get_copyright(self, resource): return datetime.now().year def get_root_meta(self, resource, many): return { 'api_docs': '/docs/api/blogs' } class Meta: model = Blog fields = ('name', 'url', 'tags', 'copyright') read_only_fields = ('tags',) meta_fields = ('copyright',) class EntrySerializer(serializers.ModelSerializer): def __init__(self, *args, **kwargs): super(EntrySerializer, self).__init__(*args, **kwargs) # to make testing more concise we'll only output the # `featured` field when it's requested via `include` request = kwargs.get('context', {}).get('request') if request and 'featured' not in request.query_params.get('include', []): self.fields.pop('featured', None) included_serializers = { 'authors': 'example.serializers.AuthorSerializer', 'comments': 'example.serializers.CommentSerializer', 'featured': 'example.serializers.EntrySerializer', 'suggested': 'example.serializers.EntrySerializer', 'tags': 'example.serializers.TaggedItemSerializer', } body_format = serializers.SerializerMethodField() # single related from model blog_hyperlinked = relations.HyperlinkedRelatedField( related_link_view_name='entry-blog', related_link_url_kwarg='entry_pk', self_link_view_name='entry-relationships', read_only=True, source='blog' ) # many related from model comments = relations.ResourceRelatedField( many=True, read_only=True) # many related hyperlinked from model comments_hyperlinked = relations.HyperlinkedRelatedField( related_link_view_name='entry-comments', related_link_url_kwarg='entry_pk', self_link_view_name='entry-relationships', many=True, read_only=True, source='comments' ) # many related from serializer suggested = relations.SerializerMethodResourceRelatedField( related_link_view_name='entry-suggested', related_link_url_kwarg='entry_pk', self_link_view_name='entry-relationships', model=Entry, many=True, ) # many related hyperlinked from serializer suggested_hyperlinked = relations.SerializerMethodHyperlinkedRelatedField( related_link_view_name='entry-suggested', related_link_url_kwarg='entry_pk', self_link_view_name='entry-relationships', model=Entry, many=True, ) # single related from serializer featured = relations.SerializerMethodResourceRelatedField(model=Entry) # single related hyperlinked from serializer featured_hyperlinked = relations.SerializerMethodHyperlinkedRelatedField( related_link_view_name='entry-featured', related_link_url_kwarg='entry_pk', self_link_view_name='entry-relationships', model=Entry, read_only=True ) tags = TaggedItemSerializer(many=True, read_only=True) def get_suggested(self, obj): return Entry.objects.exclude(pk=obj.pk) def get_featured(self, obj): return Entry.objects.exclude(pk=obj.pk).first() def get_body_format(self, obj): return 'text' class Meta: model = Entry fields = ('blog', 'blog_hyperlinked', 'headline', 'body_text', 'pub_date', 'mod_date', 'authors', 'comments', 'comments_hyperlinked', 'featured', 'suggested', 'suggested_hyperlinked', 'tags', 'featured_hyperlinked') read_only_fields = ('tags',) meta_fields = ('body_format',) class JSONAPIMeta: included_resources = ['comments'] class EntryDRFSerializers(drf_serilazers.ModelSerializer): tags = TaggedItemDRFSerializer(many=True, read_only=True) url = drf_serilazers.HyperlinkedIdentityField( view_name='drf-entry-blog-detail', lookup_url_kwarg='entry_pk', read_only=True, ) class Meta: model = Entry fields = ('tags', 'url',) read_only_fields = ('tags',) class AuthorTypeSerializer(serializers.ModelSerializer): class Meta: model = AuthorType fields = ('name', ) class AuthorBioSerializer(serializers.ModelSerializer): class Meta: model = AuthorBio fields = ('author', 'body', 'metadata') included_serializers = { 'metadata': 'example.serializers.AuthorBioMetadataSerializer', } class AuthorBioMetadataSerializer(serializers.ModelSerializer): class Meta: model = AuthorBioMetadata fields = ('body',) class AuthorSerializer(serializers.ModelSerializer): bio = relations.ResourceRelatedField( related_link_view_name='author-related', self_link_view_name='author-relationships', queryset=AuthorBio.objects, ) entries = relations.ResourceRelatedField( related_link_view_name='author-related', self_link_view_name='author-relationships', queryset=Entry.objects, many=True ) first_entry = relations.SerializerMethodResourceRelatedField( related_link_view_name='author-related', self_link_view_name='author-relationships', model=Entry, ) comments = relations.HyperlinkedRelatedField( related_link_view_name='author-related', self_link_view_name='author-relationships', queryset=Comment.objects, many=True ) included_serializers = { 'bio': AuthorBioSerializer, 'type': AuthorTypeSerializer } related_serializers = { 'bio': 'example.serializers.AuthorBioSerializer', 'type': 'example.serializers.AuthorTypeSerializer', 'comments': 'example.serializers.CommentSerializer', 'entries': 'example.serializers.EntrySerializer', 'first_entry': 'example.serializers.EntrySerializer' } class Meta: model = Author fields = ('name', 'email', 'bio', 'entries', 'comments', 'first_entry', 'type') def get_first_entry(self, obj): return obj.entries.first() class WriterSerializer(serializers.ModelSerializer): included_serializers = { 'bio': AuthorBioSerializer } class Meta: model = Author fields = ('name', 'email', 'bio') resource_name = 'writers' class CommentSerializer(serializers.ModelSerializer): # testing remapping of related name writer = relations.ResourceRelatedField(source='author', read_only=True) included_serializers = { 'entry': EntrySerializer, 'author': AuthorSerializer, 'writer': WriterSerializer } class Meta: model = Comment exclude = ('created_at', 'modified_at',) # fields = ('entry', 'body', 'author',) class ProjectTypeSerializer(serializers.ModelSerializer): class Meta: model = ProjectType fields = ('name', 'url',) class BaseProjectSerializer(serializers.ModelSerializer): included_serializers = { 'project_type': ProjectTypeSerializer, } class ArtProjectSerializer(BaseProjectSerializer): class Meta: model = ArtProject exclude = ('polymorphic_ctype',) class ResearchProjectSerializer(BaseProjectSerializer): # testing exclusive related field on inherited polymorphic model lab_results = relations.ResourceRelatedField(many=True, read_only=True) class Meta: model = ResearchProject exclude = ('polymorphic_ctype',) class LabResultsSerializer(serializers.ModelSerializer): class Meta: model = LabResults fields = ('date', 'measurements') class ProjectSerializer(serializers.PolymorphicModelSerializer): included_serializers = { 'project_type': ProjectTypeSerializer, } polymorphic_serializers = [ArtProjectSerializer, ResearchProjectSerializer] class Meta: model = Project exclude = ('polymorphic_ctype',) class CurrentProjectRelatedField(relations.PolymorphicResourceRelatedField): def get_attribute(self, instance): obj = super(CurrentProjectRelatedField, self).get_attribute(instance) is_art = ( self.field_name == 'current_art_project' and isinstance(obj, ArtProject) ) is_res = ( self.field_name == 'current_research_project' and isinstance(obj, ResearchProject) ) if is_art or is_res: return obj raise drf_fields.SkipField() class CompanySerializer(serializers.ModelSerializer): current_project = relations.PolymorphicResourceRelatedField( ProjectSerializer, queryset=Project.objects.all()) current_art_project = CurrentProjectRelatedField( ProjectSerializer, source='current_project', read_only=True) current_research_project = CurrentProjectRelatedField( ProjectSerializer, source='current_project', read_only=True) future_projects = relations.PolymorphicResourceRelatedField( ProjectSerializer, queryset=Project.objects.all(), many=True) included_serializers = { 'current_project': ProjectSerializer, 'future_projects': ProjectSerializer, 'current_art_project': ProjectSerializer, 'current_research_project': ProjectSerializer } class Meta: model = Company fields = '__all__'