1

我的表单 ModelChoiceField 有奇怪的行为。一点背景。我需要一个具有特定字段的变量查询集的表单。看着这个问题这个,我为我的表单创建了一个 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 验证失败。当我逐步完成时,我注意到与此问题类似,我收到“选择有效选择”错误,可能是因为当调用 super 并进行验证时查询集是Employees.objects.none()。我应该在设置查询集后清除所有错误并重做一个 full_clean,还是应该采取不同的方法?基本上我被困住了,不知道到底发生了什么,也不知道从哪里开始。在我添加 init 方法并拥有一个标准的 Employee 查询集之前,一切都运行良好,所以它一定是我正在做的事情。

请帮忙。谢谢!

4

2 回答 2

0

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

于 2013-10-09T14:19:43.297 回答
0

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

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

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
于 2013-05-01T21:36:51.510 回答