2017-10-15 68 views
0

我想就如何測試我的Django表單中的錯誤提供一些幫助或建議。它負責確保用戶輸入有效的會話ID,該ID用作第三方API的身份驗證令牌。有效的ID長度爲32個字符和字母數字。爲什麼Django AssertFormError拋出TypeError:'property'類型的參數不可迭代?

我選擇了驗證字段的方法,而不是模型。

當我使用開發服務器手動測試它時,它按預期工作。 I.E.如果用戶粘貼錯誤長度的字符串或特殊字符,則該字段的validate方法會創建錯誤,然後通過for循環顯示html模板中的表單錯誤。

我不明白以下錯誤。我暫時修改了testcases.py來證明錯誤正在傳遞給它 - 那麼爲什麼context [form]會拋出一個'property',並且它是如何到達那裏的?

我使用Django 1.10和Python 3.5.1

====================================================================== 
ERROR: test_index_sessid_short_strings (poe.tests.TestBannerButtons) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "/Users/adam.green/Documents/workspace/poe-client/poetools_project/poe/tests.py", line 105, in test_index_sessid_short_strings 
    self.assertFormError(response, 'form', "new_sessid" , 'The Session ID needs to be exactly 32 characters long') 
    File "/Users/adam.green/.virtualenvs/poe-tools/lib/python3.5/site-packages/django/test/testcases.py", line 421, in assertFormError 
    if field in context[form].errors: 
TypeError: argument of type 'property' is not iterable 

---------------------------------------------------------------------- 
Ran 1 test in 0.805s 

測試

def test_index_sessid_short_strings(self): 
    url = reverse('index') 
    response = self.client.post(url, {'new_sessid': "f14"}) 
    self.assertFormError(response, 'form', "new_sessid" , 'The Session ID needs to be exactly 32 characters long') 

form.py

class SessID(forms.Field): 

    def validate(self, session_id): 
     """Check if value consists only of valid emails.""" 
     # Use the parent's handling of required fields, etc. 
     super().validate(session_id) 
     if len(session_id) <32> len(session_id): 
      raise ValidationError(
            _('The Session ID needs to be exactly 32 characters long'), 
            code = 'sessid wrong length' 
           ) 
     if not re.match("^[A-Za-z0-9]*$", session_id): 
      raise ValidationError(
            _('The Session ID should only have letters and numbers, no special characters'), 
            code = 'sessid not alphanumeric' 
           )   


class ResetSessID(forms.ModelForm): 
    new_sessid = SessID() 
    #forms.CharField(widget=forms.TextInput(attrs={'class':'special', 'size': '32'})      ) 

    def __init__(self, *args, **kwargs): 
     super(ResetSessID, self).__init__(*args, **kwargs) 
     stdlogger.info("init of ResetSessID") 
     #print("dir")#, self.fields.items['new_sessid']) 
     if kwargs.get('instance'): 
      new_sessid = kwargs['instance'].new_essid 
      stdlogger.info("inner kwargs loop") 
     return super(ResetSessID, self).__init__(*args, **kwargs) 

    class Meta: 
     model = PoeAccount 
     exclude = ("acc_name", "sessid") 

    def clean(self): 
     if 'reg_button' in self.data: 
      print("amazing") 

views.py

def index(request): 
    request.session.set_test_cookie() 
    item_category_list = ItemCategory.objects.all() 
    modifications_list = FixCategory.objects.all() 
    context_dict = {} 
    if request.user.is_authenticated: 
     if request.method == 'POST': 
      form = ResetSessID(request.POST)  
      if form.is_valid(): 
       # get the right account 
       me = poe.models.PoeAccount.objects.get(
         acc_name = request.user.poeuser.poe_account_name 
         ) 
       # commit new sessid passed to here 
       # me.full_clean() 
       me.sessid = form['new_sessid'].value() 
       me.save(update_fields=['sessid']) 
       context_dict["old_sessid"] = me.sessid 
       context_dict['form'] = ResetSessID 
       response = render(request,'poe/index.html', context_dict) 
       #return response 
      else: 
       context_dict['errors'] = form.errors 
       print("form has errors", form.errors) 
       me = poe.models.PoeAccount.objects.get(
         acc_name = request.user.poeuser.poe_account_name 
         ) 
       context_dict['errors'] = form.errors 
       context_dict["old_sessid"] = me.sessid 
       context_dict['form'] = ResetSessID 
       for x, y in form.errors.items(): 
        print("errors", x, y) 
       response = render(request,'poe/index.html', context_dict) 
       #return response 

     else: 
      context_dict = {'form': ResetSessID} 
      me = poe.models.PoeAccount.objects.get(acc_name = request.user.poeuser.poe_account_name) 
      context_dict["old_sessid"] = me.sessid 

    context_dict.update({'item_categories': item_category_list, 'mods': modifications_list}) 
    # make sure the session keeps track of the number of visits 
    visits = request.session.get('visits') 
    if not visits: 
     visits = 1 
    reset_last_visit_time = False 
    last_visit = request.session.get('last_visit') 
    if last_visit: 
     last_visit_time = datetime.datetime.strptime(last_visit[:-7], "%Y-%m-%d %H:%M:%S") 
     if (datetime.datetime.now() - last_visit_time).seconds > 0: 
      # ...reassign the value of the cookie to +1 of what it was before... 
      visits = visits + 1 
      # ...and update the last visit cookie, too. 
      reset_last_visit_time = True 
    else: 
     # Cookie last_visit doesn't exist, so create it to the current date/time. 
     reset_last_visit_time = True 
    # make sure the session keeps track of time last visited 
    if reset_last_visit_time: 
     request.session['last_visit'] = str(datetime.datetime.now()) 
     request.session['visits'] = visits 
    context_dict['visits'] = visits 

    #print("context_dict", context_dict) 
    response = render(request,'poe/index.html', context_dict) 

    return response 

回答

1

發生這種情況,因爲你正在設置form上下文變量在你看來是你的形式類本身,而不是一個實例類的

替換:

context_dict['form'] = ResetSessID

有:

context_dict['form'] = form

其中form是你定義略高於您form.is_valid()檢查變量。如果您的form.is_valid()區塊在兩個分支中都執行此操作。

的外,如果塊以及同一件事:

# Not a post request 
context_dict = {'form': ResetSessID()} # Note brackets 

您目前不會在所有的工作至今,我所看到的視圖 - 它可能是值得得到它的工作你寫測試之前,它。

+0

真棒,非常感謝 - 立即修復它。 – Flicky

相關問題