我对表单ModelChoiceField有奇怪的行为。一点背景。我需要一个具有某个字段的变量查询集的表单。看看这个question和this,我已经为我的表单创建了一个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查询集之前,一切正常,所以它必须是我正在做的事情。
请帮忙。谢谢!
答案 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中呈现变量的东西会导致错误。