[Solved]-Django: <ul> inside help_text of field

9👍

As you already mentioned, in HTML there is a concept of block and inline elements.
In short block elements generate a new line and may contain other block and inline elements. Inline elements don’t generate a new line and may contain other inline elements, but not block elements.

MDN web docs offers more information on block and inline elements.

Since span is an inline element, you can’t place ul which is a block-level element inside. Or, you could, but then it’s not a valid HTML, and that’s not what you want.

Since you’re using a third-party code, modifiying it could introduce other problems.
You could fork it, modify the parts you need and then use your fork. But when that third-party code gets updated, you have to repeat the whole process.

In cases like that you could just do monkey patching.
For your particular problem we could therefore do something like this:

from django import forms

class MyBaseForm(forms.BaseForm):
    def as_table(self):
        "Return this form rendered as HTML s -- excluding the ."
        return self._html_output(
            normal_row='%(label)s%(errors)s%(field)s%(help_text)s',
            error_row='%s',
            row_ender='',
            help_text_html='<div class="helptext">%s</div>',
            errors_on_separate_row=False)

BaseForm.as_table = MyBaseForm.as_table

You can place this code in your forms.py or any other file that is suitable to you.

Now the help_text will be rendered as a div element, which is a block-level element. You can place an unordered list ul inside and have a valid HTML.

Monkey patching isn’t the most beautiful way of solving problems, but it is in my opinion a pragmatic way to overcome some tricky issues.

👤cezar

5👍

I think what you want is not exactly to “have an <ul> inside your help_text” but rather “display a bullet list inside your help text”.

So if you don’t have the ability to override as_table() or use something other than as_table(), I hope you are still able to change the stylesheet. In which case you can fake your ul with a span:

from django.utils.safestring import mark_safe

help_text=mark_safe(
    '<span class="fake-ul">'
    '<span class="fake-li">foo</span>'
    '<span class="fake-li">bar</span>'
    '</span>'
)

And here is your CSS:

.fake-ul {
  display: block;
  padding-left: 40px;
  list-style-type: disc;
}
.fake-li {
  display: list-item;
}

2👍

So probably it is too late, but I think you may find Django widget tweaks usefull.

👤alex

Leave a comment