解決Python3.6.5+Django2.0集成xadmin後臺點擊添加或者內容詳情報 list index out of range 的錯誤

一 問題說明
在建立Model的時候,若是存在類型是DateTimeField的字段,則在xadmin後端管理界面裏,對該Model進行添加操做的時候,會報list index out of range。html

這是上篇文章建立的Model:git

class IDC(models.Model):
name = models.CharField(max_length=64)
contact = models.CharField(max_length=32)
phone = models.CharField(max_length=32)
address = models.CharField(max_length=128)
create_time = models.DateField(auto_now=True)

def __str__(self):
return self.name

class Meta:
verbose_name = "IDC機房"
verbose_name_plural = verbose_name

將該Model的create_time字段類型修改以下:github

create_time = models.DateTimeField()

而後登陸xadmin系統,進入「IDC機房」管理界面,點擊添加按鈕,即會重現該問題。django

二 問題緣由
首先,報錯信息裏已經指出了報錯的代碼:bootstrap

venv\lib\site-packages\xadmin\widgets.py in render, line 80後端

按照提示的目錄,找到具體的代碼:less

def render(self, name, value, attrs=None):
input_html = [ht for ht in super(AdminSplitDateTime, self).render(name, value, attrs).split('\n') if ht != '']
# return input_html
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')))

 

上面貼出來的最後一行代碼就是widgets.py的第80行代碼。ui

input_html[1]就是報錯的代碼,由於input_html裏只有一個元素,從報錯信息裏也能找到input_html的值以下:spa

['<input type="text" name="create_time_0" class="date-field form-control '
'admindatewidget" size="10" required id="id_create_time_0" /><input '
'type="text" name="create_time_1" class="time-field form-control '
'admintimewidget" size="8" required id="id_create_time_1" />']

閱讀代碼後,能夠看出下面這句代碼是但願用「\n」把input_html裏的兩個標籤拆開,但兩個標籤之間沒有換行,因此沒能拆分,致使報錯。code

input_html = [ht for ht in super(AdminSplitDateTime, self).render(name, value, attrs).split('\n') if ht != '']

可是,做者當初這樣寫,確定是能把兩個拆開的,爲何突然不行了呢?

繼續查看兩個標籤的生成代碼,發現其來源於如下模板:

venv\Lib\site-packages\django\forms\templates\django\forms\widgets\multiwidget.html

該html模板代碼以下:

{% spaceless %}{% for widget in widget.subwidgets %}{% include widget.template_name %}{% endfor %}{% endspaceless %}

spaceless標籤:

用法:{% spaceless %}…內容…{% endspaceless %}

含義:刪除包圍內容中的全部tab或者回車字符

看到spaceless,猜想問題就出在這個標籤上,推測這個標籤是Django後來的版本加上去的。

查看Django的代碼提交記錄,驗證了猜想,在Django2.0.1版本和1.11.9版本,看到了追加spaceless標籤的提交記錄,提交記錄以下:

https://github.com/django/django/commit/47681af34447e5d45f3fdb316497cdf9fbd0b7ce
https://github.com/django/django/commit/c1d57615ac60171a73e1922a48ebc27fe513357e

三 解決問題
方案一
既然問題是因爲模板文件追加了spaceless標籤致使的,那麼刪除spaceless標籤,將模板代碼改爲以下形式,是否是就能解決問題呢?

{% for widget in widget.subwidgets %}{% include widget.template_name %}{% endfor %}

答案是確定的,確實能夠解決問題。

不過,spaceless標籤是Django做爲bug修復追加的代碼,不建議刪除,刪除後,不清楚在其餘地方會不會出現問題。

方案二
既然「\n」不能拆分標籤,那麼就換一種拆分方式,使用「/><」拆分。

原代碼:

input_html = [ht for ht in super(AdminSplitDateTime, self).render(name, value, attrs).split('\n') if ht != '']

修改後代碼:

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]
相關文章
相關標籤/搜索