class RecursiveSerializer(serializers.Serializer): pk = serializers.CharField() recursive_field = PresentablePrimaryKeyRelatedField( queryset=MockQueryset([]), presentation_serializer="tests.test_relations.RecursiveSerializer", ) recursive_fields = PresentablePrimaryKeyRelatedField( queryset=MockQueryset([]), presentation_serializer="tests.test_relations.RecursiveSerializer", many=True)
def setUp(self): self.queryset = MockQueryset([ MockObject(pk=1, name="foo"), MockObject(pk=2, name="bar"), MockObject(pk=3, name="baz"), ]) self.instance = self.queryset.items[2] self.field = PresentablePrimaryKeyRelatedField( queryset=self.queryset, presentation_serializer=PresentationSerializer)
class TemplateDetailSerializer(serializers.ModelSerializer): revenue_program = PresentablePrimaryKeyRelatedField( queryset=RevenueProgram.objects.all(), presentation_serializer=RevenueProgramInlineSerializer, read_source=None, default=None, allow_null=True, required=False, ) page = PresentablePrimaryKeyRelatedField( queryset=DonationPage.objects.all(), presentation_serializer=DonationPageFullDetailSerializer, read_source=None, required=False, allow_null=True, ) def create(self, validated_data): page = validated_data.pop("page", None) if page: return page.make_template_from_page(validated_data) return super().create(validated_data) def validate_page(self, page): """Note on why""" if page and self.initial_data.get("revenue_program") is None: self.initial_data["revenue_program"] = page.revenue_program.pk return page class Meta: model = Template fields = [ "id", "page", "name", "heading", "revenue_program", "graphic", "header_bg_image", "header_logo", "header_link", "styles", "elements", "sidebar_elements", "thank_you_redirect", "post_thank_you_redirect", ] validators = [ ValidateFkReferenceOwnership(fk_attribute="page"), UniqueTogetherValidator( queryset=Template.objects.all(), fields=["name", "revenue_program"], message="Template name already in use", ), ]
class SerializerWithPresentable(serializers.Serializer): test_many_field = PresentablePrimaryKeyRelatedField( queryset=MockQueryset([]), presentation_serializer=PresentationSerializer, read_source="foo_property", many=True) test_function_field = PresentablePrimaryKeyRelatedField( queryset=MockQueryset([]), presentation_serializer=PresentationSerializer, read_source="foo_function", many=True) test_field = PresentablePrimaryKeyRelatedField( queryset=MockQueryset([MockObject(pk=1, name="foo")]), presentation_serializer=PresentationSerializer, read_source="bar_property", many=False)
class TestPresentablePrimaryKeyRelatedField(APISimpleTestCase): def setUp(self): self.queryset = MockQueryset([ MockObject(pk=1, name="foo"), MockObject(pk=2, name="bar"), MockObject(pk=3, name="baz"), ]) self.instance = self.queryset.items[2] self.field = PresentablePrimaryKeyRelatedField( queryset=self.queryset, presentation_serializer=PresentationSerializer) def test_representation(self): representation = self.field.to_representation(self.instance) expected_representation = PresentationSerializer(self.instance).data assert representation == expected_representation def test_read_source_with_context(self): representation = SerializerWithPresentable(self.instance) expected_representation = [ PresentationSerializer(x).data for x in MockObject().foo_property ] assert representation.data[ 'test_many_field'] == expected_representation assert representation.data[ 'test_function_field'] == expected_representation expected_representation = PresentationSerializer( MockObject().bar_property).data assert representation.data['test_field'] == expected_representation
class RatingSerializer(serializers.ModelSerializer): rated_by = PresentablePrimaryKeyRelatedField( queryset=User.objects, presentation_serializer=UserSerializer ) venue = PresentablePrimaryKeyRelatedField( queryset=Venue.objects, presentation_serializer=VenueSerializer ) class Meta: model = Rating fields = ('id', 'rating', 'venue', 'rated_by') def create(self, validated_data): return Rating.objects.create(**validated_data)
class CommentSerializer(serializers.ModelSerializer): commented_by = PresentablePrimaryKeyRelatedField( queryset=User.objects, presentation_serializer=UserSerializer ) commented_to = PresentablePrimaryKeyRelatedField( queryset=Venue.objects, presentation_serializer=VenueSerializer ) class Meta: model = Comment fields = ('id', 'title', 'body', 'commented_by', 'commented_to', 'created_date') def create(self, validated_data): return Comment.objects.create(**validated_data)
class AppointmentRatingSerializer(AppointmentRatingBaseSerializer): class Meta: model = AppointmentRating fields = ('id', 'appointment', 'rate', 'comment', ) rate = serializers.IntegerField(min_value=1, max_value=5) appointment = PresentablePrimaryKeyRelatedField( presentation_serializer=AppointmentSerializer, queryset=Appointment.objects.all(), )
class VenueSerializer(serializers.ModelSerializer): created_by = PresentablePrimaryKeyRelatedField( queryset=User.objects, presentation_serializer=UserSerializer ) type = PresentablePrimaryKeyRelatedField( queryset=VenueType.objects, presentation_serializer=VenueTypeSerializer ) class Meta: model = Venue fields = ('id', 'name', 'description', 'address', 'phone_number', 'created_by', 'type', 'average_rating', 'vote_count', 'comment_count') def create(self, validated_data): rating_data = validated_data.pop('rating') venue = Venue.objects.create(**validated_data) Rating.objects.create(venue=venue, **rating_data) return venue
class VenueTypeSerializer(serializers.ModelSerializer): created_by = PresentablePrimaryKeyRelatedField( queryset=User.objects, presentation_serializer=UserSerializer ) class Meta: model = VenueType fields = ('id', 'venue_type', 'created_by', 'slug') def create(self, validated_data): return VenueType.objects.create(**validated_data)
class RecipeSerializer(serializers.ModelSerializer): images = PresentablePrimaryKeyRelatedField( presentation_serializer=ImageSerializer, queryset=Image.objects.all(), many=True, allow_empty=False) author = PresentablePrimaryKeyRelatedField( presentation_serializer=UserSerializer, read_only=True) ingredients = PresentablePrimaryKeyRelatedField( presentation_serializer=IngredientSerializer, queryset=Ingredient.objects.all(), many=True, allow_empty=False) average_rate = serializers.FloatField(read_only=True) like_count = serializers.IntegerField(read_only=True) rate_count = serializers.IntegerField(read_only=True) class Meta: model = Recipe fields = ('id', 'author', 'title', 'description', 'difficulty', 'ingredients', 'like_count', 'average_rate', 'rate_count', 'images')
class TestPresentablePrimaryKeyRelatedField(APISimpleTestCase): def setUp(self): self.queryset = MockQueryset([ MockObject(pk=1, name="foo"), MockObject(pk=2, name="bar"), MockObject(pk=3, name="baz"), ]) self.instance = self.queryset.items[2] self.field = PresentablePrimaryKeyRelatedField( queryset=self.queryset, presentation_serializer=PresentationSerializer) def test_representation(self): representation = self.field.to_representation(self.instance) expected_representation = PresentationSerializer(self.instance).data assert representation == expected_representation
class AdvertSerializerBrief(serializers.ModelSerializer): advert_category = serializers.SlugRelatedField( slug_field='name', queryset=AdvertCategory.objects.all()) city = serializers.SlugRelatedField(slug_field='name', queryset=City.objects.all()) advert_status = serializers.SlugRelatedField( slug_field='name', queryset=AdvertStatus.objects.all()) user = PresentablePrimaryKeyRelatedField( queryset=User.objects.all(), presentation_serializer=UserSerializerBrief, source='creator') image = ThumbnailImageField(represent_in_base64=True) class Meta: model = Advert fields = ('id', 'advert_category', 'city', 'advert_status', 'user', 'title', 'price', 'image')
class StyleListSerializer(StyleInlineSerializer): revenue_program = PresentablePrimaryKeyRelatedField( queryset=RevenueProgram.objects.all(), presentation_serializer=RevenueProgramInlineSerializer, read_source=None, ) used_live = serializers.SerializerMethodField() def get_used_live(self, obj): return DonationPage.objects.filter( styles=obj, published_date__lte=timezone.now()).exists() def to_internal_value(self, data): """ Data comes in as a dict with name and styles flattened. We need to stick styles in its own value and pull out name. """ name = data.pop("name", None) revenue_program = data.pop("revenue_program", None) data = { "name": name, "revenue_program": revenue_program, "styles": data, } return super().to_internal_value(data) class Meta: model = Style fields = ( "id", "created", "modified", "name", "styles", "revenue_program", "used_live", ) validators = [ ValidateFkReferenceOwnership(fk_attribute="revenue_program"), UniqueTogetherValidator(queryset=Style.objects.all(), fields=["revenue_program", "name"]), ]
class AdvertSerializer(serializers.ModelSerializer): image = CustomizedBase64ImageField(represent_in_base64=True, required=False) advert_category = serializers.SlugRelatedField( slug_field='name', queryset=AdvertCategory.objects.all()) city = serializers.SlugRelatedField(slug_field='name', queryset=City.objects.all()) promotion = serializers.SlugRelatedField( slug_field='name', queryset=AdvertPromotion.objects.all()) advert_status = serializers.SlugRelatedField( slug_field='name', queryset=AdvertStatus.objects.all()) user = PresentablePrimaryKeyRelatedField( queryset=User.objects.all(), presentation_serializer=UserSerializerBrief, source='creator', ) subscribing_users = UserSerializer(many=True, read_only=True) class Meta: model = Advert fields = '__all__'
class TestPresentablePrimaryKeyRelatedField(APISimpleTestCase): class PresentationSerializer(serializers.Serializer): def to_representation(self, instance): return {"pk": instance.pk, "name": instance.name} def setUp(self): self.queryset = MockQueryset([ MockObject(pk=1, name='foo'), MockObject(pk=2, name='bar'), MockObject(pk=3, name='baz') ]) self.instance = self.queryset.items[2] self.field = PresentablePrimaryKeyRelatedField( queryset=self.queryset, presentation_serializer=self.PresentationSerializer) def test_representation(self): representation = self.field.to_representation(self.instance) expected_representation = self.PresentationSerializer( self.instance).data assert representation == expected_representation
class UserMeSerializer(UserSerializer): answers = AnswerSerializer(many=True) one_liners = OneLinerSerializer(many=True) projects = PresentablePrimaryKeyRelatedField( queryset=Project.objects.all(), presentation_serializer=ProjectSerializer, many=True) class Meta: model = User fields = [ "id", "first_name", "last_name", "image", "timezone", "projects", "answers", "one_liners", "birth_date", "phone_number", ]
class DonationPageFullDetailSerializer(serializers.ModelSerializer): styles = PresentablePrimaryKeyRelatedField( queryset=Style.objects.all(), presentation_serializer=StyleInlineSerializer, read_source=None, allow_null=True, required=False, ) revenue_program = PresentablePrimaryKeyRelatedField( queryset=RevenueProgram.objects.all(), presentation_serializer=RevenueProgramListInlineSerializer, read_source=None, allow_null=False, required=True, ) template_pk = serializers.IntegerField(allow_null=True, required=False) graphic = serializers.ImageField(allow_empty_file=True, allow_null=True, required=False) header_bg_image = serializers.ImageField(allow_empty_file=True, allow_null=True, required=False) header_logo = serializers.ImageField(allow_empty_file=True, allow_null=True, required=False) graphic_thumbnail = HyperlinkedSorlImageField("300", source="graphic", read_only=True) header_bg_image_thumbnail = HyperlinkedSorlImageField( "300", source="header_bg_image", read_only=True) header_logo_thumbnail = HyperlinkedSorlImageField("300", source="header_logo", read_only=True) organization_is_nonprofit = serializers.SerializerMethodField( method_name="get_organization_is_nonprofit") stripe_account_id = serializers.SerializerMethodField( method_name="get_stripe_account_id") currency = serializers.SerializerMethodField(method_name="get_currency") organization_country = serializers.SerializerMethodField( method_name="get_organization_country") allow_offer_nyt_comp = serializers.SerializerMethodField( method_name="get_allow_offer_nyt_comp") benefit_levels = serializers.SerializerMethodField( method_name="get_benefit_levels") def get_organization_is_nonprofit(self, obj): return obj.organization.non_profit def get_stripe_account_id(self, obj): if self.context.get("live"): return obj.organization.stripe_account_id def get_currency(self, obj): return obj.organization.get_currency_dict() def get_organization_country(self, obj): return obj.organization.address.country def get_allow_offer_nyt_comp(self, obj): if not self.context.get("live", False): return obj.revenue_program.allow_offer_nyt_comp def get_benefit_levels(self, obj): if obj.revenue_program: benefit_levels = obj.revenue_program.benefitlevel_set.all() serializer = BenefitLevelDetailSerializer(benefit_levels, many=True) return serializer.data class Meta: model = DonationPage fields = "__all__" validators = [ ValidateFkReferenceOwnership(fk_attribute="styles"), ValidateFkReferenceOwnership(fk_attribute="revenue_program"), UniqueTogetherValidator(queryset=DonationPage.objects.all(), fields=["revenue_program", "slug"]), ] def _update_related(self, related_field, related_model, validated_data, instance): pk_field = f"{related_field}_pk" if pk_field in validated_data and validated_data[pk_field] is None: setattr(instance, related_field, None) elif pk_field in validated_data: try: related_instance = related_model.objects.get( pk=validated_data[pk_field]) setattr(instance, related_field, related_instance) except related_model.DoesNotExist: raise serializers.ValidationError({ related_field: "Could not find instance with provided pk." }) def _check_against_soft_deleted_slugs(self, validated_data): new_slug = validated_data.get(settings.PAGE_SLUG_PARAM, None) if new_slug and DonationPage.objects.deleted_only().filter( slug=new_slug).exists(): raise serializers.ValidationError( {settings.PAGE_SLUG_PARAM: [UNIQUE_PAGE_SLUG]}) def _create_from_template(self, validated_data): """ Given a template pk, find template and run model method make_page_from_template. Returns DonationPage instance Throws ValidationError if template is somehow missing. """ try: template_pk = validated_data.pop("template_pk") template = Template.objects.get(pk=template_pk) return template.make_page_from_template(validated_data) except Template.DoesNotExist: raise serializers.ValidationError( {"template": ["This template no longer exists"]}) def create(self, validated_data): self._check_against_soft_deleted_slugs(validated_data) if "template_pk" in validated_data: return self._create_from_template(validated_data) return super().create(validated_data) def update(self, instance, validated_data): self._update_related("styles", Style, validated_data, instance) return super().update(instance, validated_data)