From 587b0acb3b6e2a7dc9f6ef2f999978621892a052 Mon Sep 17 00:00:00 2001 From: FriggemannMichael Date: Wed, 8 Jul 2026 13:03:51 +0200 Subject: [PATCH] Document overridden serializer methods Add concise docstrings to the overridden validate/create/update methods and their private helpers across the app serializers, so each customization states what it does and how it differs from the default DRF behavior. Trivial computed-field getters are left as is. --- auth_app/api/serializers.py | 4 ++++ offers_app/api/serializers.py | 7 +++++++ orders_app/api/serializers.py | 3 +++ profiles_app/api/serializers.py | 1 + reviews_app/api/serializers.py | 4 ++++ 5 files changed, 19 insertions(+) diff --git a/auth_app/api/serializers.py b/auth_app/api/serializers.py index 61cc25c..99b88ff 100644 --- a/auth_app/api/serializers.py +++ b/auth_app/api/serializers.py @@ -17,6 +17,7 @@ class RegistrationSerializer(serializers.Serializer): ) def validate_username(self, value): + """Reject a username that is already taken.""" if get_user_model().objects.filter(username=value).exists(): raise serializers.ValidationError( 'A user with that username already exists.' @@ -24,6 +25,7 @@ def validate_username(self, value): return value def validate(self, attrs): + """Confirm the password and its repetition match.""" if attrs['password'] != attrs['repeated_password']: raise serializers.ValidationError( {'repeated_password': ['Passwords do not match.']} @@ -31,6 +33,7 @@ def validate(self, attrs): return attrs def create(self, validated_data): + """Create the user and its matching profile from validated input.""" validated_data.pop('repeated_password', None) user = get_user_model().objects.create_user( username=validated_data['username'], @@ -51,6 +54,7 @@ class LoginSerializer(serializers.Serializer): password = serializers.CharField(write_only=True) def validate(self, attrs): + """Authenticate the credentials and attach the resolved user.""" user = authenticate( username=attrs['username'], password=attrs['password'], diff --git a/offers_app/api/serializers.py b/offers_app/api/serializers.py index 861a299..6722166 100644 --- a/offers_app/api/serializers.py +++ b/offers_app/api/serializers.py @@ -84,6 +84,7 @@ class Meta: ] def validate(self, attrs): + """Require the full detail set when creating a new offer.""" if self.instance is None and 'details' not in attrs: raise serializers.ValidationError( { @@ -93,6 +94,7 @@ def validate(self, attrs): return super().validate(attrs) def validate_details(self, value): + """Enforce exactly one basic/standard/premium detail on create.""" if self.instance is not None: return self._validate_update_details(value) @@ -105,6 +107,7 @@ def validate_details(self, value): return value def _validate_update_details(self, value): + """Ensure updated details reference offer types that already exist.""" existing_types = set(self.instance.details.values_list('offer_type', flat=True)) for detail in value: offer_type = detail.get('offer_type') @@ -119,6 +122,7 @@ def _validate_update_details(self, value): return value def create(self, validated_data): + """Create the offer for the request user with its nested details.""" details_data = validated_data.pop('details', None) if 'image' in validated_data and validated_data['image'] is None: validated_data['image'] = '' @@ -130,6 +134,7 @@ def create(self, validated_data): return offer def update(self, instance, validated_data): + """Update the offer and apply changes to its existing details.""" details_data = validated_data.pop('details', []) if 'image' in validated_data and validated_data['image'] is None: validated_data['image'] = '' @@ -138,10 +143,12 @@ def update(self, instance, validated_data): return offer def _create_details(self, offer, details_data): + """Create the nested detail rows for a newly created offer.""" for detail_data in details_data: OfferDetail.objects.create(offer=offer, **detail_data) def _update_details(self, offer, details_data): + """Apply field updates to each existing detail by offer type.""" for detail_data in details_data: offer_type = detail_data.pop('offer_type') detail = offer.details.get(offer_type=offer_type) diff --git a/orders_app/api/serializers.py b/orders_app/api/serializers.py index 96d016a..ba99471 100644 --- a/orders_app/api/serializers.py +++ b/orders_app/api/serializers.py @@ -46,6 +46,7 @@ def get_price(self, obj): return float(obj.price) def validate(self, attrs): + """Restrict updates to the status field only.""" if self.instance is not None: invalid_fields = set(self.initial_data) - {'status'} if invalid_fields: @@ -55,6 +56,7 @@ def validate(self, attrs): return super().validate(attrs) def create(self, validated_data): + """Create an order by copying the referenced offer detail.""" offer_detail = self._get_offer_detail(validated_data) return Order.objects.create( customer_user=self.context['request'].user, @@ -68,5 +70,6 @@ def create(self, validated_data): ) def _get_offer_detail(self, validated_data): + """Fetch the referenced offer detail or raise a 404.""" queryset = OfferDetail.objects.select_related('offer', 'offer__user') return get_object_or_404(queryset, id=validated_data.pop('offer_detail_id')) diff --git a/profiles_app/api/serializers.py b/profiles_app/api/serializers.py index cb9f9f5..6cb0569 100644 --- a/profiles_app/api/serializers.py +++ b/profiles_app/api/serializers.py @@ -32,6 +32,7 @@ class Meta: ] def update(self, instance, validated_data): + """Update the profile and sync the email onto the related user.""" user_data = validated_data.pop('user', {}) if 'email' in user_data: instance.user.email = user_data['email'] diff --git a/reviews_app/api/serializers.py b/reviews_app/api/serializers.py index 51aa560..ffda84f 100644 --- a/reviews_app/api/serializers.py +++ b/reviews_app/api/serializers.py @@ -26,6 +26,7 @@ class Meta: ] def validate(self, attrs): + """Check the target is a business user and not yet reviewed.""" business_user = attrs.get('business_user') reviewer = self.context['request'].user self._validate_business_user(business_user) @@ -33,12 +34,14 @@ def validate(self, attrs): return super().validate(attrs) def create(self, validated_data): + """Create the review with the request user as its reviewer.""" return Review.objects.create( reviewer=self.context['request'].user, **validated_data, ) def _validate_business_user(self, business_user): + """Reject a review target that is not a business user.""" is_business_user = UserProfile.objects.filter( user=business_user, type=UserProfile.ProfileType.BUSINESS, @@ -49,6 +52,7 @@ def _validate_business_user(self, business_user): ) def _validate_unique_review(self, business_user, reviewer): + """Reject a second review by the same reviewer for the business.""" if Review.objects.filter( business_user=business_user, reviewer=reviewer,