Django表单与ModelChoiceField的自定义init失败验证

时间:2013-05-01 21:12:22

标签: django django-forms

我对表单ModelChoiceField有奇怪的行为。一点背景。我需要一个具有某个字段的变量查询集的表单。看看这个questionthis,我已经为我的表单创建了一个init方法,以根据传递给init方法的请求来处理它。

class QueryTimeEntryForm(forms.Form):
query_start_date = forms.DateField(label='Start Date:', required=True, widget=forms.TextInput(), input_formats=['%m/%d/%Y', '%Y-%m-%d'])
query_end_date = forms.DateField(label='End Date:', required=True, widget=forms.TextInput(), input_formats=['%m/%d/%Y', '%Y-%m-%d'])
time_query_unit = forms.ModelChoiceField(queryset=Unit.objects.all().order_by('unit'), label='', required=False, empty_label='Choose a unit', widget=forms.Select())
time_query_employee = forms.ModelChoiceField(queryset=Employee.objects.none(), label='', required=False, empty_label='Choose an employee', widget=forms.Select())
time_query_radio = forms.ChoiceField(label='', widget=forms.RadioSelect(attrs={'class':'queryRadio'}), choices=QUERY_CHOICES, initial='1')

def __init__(self, *args, **kwargs):
    self.request = kwargs.pop('request', None)
    super (QueryTimeEntryForm, self).__init__(*args, **kwargs)
    #depending on the user, set the queryset of the employee drop down
    #get the employee category for the user
    today = datetime.today()
    emp = Employee.objects.filter(user__exact=self.request.user)
    ec = EmployeeCategory.objects.filter(employee__exact=emp[0]).filter(effectiveDate__lte=today).filter(Q(enddate__gte=today) | Q(enddate__isnull=True))[0]

    if ec.category.category == 1:
        self.fields['time_query_employee'].queryset = Employee.objects.filter(user__exact=self.request.user)
    elif ec.category.category == 2:
        #get the unit for this category 2 employee
        unit = EmployeeUnit.objects.filter(employee__exact=emp).filter(effective_date__lte=today).filter(Q(end_date__gte=today) | Q(end_date__isnull=True))[0].unit
        #get the employees who currently share the unit with the current category 2 employee, excluding the current category 2 employee
        self.fields['time_query_employee'].queryset = Employee.objects.filter(employee_for_employeeunit__unit__exact=unit).filter(Q(employee_for_employeeunit__end_date__gte=today) | Q(employee_for_employeeunit__end_date__isnull=True)).exclude(employee_for_employeeunit__exact=emp).order_by('user__first_name')
    else:
        #get category 1
        cat = Category.objects.filter(category__exact=1)[0]
        self.fields['time_query_employee'].queryset = Employee.objects.filter(employee_for_employeecategory__category__exact=cat).filter(Q(employee_for_employeecategory__enddate__gte=today) | Q(employee_for_employeecategory__enddate__isnull=True)).order_by('user__first_name')

当表单没有绑定时,一切正常。我只是在html的下拉列表中得到了我期望的员工。我遇到的问题是,在发布表单时,ModelChoiceField无法通过验证。当我单步执行时,我注意到类似于this question,我得到了“选择一个有效的选择”错误,可能是因为当调用super并且验证发生时,查询集是Employees.objects.none()。我应该在设置查询集后清除所有错误并重做full_clean,还是应该采用不同的方法?基本上我被卡住了,不知道到底发生了什么,也不知道从哪里开始。在我添加init方法并拥有标准的Employee查询集之前,一切正常,所以它必须是我正在做的事情。

请帮忙。谢谢!

2 个答案:

答案 0 :(得分:0)

您是否能够测试所有三个类别分支?我个人可能会在__init__调用的开头插入一个pdb.set_trace()调用,使用Django开发服务器运行它,看看发布表单时会发生什么。

作为可读性提示 - 您可以省略__exact,并且您可以使用.exclude替换您的过滤器(Q()| Q())调用进行反向比较,因为空值永远不会为真。也就是说,而不是原来的:

unit = EmployeeUnit.objects.filter(employee__exact=emp).filter(effective_date__lte=today).filter(Q(end_date__gte=today) | Q(end_date__isnull=True))[0].unit

你可以写:

unit = EmployeeUnit.objects.filter(employee=emp, effective_date__lte=today).exclude(end_date__lt=today)[0].unit

答案 1 :(得分:0)

@Shawn,我今天遇到了同样的问题。我注意到调试时(在Eclipse中,显示/活动的Variables窗格)表单的__init__()方法和行代码,我得到“选择有效选择”错误。但是,如果我清除断点并让它运行,或者如果我使用未显示/未激活的变量窗格进行行步调试,那么我不会收到错误。在Eclipse中呈现变量的东西会导致错误。