limits vlaiadtion adn keywrods forms
This commit is contained in:
@@ -16,10 +16,21 @@ class KeywordSerializer(serializers.ModelSerializer):
|
||||
intent = serializers.CharField(read_only=True) # From seed_keyword.intent
|
||||
|
||||
# SeedKeyword relationship
|
||||
# Required for create, optional for update (can change seed_keyword or just update other fields)
|
||||
# Optional for create - can either provide seed_keyword_id OR custom keyword fields
|
||||
seed_keyword_id = serializers.IntegerField(write_only=True, required=False)
|
||||
seed_keyword = SeedKeywordSerializer(read_only=True)
|
||||
|
||||
# Custom keyword fields (write-only, for creating new seed keywords on-the-fly)
|
||||
custom_keyword = serializers.CharField(write_only=True, required=False, allow_blank=False)
|
||||
custom_volume = serializers.IntegerField(write_only=True, required=False, allow_null=True)
|
||||
custom_difficulty = serializers.IntegerField(write_only=True, required=False, allow_null=True)
|
||||
custom_intent = serializers.ChoiceField(
|
||||
write_only=True,
|
||||
required=False,
|
||||
choices=['informational', 'navigational', 'transactional', 'commercial'],
|
||||
default='informational'
|
||||
)
|
||||
|
||||
# Overrides
|
||||
volume_override = serializers.IntegerField(required=False, allow_null=True)
|
||||
difficulty_override = serializers.IntegerField(required=False, allow_null=True)
|
||||
@@ -40,6 +51,10 @@ class KeywordSerializer(serializers.ModelSerializer):
|
||||
'volume',
|
||||
'difficulty',
|
||||
'intent',
|
||||
'custom_keyword', # Write-only field for creating custom keywords
|
||||
'custom_volume', # Write-only
|
||||
'custom_difficulty', # Write-only
|
||||
'custom_intent', # Write-only
|
||||
'volume_override',
|
||||
'difficulty_override',
|
||||
'cluster_id',
|
||||
@@ -61,28 +76,94 @@ class KeywordSerializer(serializers.ModelSerializer):
|
||||
self.fields['attribute_values'] = serializers.JSONField(read_only=True)
|
||||
|
||||
def validate(self, attrs):
|
||||
"""Validate that seed_keyword_id is provided for create operations"""
|
||||
# For create operations, seed_keyword_id is required
|
||||
if self.instance is None and 'seed_keyword_id' not in attrs:
|
||||
raise serializers.ValidationError({'seed_keyword_id': 'This field is required when creating a keyword.'})
|
||||
"""Validate that either seed_keyword_id OR custom keyword fields are provided"""
|
||||
# For create operations, need either seed_keyword_id OR custom keyword
|
||||
if self.instance is None:
|
||||
has_seed_keyword = 'seed_keyword_id' in attrs
|
||||
has_custom_keyword = 'custom_keyword' in attrs
|
||||
|
||||
if not has_seed_keyword and not has_custom_keyword:
|
||||
raise serializers.ValidationError({
|
||||
'keyword': 'Either provide seed_keyword_id to link an existing keyword, or provide custom_keyword to create a new one.'
|
||||
})
|
||||
|
||||
if has_custom_keyword:
|
||||
# Validate custom keyword fields
|
||||
if not attrs.get('custom_keyword', '').strip():
|
||||
raise serializers.ValidationError({'custom_keyword': 'Keyword text cannot be empty.'})
|
||||
|
||||
if attrs.get('custom_volume') is None:
|
||||
raise serializers.ValidationError({'custom_volume': 'Volume is required when creating a custom keyword.'})
|
||||
|
||||
if attrs.get('custom_difficulty') is None:
|
||||
raise serializers.ValidationError({'custom_difficulty': 'Difficulty is required when creating a custom keyword.'})
|
||||
|
||||
return attrs
|
||||
|
||||
def create(self, validated_data):
|
||||
"""Create Keywords instance with seed_keyword"""
|
||||
seed_keyword_id = validated_data.pop('seed_keyword_id', None)
|
||||
if not seed_keyword_id:
|
||||
raise serializers.ValidationError({'seed_keyword_id': 'This field is required when creating a keyword.'})
|
||||
"""Create Keywords instance with seed_keyword (existing or newly created)"""
|
||||
# Extract custom keyword fields
|
||||
custom_keyword = validated_data.pop('custom_keyword', None)
|
||||
custom_volume = validated_data.pop('custom_volume', None)
|
||||
custom_difficulty = validated_data.pop('custom_difficulty', None)
|
||||
custom_intent = validated_data.pop('custom_intent', None) or 'informational'
|
||||
|
||||
try:
|
||||
seed_keyword = SeedKeyword.objects.get(id=seed_keyword_id)
|
||||
except SeedKeyword.DoesNotExist:
|
||||
raise serializers.ValidationError({'seed_keyword_id': f'SeedKeyword with id {seed_keyword_id} does not exist'})
|
||||
# Get site and sector - they're passed as objects via save() in the view
|
||||
site = validated_data.get('site')
|
||||
sector = validated_data.get('sector')
|
||||
|
||||
if not site or not sector:
|
||||
raise serializers.ValidationError('Site and sector are required.')
|
||||
|
||||
# Determine which seed_keyword to use
|
||||
if custom_keyword:
|
||||
# Create or get SeedKeyword for this custom keyword
|
||||
if not site.industry:
|
||||
raise serializers.ValidationError({'site': 'Site must have an industry assigned.'})
|
||||
|
||||
if not sector.industry_sector:
|
||||
raise serializers.ValidationError({'sector': 'Sector must have an industry_sector assigned.'})
|
||||
|
||||
# Get or create the SeedKeyword
|
||||
seed_keyword, created = SeedKeyword.objects.get_or_create(
|
||||
keyword=custom_keyword.strip().lower(),
|
||||
industry=site.industry,
|
||||
sector=sector.industry_sector,
|
||||
defaults={
|
||||
'volume': custom_volume or 0,
|
||||
'difficulty': custom_difficulty or 0,
|
||||
'intent': custom_intent or 'informational',
|
||||
'is_active': True,
|
||||
}
|
||||
)
|
||||
|
||||
# If it existed, optionally update values (or keep existing ones)
|
||||
# For now, we'll keep existing values if the seed keyword already exists
|
||||
|
||||
validated_data['seed_keyword'] = seed_keyword
|
||||
else:
|
||||
# Use provided seed_keyword_id
|
||||
seed_keyword_id = validated_data.pop('seed_keyword_id', None)
|
||||
if not seed_keyword_id:
|
||||
raise serializers.ValidationError({'seed_keyword_id': 'This field is required when not providing a custom keyword.'})
|
||||
|
||||
try:
|
||||
seed_keyword = SeedKeyword.objects.get(id=seed_keyword_id)
|
||||
except SeedKeyword.DoesNotExist:
|
||||
raise serializers.ValidationError({'seed_keyword_id': f'SeedKeyword with id {seed_keyword_id} does not exist'})
|
||||
|
||||
validated_data['seed_keyword'] = seed_keyword
|
||||
|
||||
validated_data['seed_keyword'] = seed_keyword
|
||||
return super().create(validated_data)
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
"""Update Keywords instance with seed_keyword"""
|
||||
"""Update Keywords instance - only cluster_id and status can be updated"""
|
||||
# Remove custom keyword fields if present (they shouldn't be in update)
|
||||
validated_data.pop('custom_keyword', None)
|
||||
validated_data.pop('custom_volume', None)
|
||||
validated_data.pop('custom_difficulty', None)
|
||||
validated_data.pop('custom_intent', None)
|
||||
|
||||
# seed_keyword_id is optional for updates - only update if provided
|
||||
if 'seed_keyword_id' in validated_data:
|
||||
seed_keyword_id = validated_data.pop('seed_keyword_id')
|
||||
|
||||
Reference in New Issue
Block a user