2013-05-01 85 views
1

我有一个表单ModelChoiceField奇怪的行为。一点背景。我需要一个具有特定字段的可变查询集的表单。看看这个questionthis,我已经为我的表单创建了一个init方法来根据传递给init方法的请求来处理这个方法。Django窗体与自定义初始化ModelChoiceField失败验证

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 queryset之前,一切正常,所以它一定是我正在做的事情。

请帮忙。谢谢!

回答

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 
+0

感谢您的可读性提示。今天它的工作。我不知道昨天为什么会失败。 – Shawn 2013-05-02 15:22:07

0

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