You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django表单中校验字段大小关系?自定义校验函数未生效

Fixing Your Django Form Time Validation Issue

The reason your compare_mon method isn’t running at all is because Django’s form system doesn’t automatically execute custom methods with arbitrary names during validation. You need to hook into Django’s built-in validation lifecycle methods to make your time comparison checks actually run.

Here’s how to fix it:

Option 1: Use the general clean() method (best for cross-field validation)

The clean() method is called after all individual field clean methods, making it perfect for comparing multiple fields like start and end times. If you have multiple days (mon, tues, wed, etc.), you can loop through them to avoid repeating code:

class TimeOpeningHoursForm(forms.ModelForm):
    class Meta:
        model = BusinessOpeningHours
        fields = ('mon_st', 'mon_end', 'tue_st', 'tue_end', ...)
        widgets = {
            'mon_st': Select(attrs={'class': 'form-control'}),
            'mon_end': Select(attrs={'class': 'form-control'}),
            'tue_st': Select(attrs={'class': 'form-control'}),
            'tue_end': Select(attrs={'class': 'form-control'}),
            ...
        }
    
    def clean(self):
        cleaned_data = super().clean()
        # Define pairs of start/end fields for each day
        day_field_pairs = [
            ('mon_st', 'mon_end'),
            ('tue_st', 'tue_end'),
            # Add wed_st/wed_end, thu_st/thu_end, etc. here
        ]
        
        for start_field, end_field in day_field_pairs:
            start_time = cleaned_data.get(start_field)
            end_time = cleaned_data.get(end_field)
            
            # Only validate if both fields have valid data (avoids errors from required fields failing first)
            if start_time and end_time:
                if start_time > end_time:
                    # Attach the error to the end field for better user feedback
                    day_name = start_field.split('_')[0].capitalize()
                    self.add_error(end_field, f"{day_name} start time must be before end time.")
        
        return cleaned_data

Option 2: Call your custom method from clean()

If you want to keep your compare_mon logic separate, you can call it directly from the clean() method (which Django does recognize):

class TimeOpeningHoursForm(forms.ModelForm):
    # ... your Meta and widgets code remains the same ...
    
    def clean(self):
        cleaned_data = super().clean()
        self.compare_mon(cleaned_data)
        # Add calls to compare_tue(), compare_wed(), etc. if needed
        return cleaned_data
    
    def compare_mon(self, cleaned_data):
        st = cleaned_data.get('mon_st')
        end = cleaned_data.get('mon_end')
        if st and end and st > end:
            self.add_error('mon_end', "Monday start time must be less than end time.")

Key Tips:

  • Always call super().clean() first to get the validated cleaned data from parent methods.
  • Use cleaned_data.get() instead of direct indexing to avoid KeyError if a field failed earlier validation (like a required field left empty).
  • Use self.add_error() to attach errors to specific fields—this makes error messages show up next to the relevant input, improving user experience.

Content of the question originates from Stack Exchange, asked by Maddie Graham

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 16:22:45