Conditional Validation

+15 Mana ✨

Introduction

Sometimes validation rules depend on other field values or external conditions.

Key Concepts

Conditional Logic: Rules that depend on other fields.

Optional Requirements: Required only under certain conditions.

Real World Context

A checkout form needs address fields only for delivery, not store pickup. Conditional validation in clean() enforces these context-dependent rules.

Deep Dive

Field-Dependent Validation

python
class ShippingForm(forms.Form):
    delivery_type = forms.ChoiceField(
        choices=[('pickup', 'Store Pickup'), ('delivery', 'Home Delivery')]
    )
    address = forms.CharField(required=False)
    
    def clean(self):
        cleaned_data = super().clean()
        delivery = cleaned_data.get('delivery_type')
        address = cleaned_data.get('address')
        
        # Address required only for delivery
        if delivery == 'delivery' and not address:
            self.add_error('address', 'Address required for delivery')
        
        return cleaned_data

Dynamic Required Fields

python
class PaymentForm(forms.Form):
    payment_method = forms.ChoiceField(
        choices=[('card', 'Credit Card'), ('bank', 'Bank Transfer')]
    )
    card_number = forms.CharField(required=False)
    bank_account = forms.CharField(required=False)
    
    def clean(self):
        cleaned_data = super().clean()
        method = cleaned_data.get('payment_method')
        
        if method == 'card' and not cleaned_data.get('card_number'):
            self.add_error('card_number', 'Required for card payments')
        elif method == 'bank' and not cleaned_data.get('bank_account'):
            self.add_error('bank_account', 'Required for bank transfers')
        
        return cleaned_data

Common Pitfalls

  1. Setting required=True on conditionally-required fields -- Set required=False and enforce in clean() instead.
  2. Not clearing irrelevant field data -- Stale data from unused fields may persist.

Best Practices

  1. Document the conditions -- Add comments explaining which fields are required when.
  2. Consider multiple form classes -- For complex branching, separate classes may be cleaner.

Summary

Use clean() for conditional validation. Check field dependencies. Add targeted errors with add_error().

✓ Completed