from django.conf import settings from rest_framework import serializers from rest_framework.exceptions import ValidationError from taggit.models import Tag from core.models import Image, Board from core.models import Pin from django_images.models import Thumbnail from users.models import User class UserSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = User fields = ( 'username', 'gravatar', settings.DRF_URL_FIELD_NAME, ) class ThumbnailSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Thumbnail fields = ( "image", "width", "height", ) class ImageSerializer(serializers.ModelSerializer): class Meta: model = Image fields = ( "id", "image", "width", "height", "standard", "thumbnail", "square", ) extra_kwargs = { "width": {"read_only": True}, "height": {"read_only": True}, } standard = ThumbnailSerializer(read_only=True) thumbnail = ThumbnailSerializer(read_only=True) square = ThumbnailSerializer(read_only=True) def create(self, validated_data): image = super(ImageSerializer, self).create(validated_data) Thumbnail.objects.get_or_create_at_sizes(image, settings.IMAGE_SIZES.keys()) return image class TagSerializer(serializers.SlugRelatedField): class Meta: model = Tag fields = ("name",) queryset = Tag.objects.all() def __init__(self, **kwargs): super(TagSerializer, self).__init__( slug_field="name", **kwargs ) def to_internal_value(self, data): obj, _ = self.get_queryset().get_or_create( defaults={self.slug_field: data, "slug": data}, **{self.slug_field: data} ) return obj class PinSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Pin fields = ( settings.DRF_URL_FIELD_NAME, "id", "submitter", "url", "origin", "description", "referer", "image", "image_by_id", "tags", ) submitter = UserSerializer(read_only=True) tags = TagSerializer( many=True, source="tag_list", required=False, ) image = ImageSerializer(required=False, read_only=True) image_by_id = serializers.PrimaryKeyRelatedField( queryset=Image.objects.all(), write_only=True, required=False, ) def create(self, validated_data): if 'url' not in validated_data and\ 'image_by_id' not in validated_data: raise ValidationError( detail={ "url-or-image": "Either url or image_by_id is required." }, ) submitter = self.context['request'].user if 'url' in validated_data and validated_data['url']: url = validated_data['url'] image = Image.objects.create_for_url( url, validated_data.get('referer', url), ) else: image = validated_data.pop("image_by_id") tags = validated_data.pop('tag_list', []) pin = Pin.objects.create(submitter=submitter, image=image, **validated_data) if tags: pin.tags.set(*tags) return pin def update(self, instance, validated_data): tags = validated_data.pop('tag_list', None) if tags: instance.tags.set(*tags) # change for image-id or image is not allowed validated_data.pop('image_by_id', None) return super(PinSerializer, self).update(instance, validated_data) class BoardSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Board fields = ( "name", "pins", "pins_detail", "published", "submitter", ) read_only_fields = ('submitter', 'published') pins_detail = PinSerializer(source="pins", many=True, read_only=True) pins = serializers.HyperlinkedRelatedField( write_only=True, queryset=Pin.objects.all(), view_name="pin-detail", many=True, required=False, ) def create(self, validated_data): user = self.context['request'].user if Board.objects.filter(name=validated_data['name'], submitter=user).exists(): raise ValidationError( detail={"name": "board with this name already exists."} ) validated_data['submitter'] = user return super(BoardSerializer, self).create(validated_data)