2013-05-01 95 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中渲染變量會導致錯誤。