Tour operator forms
Tour operator forms (English fallback)
Aug. 17, 2025
Posted by admin
Nhom |
Notes |
|
Tour Operators Forms System - Detailed Analysis File Overview Purpose: Django form definitions for tour operators management system Location: forms.py Function: User interface forms for data input, validation, and processing Framework: Django Forms with Bootstrap styling integration Import Dependencies Analysis from django import forms from django.core.exceptions import ValidationError from django.utils import timezone from django.db import models from decimal import Decimal from .models import ( TourOperator, Tour, TourBooking, TourSchedule, TourGuide, TourCategory, TourItinerary, TourInclusion, TourParticipant ) Key Components:
|
|
Forms Detailed Breakdown
|
|
1. TourOperatorForm - Operator Registration/Management class TourOperatorForm(forms.ModelForm): class Meta: model = TourOperator fields = [ 'name', 'name_vi', 'description', 'description_vi', 'operator_type', 'email', 'phone', 'website', 'address', 'city', 'country', 'license_number', 'certification', 'established_year', 'api_endpoint', 'api_key', 'commission_rate' ] Purpose: Tour operator profile creation and management Field Categories: Basic Information:
Contact & Location:
Legal & Business:
API Integration:
Widget Customizations: widgets = { 'description': forms.Textarea(attrs={'rows': 4}), 'description_vi': forms.Textarea(attrs={'rows': 4}), 'address': forms.Textarea(attrs={'rows': 3}), 'operator_type': forms.Select(attrs={'class': 'form-select'}), 'certification': forms.Select(attrs={'class': 'form-select'}), 'commission_rate': forms.NumberInput(attrs={'step': '0.01', 'min': '0', 'max': '100'}), } Business Use: Operator onboarding, profile updates, partnership management
|
|
2. TourForm - Comprehensive Tour Creation class TourForm(forms.ModelForm): class Meta: model = Tour fields = [ 'title', 'title_vi', 'slug', 'short_description', 'short_description_vi', 'description', 'description_vi', 'tour_operator', 'categories', 'tour_type', 'difficulty', 'duration_days', 'duration_hours', 'start_location', 'end_location', 'destinations', 'min_participants', 'max_participants', 'min_age', 'max_age', 'base_price', 'price_currency', 'child_price', 'senior_price', 'includes_accommodation', 'includes_meals', 'includes_transport', 'includes_guide', 'includes_tickets', 'fitness_level_required', 'special_requirements', 'what_to_bring', 'main_image', 'video_url' ] Purpose: Complete tour creation and editing interface Field Groups: Content Management:
Tour Classification:
Logistics:
Capacity & Demographics:
Pricing Structure:
Inclusions:
Advanced Features: User Permission Control: def __init__(self, *args, **kwargs): self.user = kwargs.pop('user', None) super().__init__(*args, **kwargs)
# Limit tour operator choices to user's operators if self.user and not self.user.is_staff: user_operators = TourOperator.objects.filter( models.Q(user=self.user) | models.Q(managers=self.user) ) self.fields['tour_operator'].queryset = user_operators Custom Validation: def clean_slug(self): slug = self.cleaned_data['slug'] qs = Tour.objects.filter(slug=slug) if self.instance: qs = qs.exclude(pk=self.instance.pk) if qs.exists(): raise ValidationError('This slug is already taken.') return slug def clean(self): cleaned_data = super().clean() min_age = cleaned_data.get('min_age') max_age = cleaned_data.get('max_age')
if min_age and max_age and min_age >= max_age: raise ValidationError('Maximum age must be greater than minimum age.')
|
|
3. TourBookingForm - Advanced Booking System class TourBookingForm(forms.ModelForm): # Participant details adult_count = forms.IntegerField(min_value=1, initial=1) child_count = forms.IntegerField(min_value=0, initial=0) senior_count = forms.IntegerField(min_value=0, initial=0)
# Lead traveler details lead_traveler_name = forms.CharField(max_length=200) lead_traveler_email = forms.EmailField() lead_traveler_phone = forms.CharField(max_length=20) Purpose: Customer booking creation with complex validation Key Features: Dynamic Schedule Filtering: def __init__(self, *args, **kwargs): self.tour = kwargs.pop('tour', None) self.user = kwargs.pop('user', None) super().__init__(*args, **kwargs)
if self.tour: # Filter schedules for this tour today = timezone.now().date() self.fields['schedule'].queryset = TourSchedule.objects.filter( tour=self.tour, is_active=True, start_date__gte=today ).order_by('start_date', 'start_time') User Auto-Population: # Pre-fill user details if available if self.user: self.fields['lead_traveler_name'].initial = self.user.get_full_name() self.fields['lead_traveler_email'].initial = self.user.email Complex Business Validation: def clean(self): cleaned_data = super().clean() adult_count = cleaned_data.get('adult_count', 0) child_count = cleaned_data.get('child_count', 0) senior_count = cleaned_data.get('senior_count', 0) schedule = cleaned_data.get('schedule')
total_participants = adult_count + child_count + senior_count
if total_participants == 0: raise ValidationError('At least one participant is required.')
if schedule and self.tour: if total_participants < self.tour.min_participants: raise ValidationError(f'Minimum {self.tour.min_participants} participants required.')
if total_participants > self.tour.max_participants: raise ValidationError(f'Maximum {self.tour.max_participants} participants allowed.')
if total_participants > schedule.remaining_spots: raise ValidationError(f'Only {schedule.remaining_spots} spots available for this schedule.') Advanced Save Method with Pricing Logic: def save(self, commit=True): booking = super().save(commit=False)
# Calculate pricing adult_count = self.cleaned_data['adult_count'] child_count = self.cleaned_data['child_count'] senior_count = self.cleaned_data['senior_count']
schedule = self.cleaned_data['schedule'] base_price = schedule.price_override or self.tour.base_price
# Calculate total price adult_price = base_price * adult_count child_price = (self.tour.child_price or base_price * Decimal('0.7')) * child_count senior_price = (self.tour.senior_price or base_price * Decimal('0.9')) * senior_count
booking.base_price = base_price booking.total_price = adult_price + child_price + senior_price booking.total_participants = self.cleaned_data['total_participants']
if commit: booking.save()
# Update schedule booked spots schedule.booked_spots += booking.total_participants schedule.save()
return booking
|
|
4. TourScheduleForm - Schedule Management class TourScheduleForm(forms.ModelForm): class Meta: model = TourSchedule fields = [ 'schedule_type', 'start_date', 'end_date', 'start_time', 'days_of_week', 'available_spots', 'price_override', 'notes' ] Purpose: Tour schedule creation and management Features:
Business Logic Validation: def clean(self): cleaned_data = super().clean() start_date = cleaned_data.get('start_date') end_date = cleaned_data.get('end_date') schedule_type = cleaned_data.get('schedule_type')
if schedule_type == 'fixed' and not start_date: raise ValidationError('Start date is required for fixed schedules.')
if start_date and end_date and start_date > end_date: raise ValidationError('End date must be after start date.')
|
|
5. TourSearchForm - Advanced Search Interface class TourSearchForm(forms.Form): SORT_CHOICES = [ ('featured', 'Featured'), ('price_low', 'Price: Low to High'), ('price_high', 'Price: High to Low'), ('rating', 'Highest Rated'), ('duration', 'Duration'), ('alphabetical', 'Alphabetical'), ] Purpose: Comprehensive tour search and filtering Search Capabilities: Text Search: search = forms.CharField( required=False, widget=forms.TextInput(attrs={ 'class': 'form-control', 'placeholder': 'Search tours...' }) ) Category Filtering: category = forms.ModelChoiceField( queryset=TourCategory.objects.filter(is_active=True), required=False, empty_label='All Categories', widget=forms.Select(attrs={'class': 'form-select'}) ) Price Range Filtering: min_price = forms.DecimalField( required=False, widget=forms.NumberInput(attrs={ 'class': 'form-control', 'step': '0.01', 'min': '0' }) ) max_price = forms.DecimalField( required=False, widget=forms.NumberInput(attrs={ 'class': 'form-control', 'step': '0.01', 'min': '0' }) )
|
|
6. TourParticipantForm - International Travel Support class TourParticipantForm(forms.ModelForm): """Form for collecting individual participant details including passport upload"""
class Meta: model = TourParticipant fields = [ 'participant_type', 'first_name', 'last_name', 'date_of_birth', 'nationality', 'passport_number', 'passport_expiry', 'passport_image', 'dietary_requirements', 'medical_conditions', 'emergency_contact_name', 'emergency_contact_phone' ] Purpose: International tour participant data collection Key Features: Document Upload Validation: def clean_passport_image(self): passport_image = self.cleaned_data.get('passport_image')
if passport_image: # Validate file size (max 5MB) if passport_image.size > 5 * 1024 * 1024: raise ValidationError('Passport image must be smaller than 5MB.')
# Validate file type valid_extensions = ['.jpg', '.jpeg', '.png', '.pdf'] file_extension = passport_image.name.lower().split('.')[-1] if f'.{file_extension}' not in valid_extensions: raise ValidationError('Please upload a valid image file (JPG, PNG) or PDF.')
return passport_image Required Field Management: def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs)
# Mark required fields required_fields = ['first_name', 'last_name', 'nationality'] for field_name in required_fields: if field_name in self.fields: self.fields[field_name].required = True self.fields[field_name].widget.attrs['required'] = True
|
|
7. TourGuideForm - Professional Guide Management class TourGuideForm(forms.ModelForm): """Form for tour guides to update their profile and upload documents"""
class Meta: model = TourGuide fields = [ 'bio', 'bio_vi', 'specializations', 'languages', 'years_experience', 'certifications', 'license_number', 'certification_document', 'license_document', 'photo_id_document', 'is_available', 'hourly_rate', 'daily_rate', 'base_location' ] Purpose: Tour guide profile and document management Features: Professional Information:
Document Upload System: def _validate_document_file(self, file, file_type): """Validate uploaded document files""" if file: # Validate file size (max 10MB) if file.size > 10 * 1024 * 1024: raise ValidationError(f'{file_type.title()} must be smaller than 10MB.')
# Validate file type valid_extensions = ['.pdf', '.doc', '.docx', '.jpg', '.jpeg', '.png'] file_extension = file.name.lower().split('.')[-1] if f'.{file_extension}' not in valid_extensions: raise ValidationError( f'Please upload a valid {file_type} (PDF, DOC, DOCX, JPG, PNG).' )
return file Rate Management:
|
|
8. Additional Supporting Forms TourItineraryForm: Day-by-day tour planning
TourInclusionForm: Tour inclusion/exclusion management
TourGuideVerificationForm: Admin verification system
Form System Architecture Bootstrap Integration All forms include Bootstrap CSS classes: def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Add CSS classes for field_name, field in self.fields.items(): if field_name not in ['operator_type', 'certification']: field.widget.attrs['class'] = 'form-control'
|
|
Multilingual Support Consistent Vietnamese/English field pairs:
Business Rule Enforcement
User Experience Features
|
|
Security & Validation File Upload Security:
Business Logic Validation:
User Permission Control:
This comprehensive form system provides a robust, user-friendly interface for all tour operators business processes, from operator registration through customer booking and guide management, with strong validation and security measures throughout.
|
Nhom |
Notes |
|
Tour Operators Forms System - Detailed Analysis File Overview Purpose: Django form definitions for tour operators management system Location: forms.py Function: User interface forms for data input, validation, and processing Framework: Django Forms with Bootstrap styling integration Import Dependencies Analysis from django import forms from django.core.exceptions import ValidationError from django.utils import timezone from django.db import models from decimal import Decimal from .models import ( TourOperator, Tour, TourBooking, TourSchedule, TourGuide, TourCategory, TourItinerary, TourInclusion, TourParticipant ) Key Components:
|
|
Forms Detailed Breakdown
|
|
1. TourOperatorForm - Operator Registration/Management class TourOperatorForm(forms.ModelForm): class Meta: model = TourOperator fields = [ 'name', 'name_vi', 'description', 'description_vi', 'operator_type', 'email', 'phone', 'website', 'address', 'city', 'country', 'license_number', 'certification', 'established_year', 'api_endpoint', 'api_key', 'commission_rate' ] Purpose: Tour operator profile creation and management Field Categories: Basic Information:
Contact & Location:
Legal & Business:
API Integration:
Widget Customizations: widgets = { 'description': forms.Textarea(attrs={'rows': 4}), 'description_vi': forms.Textarea(attrs={'rows': 4}), 'address': forms.Textarea(attrs={'rows': 3}), 'operator_type': forms.Select(attrs={'class': 'form-select'}), 'certification': forms.Select(attrs={'class': 'form-select'}), 'commission_rate': forms.NumberInput(attrs={'step': '0.01', 'min': '0', 'max': '100'}), } Business Use: Operator onboarding, profile updates, partnership management
|
|
2. TourForm - Comprehensive Tour Creation class TourForm(forms.ModelForm): class Meta: model = Tour fields = [ 'title', 'title_vi', 'slug', 'short_description', 'short_description_vi', 'description', 'description_vi', 'tour_operator', 'categories', 'tour_type', 'difficulty', 'duration_days', 'duration_hours', 'start_location', 'end_location', 'destinations', 'min_participants', 'max_participants', 'min_age', 'max_age', 'base_price', 'price_currency', 'child_price', 'senior_price', 'includes_accommodation', 'includes_meals', 'includes_transport', 'includes_guide', 'includes_tickets', 'fitness_level_required', 'special_requirements', 'what_to_bring', 'main_image', 'video_url' ] Purpose: Complete tour creation and editing interface Field Groups: Content Management:
Tour Classification:
Logistics:
Capacity & Demographics:
Pricing Structure:
Inclusions:
Advanced Features: User Permission Control: def __init__(self, *args, **kwargs): self.user = kwargs.pop('user', None) super().__init__(*args, **kwargs)
# Limit tour operator choices to user's operators if self.user and not self.user.is_staff: user_operators = TourOperator.objects.filter( models.Q(user=self.user) | models.Q(managers=self.user) ) self.fields['tour_operator'].queryset = user_operators Custom Validation: def clean_slug(self): slug = self.cleaned_data['slug'] qs = Tour.objects.filter(slug=slug) if self.instance: qs = qs.exclude(pk=self.instance.pk) if qs.exists(): raise ValidationError('This slug is already taken.') return slug def clean(self): cleaned_data = super().clean() min_age = cleaned_data.get('min_age') max_age = cleaned_data.get('max_age')
if min_age and max_age and min_age >= max_age: raise ValidationError('Maximum age must be greater than minimum age.')
|
|
3. TourBookingForm - Advanced Booking System class TourBookingForm(forms.ModelForm): # Participant details adult_count = forms.IntegerField(min_value=1, initial=1) child_count = forms.IntegerField(min_value=0, initial=0) senior_count = forms.IntegerField(min_value=0, initial=0)
# Lead traveler details lead_traveler_name = forms.CharField(max_length=200) lead_traveler_email = forms.EmailField() lead_traveler_phone = forms.CharField(max_length=20) Purpose: Customer booking creation with complex validation Key Features: Dynamic Schedule Filtering: def __init__(self, *args, **kwargs): self.tour = kwargs.pop('tour', None) self.user = kwargs.pop('user', None) super().__init__(*args, **kwargs)
if self.tour: # Filter schedules for this tour today = timezone.now().date() self.fields['schedule'].queryset = TourSchedule.objects.filter( tour=self.tour, is_active=True, start_date__gte=today ).order_by('start_date', 'start_time') User Auto-Population: # Pre-fill user details if available if self.user: self.fields['lead_traveler_name'].initial = self.user.get_full_name() self.fields['lead_traveler_email'].initial = self.user.email Complex Business Validation: def clean(self): cleaned_data = super().clean() adult_count = cleaned_data.get('adult_count', 0) child_count = cleaned_data.get('child_count', 0) senior_count = cleaned_data.get('senior_count', 0) schedule = cleaned_data.get('schedule')
total_participants = adult_count + child_count + senior_count
if total_participants == 0: raise ValidationError('At least one participant is required.')
if schedule and self.tour: if total_participants < self.tour.min_participants: raise ValidationError(f'Minimum {self.tour.min_participants} participants required.')
if total_participants > self.tour.max_participants: raise ValidationError(f'Maximum {self.tour.max_participants} participants allowed.')
if total_participants > schedule.remaining_spots: raise ValidationError(f'Only {schedule.remaining_spots} spots available for this schedule.') Advanced Save Method with Pricing Logic: def save(self, commit=True): booking = super().save(commit=False)
# Calculate pricing adult_count = self.cleaned_data['adult_count'] child_count = self.cleaned_data['child_count'] senior_count = self.cleaned_data['senior_count']
schedule = self.cleaned_data['schedule'] base_price = schedule.price_override or self.tour.base_price
# Calculate total price adult_price = base_price * adult_count child_price = (self.tour.child_price or base_price * Decimal('0.7')) * child_count senior_price = (self.tour.senior_price or base_price * Decimal('0.9')) * senior_count
booking.base_price = base_price booking.total_price = adult_price + child_price + senior_price booking.total_participants = self.cleaned_data['total_participants']
if commit: booking.save()
# Update schedule booked spots schedule.booked_spots += booking.total_participants schedule.save()
return booking
|
|
4. TourScheduleForm - Schedule Management class TourScheduleForm(forms.ModelForm): class Meta: model = TourSchedule fields = [ 'schedule_type', 'start_date', 'end_date', 'start_time', 'days_of_week', 'available_spots', 'price_override', 'notes' ] Purpose: Tour schedule creation and management Features:
Business Logic Validation: def clean(self): cleaned_data = super().clean() start_date = cleaned_data.get('start_date') end_date = cleaned_data.get('end_date') schedule_type = cleaned_data.get('schedule_type')
if schedule_type == 'fixed' and not start_date: raise ValidationError('Start date is required for fixed schedules.')
if start_date and end_date and start_date > end_date: raise ValidationError('End date must be after start date.')
|
|
5. TourSearchForm - Advanced Search Interface class TourSearchForm(forms.Form): SORT_CHOICES = [ ('featured', 'Featured'), ('price_low', 'Price: Low to High'), ('price_high', 'Price: High to Low'), ('rating', 'Highest Rated'), ('duration', 'Duration'), ('alphabetical', 'Alphabetical'), ] Purpose: Comprehensive tour search and filtering Search Capabilities: Text Search: search = forms.CharField( required=False, widget=forms.TextInput(attrs={ 'class': 'form-control', 'placeholder': 'Search tours...' }) ) Category Filtering: category = forms.ModelChoiceField( queryset=TourCategory.objects.filter(is_active=True), required=False, empty_label='All Categories', widget=forms.Select(attrs={'class': 'form-select'}) ) Price Range Filtering: min_price = forms.DecimalField( required=False, widget=forms.NumberInput(attrs={ 'class': 'form-control', 'step': '0.01', 'min': '0' }) ) max_price = forms.DecimalField( required=False, widget=forms.NumberInput(attrs={ 'class': 'form-control', 'step': '0.01', 'min': '0' }) )
|
|
6. TourParticipantForm - International Travel Support class TourParticipantForm(forms.ModelForm): """Form for collecting individual participant details including passport upload"""
class Meta: model = TourParticipant fields = [ 'participant_type', 'first_name', 'last_name', 'date_of_birth', 'nationality', 'passport_number', 'passport_expiry', 'passport_image', 'dietary_requirements', 'medical_conditions', 'emergency_contact_name', 'emergency_contact_phone' ] Purpose: International tour participant data collection Key Features: Document Upload Validation: def clean_passport_image(self): passport_image = self.cleaned_data.get('passport_image')
if passport_image: # Validate file size (max 5MB) if passport_image.size > 5 * 1024 * 1024: raise ValidationError('Passport image must be smaller than 5MB.')
# Validate file type valid_extensions = ['.jpg', '.jpeg', '.png', '.pdf'] file_extension = passport_image.name.lower().split('.')[-1] if f'.{file_extension}' not in valid_extensions: raise ValidationError('Please upload a valid image file (JPG, PNG) or PDF.')
return passport_image Required Field Management: def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs)
# Mark required fields required_fields = ['first_name', 'last_name', 'nationality'] for field_name in required_fields: if field_name in self.fields: self.fields[field_name].required = True self.fields[field_name].widget.attrs['required'] = True
|
|
7. TourGuideForm - Professional Guide Management class TourGuideForm(forms.ModelForm): """Form for tour guides to update their profile and upload documents"""
class Meta: model = TourGuide fields = [ 'bio', 'bio_vi', 'specializations', 'languages', 'years_experience', 'certifications', 'license_number', 'certification_document', 'license_document', 'photo_id_document', 'is_available', 'hourly_rate', 'daily_rate', 'base_location' ] Purpose: Tour guide profile and document management Features: Professional Information:
Document Upload System: def _validate_document_file(self, file, file_type): """Validate uploaded document files""" if file: # Validate file size (max 10MB) if file.size > 10 * 1024 * 1024: raise ValidationError(f'{file_type.title()} must be smaller than 10MB.')
# Validate file type valid_extensions = ['.pdf', '.doc', '.docx', '.jpg', '.jpeg', '.png'] file_extension = file.name.lower().split('.')[-1] if f'.{file_extension}' not in valid_extensions: raise ValidationError( f'Please upload a valid {file_type} (PDF, DOC, DOCX, JPG, PNG).' )
return file Rate Management:
|
|
8. Additional Supporting Forms TourItineraryForm: Day-by-day tour planning
TourInclusionForm: Tour inclusion/exclusion management
TourGuideVerificationForm: Admin verification system
Form System Architecture Bootstrap Integration All forms include Bootstrap CSS classes: def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Add CSS classes for field_name, field in self.fields.items(): if field_name not in ['operator_type', 'certification']: field.widget.attrs['class'] = 'form-control'
|
|
Multilingual Support Consistent Vietnamese/English field pairs:
Business Rule Enforcement
User Experience Features
|
|
Security & Validation File Upload Security:
Business Logic Validation:
User Permission Control:
This comprehensive form system provides a robust, user-friendly interface for all tour operators business processes, from operator registration through customer booking and guide management, with strong validation and security measures throughout.
|
Attached Files
You are viewing this article in public mode. Some features may be limited.