limits vlaiadtion adn keywrods forms

This commit is contained in:
IGNY8 VPS (Salman)
2025-12-12 20:05:21 +00:00
parent 9824e9a4dc
commit 44ecd3fa7d
7 changed files with 224 additions and 110 deletions

View File

@@ -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')