class ArticleSerializer(serializers.ModelSerializer): author = ProfileSerializer(read_only=True) description = serializers.CharField(required=False) slug = serializers.SlugField(required=False) # Django REST Framework makes it possible to create a read-only field that # gets its value by calling a function. In this case, the client expects # `created_at` to be called `createdAt` and `updated_at` to be `updatedAt`. # `serializers.SerializerMethodField` is a good way to avoid having the # requirements of the client leak into our API. createdAt = serializers.SerializerMethodField(method_name='get_created_at') updatedAt = serializers.SerializerMethodField(method_name='get_updated_at') class Meta: model = Article fields = ('author', 'body', 'createdAt', 'description', 'slug', 'title', 'updatedAt') def create(self, validated_data): author = self.context.get('author', None) return Article.objects.create(author=author, **validated_data) def get_created_at(self, instance): return instance.created_at.isoformat() def get_udpated_at(self, instance): return instance.updated_at.isoformat()
class LocalSerializer(serializers.ModelSerializer): createdAt = serializers.SerializerMethodField(method_name='get_created_at') updatedAt = serializers.SerializerMethodField(method_name='get_updated_at') author = ProfileSerializer(read_only=True) class Meta: model = Local fields = ( 'id', 'nombre', 'telefono', 'createdAt', 'direccion', 'poblacion', 'provincia', 'latitud', 'longitud', 'foto', 'updatedAt', 'categoria', 'author', ) def create(self, validated_data): author = self.context.get('author', None) local = Local.objects.create(author=author, **validated_data) return local def get_created_at(self, instance): return instance.created_at.isoformat() def get_updated_at(self, instance): return instance.updated_at.isoformat()
class ArticleSerializer(serializers.ModelSerializer): author = ProfileSerializer(read_only=True) description = serializers.CharField(required=False) slug = serializers.SlugField(required=False) createdAt = serializers.SerializerMethodField(method_name='get_created_at') updatedAt = serializers.SerializerMethodField(method_name='get_updated_at') class Meta: model = Article fields = ( 'author', 'body', 'createdAt', 'description', 'slug', 'title', 'updatedAt', ) def create(self, validated_data): author = self.context.get('author', None) return Article.objects.create(author=author, **validated_data) def get_created_at(self, instance): return instance.created_at.isoformat() def get_updated_at(self, instance): return instance.updated_at.isoformat()
class ArticleSerializer(serializers.ModelSerializer): author = ProfileSerializer(read_only=True) description = serializers.CharField(required=False) slug = serializers.SlugField(required=False) favorited = serializers.SerializerMethodField() favoritesCount = serializers.SerializerMethodField( method_name='get_favorites_count' ) tagList = TagRelatedField(many=True, required=False, source='tags') createdAt = serializers.SerializerMethodField(method_name='get_created_at') updatedAt = serializers.SerializerMethodField(method_name='get_updated_at') class Meta: model = Article fields = ( 'author', 'body', 'createdAt', 'description', 'favorited', 'favoritesCount', 'slug', 'tagList', 'title', 'updatedAt', ) def create(self, validated_data): author = self.context.get('author', None) tags = validated_data.pop('tags', []) article = Article.objects.create(author=author, **validated_data) for tag in tags: article.tags.add(tag) return article def get_created_at(self, instance): return instance.created_at.isoformat() def get_favorited(self, instance): request = self.context.get('request', None) if request is None: return False if not request.user.is_authenticated(): return False return request.user.profile.has_favorited(instance) def get_favorites_count(self, instance): return instance.favorited_by.count() def get_updated_at(self, instance): return instance.updated_at.isoformat()
class UserSerializer(serializers.ModelSerializer): password = serializers.CharField(max_length=255, min_length=8, write_only=True) profile = ProfileSerializer(write_only=True) bio = serializers.CharField(source='profile.bio', read_only=True) image = serializers.CharField(source='profile.image', read_only=True) class Meta: model = User fields = ('email', 'username', 'password', 'token', 'profile', 'bio', 'image') read_only_fields = ('token', ) def update(self, instance, validated_data): password = validated_data.pop('password', None) profile_data = validated_data.pop('profile', {}) for (key, value) in validated_data.items(): setattr(instance, key, value) if password is not None: instance.set_password(password) instance.save() for (key, value) in profile_data.items(): setattr(instance.profile, key, value) instance.profile.save() return instance
class CommentSerializer(serializers.ModelSerializer): author = ProfileSerializer(required=False) createdAt = serializers.SerializerMethodField(method_name="get_created_at") updatedAt = serializers.SerializerMethodField(method_name="get_updated_at") class Meta: model = Comment fields = ( "id", "author", "body", "createdAt", "updatedAt", ) def create(self, validated_data): article = self.context["article"] author = self.context["author"] return Comment.objects.create(author=author, article=article, **validated_data) def get_created_at(self, instance): return instance.created_at.isoformat() def get_updated_at(self, instance): return instance.updated_at.isoformat()
class ArticleSerializer(serializers.ModelSerializer): author = ProfileSerializer(read_only=True) description = serializers.CharField(required=False) slug = serializers.SlugField(required=False) favorited = serializers.SerializerMethodField() favoritesCount = serializers.SerializerMethodField( method_name='get_favorites_count') tagList = TagRelatedField(many=True, required=False, source='tags') # Django REST Framework makes it possible to create a read-only field that # gets it's value by calling a function. In this case, the client expects # `created_at` to be called `createdAt` and `updated_at` to be `updatedAt`. # `serializers.SerializerMethodField` is a good way to avoid having the # requirements of the client leak into our API. createdAt = serializers.SerializerMethodField(method_name='get_created_at') updatedAt = serializers.SerializerMethodField(method_name='get_updated_at') class Meta: model = Article fields = ( 'author', 'body', 'createdAt', 'description', 'favorited', 'favoritesCount', 'slug', 'tagList', 'title', 'updatedAt', ) def create(self, validated_data): author = self.context.get('author', None) article = Article.objects.create(author=author, **validated_data) return article def get_created_at(self, instance): return instance.created_at.isoformat() def get_favorited(self, instance): request = self.context.get('request', None) if request is None: return False if not request.user.is_authenticated(): return False return request.user.profile.has_favorited(instance) def get_favorites_count(self, instance): return instance.favorited_by.count() def get_updated_at(self, instance): return instance.updated_at.isoformat()
class CommentSerializer(serializers.ModelSerializer): author = ProfileSerializer(required=False) createdAt = serializers.SerializerMethodField(method_name='get_created_at') updatedAt = serializers.SerializerMethodField(method_name='get_updated_at') class Meta: model = Comment fields = ( 'id', 'author', 'body', 'score', 'createdAt', 'updatedAt', ) def create(self, validated_data): article = self.context['article'] author = self.context['author'] return Comment.objects.create(author=author, article=article, **validated_data) def get_created_at(self, instance): return instance.created_at.isoformat() def get_updated_at(self, instance): return instance.updated_at.isoformat()
class UserSerializer(serializers.ModelSerializer): """ Handles serialization and deserialization of User objects. """ # Passwords must have at >= 8 character, <= 128 password = serializers.CharField(max_length=128, min_length=8, write_only=True) profile = ProfileSerializer(write_only=True) bio = serializers.CharField(source='profile.bio', read_only=True) image = serializers.CharField(source='profile.image', read_only=True) class Meta: model = User fields = ( 'email', 'username', 'password', 'token', 'profile', 'bio', 'image', ) # 'read_only_fields' option is alternative for explicitly specifying # field with 'read_only=True', like with password above read_only_fields = ('token', ) def update(self, instance, validated_data): """ Performs an update on a User. """ password = validated_data.pop('password', None) profile_data = validated_data.pop('profile', {}) for (key, value) in validated_data.items(): # For keys remaining in 'validated_data', set them # on current 'User' instance one at a time setattr(instance, key, value) if password is not None: # '.set_password()' handles all of the # security stuff that we shouldn't be concered with instance.set_password(password) # Save model instance.save() for (key, value) in profile_data.items(): setattr(instance.profile, key, value) instance.profile.save() return instance
class UserSerializer(serializers.ModelSerializer): password = serializers.CharField(min_length=8, max_length=128, write_only=True) profile = ProfileSerializer(write_only=True) bio = serializers.CharField(source='profile.bio', read_only=True) image = serializers.CharField(source='profile.image', read_only=True) class Meta: model = User fields = ( 'email', 'username', 'password', 'token', 'profile', 'bio', 'image', ) read_only_fields = ('token', ) def update(self, instance, validated_data): # passwords should not be updated with setattr. Will use Django's hashing and salt function # but need to extract it before iterating over the validated_data password = validated_data.pop('password', None) # handling profile data separately too profile_data = validated_data.pop('profile', {}) for (key, value) in validated_data.items(): setattr(instance, key, value) if password is not None: instance.set_password(password) instance.save() for (key, value) in profile_data.items(): setattr(instance.profile, key, value) instance.profile.save() return instance
class PlayerSerializer(serializers.ModelSerializer): username = ProfileSerializer(read_only=True) image = serializers.CharField(required=False) slug = serializers.SlugField(required=False) # Django REST Framework makes it possible to create a read-only field that # gets it's value by calling a function. In this case, the client expects # `created_at` to be called `createdAt` and `updated_at` to be `updatedAt`. # `serializers.SerializerMethodField` is a good way to avoid having the # requirements of the client leak into our API. class Meta: model = Player fields = ( 'slug', 'username', 'image', )
class CommentSerializer(serializers.ModelSerializer): author = ProfileSerializer(required=False) createdAt = serializers.SerializerMethodField(method_name='get_created_at') updatedAt = serializers.SerializerMethodField(method_name='get_updated_at') class Meta: model = Comment fields = ( 'id', 'author', 'body', 'createdAt', 'updatedAt', ) def create(self, validated_data): article = self.context['article'] author = self.context['author'] return Comment.objects.create(author=author, article=article, **validated_data) def get_created_at(self, instance): return instance.create_at.isoformat() def get_updated_at(self, instance): return instance.create_at.isoformat() def get_favorited(self, instance): request = self.context.get('request', None) if request is None: return False if not request.user.is_authenticated: return False return request.user.profile.has_favorited(instance) def get_favorites_count(self, instance): return instance.favorited_by.count()
class GrantApplicationSerializer(serializers.ModelSerializer): author = ProfileSerializer(read_only=True) createdAt = serializers.SerializerMethodField(method_name='get_created_at') updatedAt = serializers.SerializerMethodField(method_name='get_updated_at') class Meta: model = GrantApplication fields = ( 'id', 'author', 'body', 'createdAt', 'updatedAt', ) def create(self, validated_data): if self.context['grant'] is None: raise ValueError( 'grant should be in the context when creating a grant application' ) if self.context['author'] is None: raise ValueError( 'author should be in the context when creating a grant application' ) grant = self.context['grant'] author = self.context['author'] return GrantApplication.objects.create(author=author, grant=grant, **validated_data) def get_created_at(self, instance): return instance.created_at.isoformat() def get_updated_at(self, instance): return instance.updated_at.isoformat()
class CommentSerializer(serializers.ModelSerializer): author = ProfileSerializer(read_only=True) body = serializers.CharField() # Why this is not needed? #article = ArticleSerializer(read_only=True) # Call get_[~~~]_at createdAt = serializers.SerializerMethodField(method_name='get_created_at') updatedAt = serializers.SerializerMethodField(method_name='get_updated_at') class Meta: model = Comment # Why id is here and article is not in the fields? fields = ( 'id', 'body', 'author', 'createdAt', 'updatedAt', ) def create(self, validated_data): # Where context fame from? author = self.context.get('author', None) article = self.context.get('article', None) return Comment.objects.create(author=author, article=article, **validated_data) def get_created_at(self, instance): return instance.created_at.isoformat() def get_updated_at(self, instance): return instance.updated_at.isoformat()
class CommentSerializer(serializers.ModelSerializer): author = ProfileSerializer(required=False) createdAt = serializers.SerializerMethodField(method_name='get_created_at') updatedAt = serializers.SerializerMethodField(method_name='get_updated_at') class Meta: model = Comment fields = ( 'id', 'author', 'body', 'createdAt', 'updatedAt', ) def create(self, validated_data): author = None article = None request = self.context.get("request") if request and hasattr(request, "user"): author = request.user.profile request = self.context.get("request") if request and hasattr(request, "article"): article = request.article return Comment.objects.create(author=author, article=article, **validated_data) def get_created_at(self, instance): return instance.created_at.isoformat() def get_updated_at(self, instance): return instance.updated_at.isoformat()
class ArticleSerializer(serializers.ModelSerializer): author = ProfileSerializer(read_only=True) description = serializers.CharField(required=False) slug = serializers.SlugField(required=False) favorited = serializers.SerializerMethodField() favoritesCount = serializers.SerializerMethodField( method_name="get_favorites_count") tagList = TagRelatedField(many=True, required=False, source="tags") # Django REST Framework makes it possible to create a read-only field that # gets it's value by calling a function. In this case, the client expects # `created_at` to be called `createdAt` and `updated_at` to be `updatedAt`. # `serializers.SerializerMethodField` is a good way to avoid having the # requirements of the client leak into our API. createdAt = serializers.SerializerMethodField(method_name="get_created_at") updatedAt = serializers.SerializerMethodField(method_name="get_updated_at") class Meta: model = Article fields = ( "author", "body", "createdAt", "description", "favorited", "favoritesCount", "slug", "tagList", "title", "updatedAt", ) def create(self, validated_data): author = self.context.get("author", None) tags = validated_data.pop("tags", []) article = Article.objects.create(author=author, **validated_data) for tag in tags: article.tags.add(tag) return article def get_created_at(self, instance): return instance.created_at.isoformat() def get_favorited(self, instance): request = self.context.get("request", None) if request is None: return False if not request.user.is_authenticated(): return False return request.user.profile.has_favorited(instance) def get_favorites_count(self, instance): return instance.favorited_by.count() def get_updated_at(self, instance): return instance.updated_at.isoformat()
class ArticleSerializer(serializers.ModelSerializer): author = ProfileSerializer(read_only=True) description = serializers.CharField(required=False) slug = serializers.SlugField(required=False) # Note that because we use the method get_favorited as the method_name here, we do not need to # specify it, as SerializerMethodField defaults to get_<field_name> favorited = serializers.SerializerMethodField() favoritesCount = serializers.SerializerMethodField( method_name='get_favorites_count') tagList = TagRelatedField(many=True, required=False, source='tags') # DRF makes it possible to create a read-only field that gets its value by calling a function # In this case, the client expects created to be called createdAt and updated_at to be updatedAt. # serializers.SerializerMethodField is a good way to avoid having the requirements of the client # to leak into our previous API createdAt = serializers.SerializerMethodField(method_name='get_created_at') updatedAt = serializers.SerializerMethodField(method_name='get_updated_at') class Meta: model = Article fields = ( 'author', 'body', 'createdAt', 'description', 'favorited', 'favoritesCount', 'slug', 'tagList', 'title', 'updatedAt', ) def create(self, validated_data): author = self.context.get('author', None) tags = validated_data.pop('tags', []) article = Article.objects.create(author=author, **validated_data) for tag in tags: article.tags.add(tag) return article def get_created_at(self, instance): return instance.created_at.isoformat() def get_updated_at(self, instance): return instance.updated_at.isoformat() def get_favorited(self, instance): request = self.context.get('request', None) if request is None: return False if not request.user.is_authenticated(): return False return request.user.profile.has_favorited(instance) def get_favorites_count(self, instance): return instance.favorited_by.count()
class UserSerializer(serializers.ModelSerializer): """Handles serialization and deserialization of User objects.""" # Passwords must be 8 characters, but no more than 128 characters. # These values are the default provided by Django. We could # change them, but that would create extra work whil introducing no real # benefit, so let's just stick with the defaults. password = serializers.CharField( max_length=128, min_length=8, write_only=True, ) # When a field should be handled as a serializer, we must explicitly say so. Moreover, # UserSerializers should never expose profile information, so we set write_only=True. profile = ProfileSerializer(write_only=True) # We want to get the bio and image fields from the related Profile model bio = serializers.CharField(source='profile.bio', read_only=True) image = serializers.CharField(source='profile.image', read_only=True) class Meta: model = User fields = ( 'email', 'username', 'password', 'token', 'profile', 'bio', 'image', ) # The read_only_fields option is an alternative for explicitly # specifying the field with read_only=True like we did for password # above. The reason we want to user read_only_fields here is that # we don't need to specify anything else about the field. The # password field needed the min_length and max_length properties, # but token don't care read_only_fields = ('token',) def update(self, instance, validated_data): """ Performs an update on a User. """ # Passwords should not be handled with setattr, unlike other fields. # Django provides a function that handles hashing and salting passwords. # TRhat means we need to remove the password field from the # validated_data dictionary before iterating over it. password = validated_data.pop('password', None) # Like passwords, we have to handle profiles separately. To do that, we remove the profile # data from the validated_dictionary dict. profile_data = validated_data.pop('profile', {}) for (key, value) in validated_data.items(): # For the remaining keys, we will set them on the current User instance one at a time. setattr(instance, key, value) if password is not None: # .set_password() handles all that good security stuffs instance.set_password(password) # After everything has been updated we must explicitly save the model # It's worth pointing out that .set_password() does not save the model instance.save() for key, value in profile_data.items(): # We're doing the same thing as above, but now with items in the Profile Model. setattr(instance.profile, key, value) # Save the profile just like we saved the user instance.profile.save() return instance
class UserSerializer(serializers.ModelSerializer): """Handles serialization and deserialization of User objects.""" # Passwords must be at least 5 characters, but no more than 128 # characters. These values are the default provided by Django. We could # change them, but that would create extra work while introducing no real # benefit, so lets just stick with the defaults. password = serializers.CharField(max_length=128, min_length=8, write_only=True) # When a field should be handled as a serializer, we must explicitly say # so. Moreover, `UserSerializer` should never expose profile information, # so we set `write_only=True`. profile = ProfileSerializer(write_only=True) # We want to get the `bio` and `image` fields from the related Profile # model. bio = serializers.CharField(source='profile.bio', read_only=True) image = serializers.CharField(source='profile.image', read_only=True) class Meta: model = User fields = ( 'email', 'username', 'password', 'token', 'profile', 'bio', 'image', ) # The `read_only_fields` option is an alternative for explicitly # specifying the field with `read_only=True` like we did for password # above. The reason we want to use `read_only_fields` here is that # we don't need to specify anything else about the field. The # password field needed the `min_length` and # `max_length` properties, but that isn't the case for the token # field. read_only_fields = ('token', ) def update(self, instance, validated_error): '''Performs an update on a User''' # Passwords should not be handled with `setattr`, unlike other fields. # Django provides a function that handles hashing and # salting passwords. That means # we need to remove the password field from the # `validated_data` dictionary before iterating over it. password = validated_error.pop('password', None) # Like passwords, we have to handle profiles separately. To do that, # we remove the profile data from the `validated_data` dictionary. profile_data = validated_data.pop('profile', {}) for (key, value) in validated_data.items(): # For the keys remaining in `validated_data`, we will set them on # the current `User` instance one at a time. setattr(instance, key, value) if password is not None: # `.set_password()` handles all # of the security stuff that we shouldn't be concerned with. instance.set_password(password) # After everything has been updated we must explicitly save # the model. It's worth pointing out that `.set_password()` does not # save the model. instance.save() for (key, value) in profile_data.items(): # We're doing the same thing as above, but this time we're making # changes to the Profile model. setattr(instance.profile, key, value) # Save the profile just like we saved the user. instance.profile.save() return instance
class FoundationSerializer(serializers.ModelSerializer): name = serializers.CharField( ) # TODO: Not sure if this should be read_only description = serializers.CharField(required=False) website = serializers.URLField(required=False, allow_blank=True, allow_null=True, default=None) # TODO: See issue #22 grantees = serializers.CharField(required=False) tagList = TagRelatedField(many=True, required=False, source='tags') createdAt = serializers.SerializerMethodField(method_name='get_created_at') updatedAt = serializers.SerializerMethodField(method_name='get_updated_at') followed = serializers.SerializerMethodField() followersCount = serializers.SerializerMethodField( method_name='get_followers_count') img = serializers.SerializerMethodField(method_name='get_image_link') founder = ProfileSerializer(read_only=True) class Meta: model = Foundation fields = ('name', 'description', 'website', 'createdAt', 'founder', 'grantees', 'followed', 'followersCount', 'img', 'tagList', 'updatedAt') def create(self, validated_data): founder = self.context.get('founder', None) tags = validated_data.pop('tags', []) foundation = Foundation.objects.create(founder=founder, **validated_data) for tag in tags: foundation.tags.add(tag) return foundation def get_created_at(self, instance): return instance.created_at.isoformat() def get_followed(self, instance): request = self.context.get('request', None) if request is None: return False if not request.user.is_authenticated: return False return request.user.profile.is_following_foundation(instance) def get_followers_count(self, instance): return instance.followed_by.count() def get_updated_at(self, instance): return instance.updated_at.isoformat() def get_image_link(self, instance): if instance.img and hasattr(instance.img, 'url'): return instance.img.base_url return ''
class UserSerializer(serializers.ModelSerializer): """Handles serialization and deserialization of User objects.""" # Passwords must be at least 8 characters, but no more than 128 # characters. These values are the default provided by Django. We could # change them, but that would create extra work while introducing no real # benefit, so lets just stick with the defaults. password = serializers.CharField(max_length=128, min_length=8, read_only=True) # When a field should be handled as a serializer, we must explicitly say # so. Moreover, `UserSerializer` should never expose profile information, # so we set `write_only=True`. profile = ProfileSerializer(write_only=True) # We want to get the `bio` and `image` fields from the related Profile # model. bio = serializers.CharField(source='profile.bio', read_only=True) image = serializers.CharField(source='profile.image', read_only=True) class Meta: model = User fields = ( "email", "username", "password", "token", "profile", "bio", "image", ) # The `read_only_fields` option is an alternative for explicitly # specifying the field with `read_only=True` like we did for password # above. The reason we want to use `read_only_fields` here is that # we don't need to specify anything else about the field. The # password field needed the `min_length` and # `max_length` properties, but that isn't the case for the token # field. read_only_fields = ("token", ) def update(self, instance, validated_data): # password should be deleted from validated_data # without deleting password, password is stored as # usual variable password = validated_data.pop("password", None) # profile is separated table, so we do not want to # include profile data when updating user table profile_data = validated_data.pop("profile", {}) for key, value in validated_data.items(): setattr(instance, key, value) # password should be hashed nd salted # set_password method takes care of it if password is not None: instance.set_password(password) # Update User model(table) instance.save() # Update profile model(table) for key, value in profile_data.items(): setattr(instance.profile, key, value) instance.profile.save() return instance
class UserSerializer(serializers.ModelSerializer): """Handles serialization and deserialization of User objects.""" # Passwords must be at least 8 characters, but no more than 128 # characters. These values are the default provided by Django. We could # change them, but that would create extra work while introducing no real # benefit, so let's just stick with the defaults. password = serializers.CharField(max_length=128, min_length=8, write_only=True) profile = ProfileSerializer(write_only=True) bio = serializers.CharField(source='profile.bio', read_only=True) image = serializers.CharField(source='profile.image', read_only=True) class Meta: model = User fields = ( 'email', 'username', 'password', 'token', 'profile', 'bio', 'image', ) # The `read_only_fields` option is an alternative for explicitly # specifying the field with `read_only=True` like we did for password # above. The reason we want to use `read_only_fields` here is because # we don't need to specify anything else about the field. For the # password field, we needed to specify the `min_length` and # `max_length` properties too, but that isn't the case for the token # field. read_only_fields = ('token', ) def update(self, instance, validated_data): """Performs an update on a User.""" # Passwords should not be handled with `setattr`, unlike other fields. # This is because Django provides a function that handles hashing and # salting passwords, which is important for security. What that means # here is that we need to remove the password field from the # `validated_data` dictionary before iterating over it. password = validated_data.pop('password', None) # Like passwords, we have to handle profiles separately. To do that, # we remove the profile data from the `validated_data` dictionary. profile_data = validated_data.pop('profile', {}) for (key, value) in validated_data.items(): # Set the other keys as attributes for the user instance. setattr(instance, key, value) if password is not None: instance.set_password(password) instance.save() for (key, value) in profile_data.items(): # We're doing the same thing as above, but this time we're making # changes to the Profile model. setattr(instance.profile, key, value) instance.profile.save() return instance
class ArticleSerializer(serializers.ModelSerializer): # Three variables are specified here because they are not used # directly from Article model # This is my guess, but # author came from profiles.Profile model # Therefore, assigned ProfileSerializer with read_only=True # author field is defined in models.py like below # author = models.ForeignKey( # 'profiles.Profile', on_delete=models.CASCADE, related_name='articles') author = ProfileSerializer(read_only=True) # There are no TextField in serializer # Therefore use CharField with required=False description = serializers.CharField(required=False) body = serializers.CharField(required=False) favorited = serializers.SerializerMethodField() favoritedCount = serializers.SerializerMethodField( method_name='get_favorited_count') tagList = TagRelatedField(many=True, required=False, source='tags') print("tagList") print(tagList) # Call get_[~~~]_at createdAt = serializers.SerializerMethodField(method_name='get_created_at') updatedAt = serializers.SerializerMethodField(method_name='get_updated_at') class Meta: # Use model profile model = Article fields = ( 'slug', 'title', 'description', 'body', 'favorited', 'favoritedCount', 'tagList', 'author', 'createdAt', 'updatedAt', ) # override create to retrieve author from context # What is the context of serializers.ModelSerializer? def create(self, validated_data): print("validated_data") print(validated_data) # Where context fame from? author = self.context.get('author', None) # Why have to use pop instead get tags = self.validated_data.pop('tags', []) # tags = self.validated_data.get('tags', []) article = Article.objects.create(author=author, **validated_data) for tag in tags: article.tags.add(tag) return article # Why created_at? the variable came from client like this? def get_created_at(self, instance): return instance.created_at.isoformat() def get_updated_at(self, instance): return instance.updated_at.isoformat() def get_favorited(self, instance): request = self.context.get('request', None) if request is None: return False if not request.user.is_authenticated: return False # check out the client already favorite an article or not return request.user.profile.has_favorited(instance) # Check out how many favorite has the article # It look at the instance favorited_by table # (It is the intermiddle table connect to profile and article # ManyToMany relationship) def get_favorited_count(self, instance): return instance.favorited_by.count()