django2整合xadmin list index out of range報錯追蹤和處理
今天又搞起了django,個人愛好用最新版的,所以雖然比著老師的視訊做,還是出了莫名其妙的問題
IndexError at /xadmin/goods/goods/add/
list index out of range
遇到了陣列越界
貼下報錯資訊,當然這個看不出什麼,陣列越界,這菜鳥都能看懂的英文
Error during template rendering
In template /Users/seth/pyenv/imooc_env36/lib/python3.6/site-packages/crispy_forms/templates/bootstrap3/field.html, error at line 28
{% if field|is_checkbox and form_show_labels %}
順便上張圖
一般人看到這裡就懵了,反正只知道陣列越界,天知道什麼原因,然後把這個圖貼給別人。
淡定,django的報錯很詳細的,往下看
很明顯是時間這邊出了問題
時間add_time的欄位型別出了問題
先說下django的時間欄位型別
有3個,這裡直接貼網上的
需要了解跟時間相關的三個modelField,
DateTimeField和DateField和TimeField
儲存的內容分別對應著datetime(),date(),time()三個物件。
對於auto_now和auto_now_add。兩者預設值都為False 。
auto_now=Ture,欄位儲存時會自動儲存當前時間,但要注意每次對其例項執行save()的時候都會將當前時間儲存,也就是不能再手動給它存非當前時間的值。
auto_now_add=True,欄位在例項第一次儲存的時候會儲存當前時間,不管你在這裡是否對其賦值。但是之後的save()是可以手動賦值的。也就是新例項化一個model,想手動存其他時間,就需要對該例項save()之後賦值然後再save()。
隨便拷貝了一句,大概只是介紹了auto_now和auto_now_add,和我們報錯無關,這裡只是拓展一下三個時間型別,
然後我們來看這datetime(),date(),time()3個物件
date “1000-01-01”到“9999-12-31” 3位元組
time “-838:59:59”到“838:59:59” 3位元組
datetime “1000-01-01 00:00:00” 到“9999-12-31 23:59:59” 8位元組
date :“yyyy-mm-dd”格式表示的日期值
time :“hh:mm:ss”格式表示的時間值
datetime: “yyyy-mm-dd hh:mm:ss”格式
修改時間格式為DateField,完美解決,
有些人不樂意了,按天的新增時間還有毛用,是的,問題解決了,但業務邏輯不對了
回到之前被忽略的xadmin的第80行程式碼報錯提示
找到相關程式碼
return mark_safe('<div class="datetime clearfix"><div class="input-group date bootstrap-datepicker"><span class="input-group-addon"><i class="fa fa-calendar"></i></span>%s'
'<span class="input-group-btn"><button class="btn btn-default" type="button">%s</button></span></div>'
'<div class="input-group time bootstrap-clockpicker"><span class="input-group-addon"><i class="fa fa-clock-o">'
'</i></span>%s<span class="input-group-btn"><button class="btn btn-default" type="button">%s</button></span></div></div>' % (input_html[0], _(u'Today'), input_html[1], _(u'Now')))
input_html[1]就是報錯的程式碼,因為input_html裡只有一個元素,從報錯資訊裡也能找到input_html的值
仔細看input_html長度是為1的,所以沒辦法取到值
再看上一行程式碼,作者是想通過用“\n”把input_html裡的兩個標籤拆開,但兩個標籤之間沒有換行,所以沒能拆分,導致報錯。
input_html = [ht for ht in super(AdminSplitDateTime, self).render(name, value, attrs).split('\n') if ht != '']
但是,作者當初這樣寫,肯定是能把兩個拆開的,為什麼忽然不行了呢?
我們來看看這個forms是哪個html的
ctrl點MultWidget進去
找到html了
{% spaceless %}{% for widget in widget.subwidgets %}{% include widget.template_name %}{% endfor %}{% endspaceless %}
裡面就一句話,先補充一下spaceless標籤
spaceless標籤:
用法:{% spaceless %}…內容…{% endspaceless %}
含義:刪除包圍內容中的所有tab或者回車字元
所以自然xadmin那邊的程式碼就錯誤了
來看下作者的提交記錄
https://github.com/django/django/commit/47681af34447e5d45f3fdb316497cdf9fbd0b7ce
英文不太好,不過意思應該是空格會導致多個widget的時候顯示有問題,所以就加了spaceless標籤
問題找到了,
但是django畢竟是主框架,我們儘量不要動他的程式碼,
我們來修改xadmin的程式碼
原來使用\n分割的
我們把程式碼改成下面這樣
input_html = [ht for ht in super(AdminSplitDateTime, self).render(name, value, attrs).split('/><') if ht != '']
input_html[0] = input_html[0] + "/>"
input_html[1] = "<" + input_html[1]
原來的程式碼不要刪,如圖,註釋掉就好
但有人可能還不明白了,怎麼date型別就不出錯,其實上面寫了,data是年月日,datetime是年月日時分秒就要2個widget顯示了,所以就出問題了
文章參考https://blog.csdn.net/yuhan963/article/details/79167743,感謝作者