Problem Description
When creating a Model, if a field of type DateTimeField exists, the list index out of range is reported when adding to the Model in the xadmin back-end management interface.
This is the Model created in the last article:
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 Computer room" verbose_name_plural = verbose_name
Modify the Model's create_time field type as follows:
create_time = models.DateTimeField()
Then log in to the xadmin system, enter the IDC Room management interface, click the Add button, and the problem will recur.
Second, the cause of the problem
First, the error code is indicated in the error message:
venv\lib\site-packages\xadmin\widgets.py in render, line 80
Follow the prompted directory to find the specific code:
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')))
The last line of code pasted above is line 80 of widgets.py.
input_html[1] is the error code because there is only one element in input_html, and the value of input_html can also be found from the error message as follows:
['<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" />']
After reading the code, you can see that the following code is intended to use "\n" to split the two tags in input_html, but there is no line break between the two tags, so it cannot be split, causing an error.
input_html = [ht for ht in super(AdminSplitDateTime, self).render(name, value, attrs).split('\n') if ht != '']
But when the author wrote this, he could certainly split the two apart. Why couldn't it suddenly work?
Continue to look at the generated code for the two tags and find that they came from the following templates:
venv\Lib\site-packages\django\forms\templates\django\forms\widgets\multiwidget.html
The html template code is as follows:
{% spaceless %}{% for widget in widget.subwidgets %}{% include widget.template_name %}{% endfor %}{% endspaceless %}
The spaceless tag:
Usage: {% spaceless%}...Content...{% endspaceless%}
Meaning: Delete all tab s or carriage return characters in the enclosure
When you see spaceless, the guess comes from this tag, which is supposed to have been added by a later version of Django.
Check Django's code submission record to verify your guess. At Django version 2.0.1 and 1.11.9, you see the submission record with the spaceless tag appended. The submission record is as follows:
https://github.com/django/django/commit/47681af34447e5d45f3fdb316497cdf9fbd0b7ce
https://github.com/django/django/commit/c1d57615ac60171a73e1922a48ebc27fe513357e
Three Solutions
Scheme One
Since the problem is caused by appending the spaceless tag to the template file, can deleting the spaceless tag and changing the template code to the following form solve the problem?
{% for widget in widget.subwidgets %}{% include widget.template_name %}{% endfor %}
The answer is yes, it does solve the problem.
However, the spaceless tag is the code that Django appends as a bug fix and is not recommended for deletion. After deletion, it is not clear if there will be problems elsewhere.
Option 2
Since "\n" cannot split labels, use "/><" instead.
Original code:
input_html = [ht for ht in super(AdminSplitDateTime, self).render(name, value, attrs).split('\n') if ht != '']
Modify the code after:
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]