square brackets bug

Hi,

Have just tried to log a ticket for a bug however the ticket tracker said it was 94% convinced it was spam so wouldn’t take it, um lucky me? Not sure if this is the right place but putting it here instead for someone’s attention.


Hi,

I’ve come across an issue where my forms are having random sets of empty square braces rendered into them, I can’t find any mention of this other than one StackOverflow post where a guy said he downgraded his python and it went away.

I’m on a Mac running Python 3.12.2 (from python website) and Homebrew Apache 2. Curiously this issue only occurs when viewing sites through Apache/WSGI not when running the test server using Django. However, this does occur both in my own apps as well as the Django admin login page.

I’ve had a look into this and can see that the brackets are getting returned by Django in the form render so this isn’t any spurious typo on my part or some dodgy CSS as far as I can tell.

I made the RenderableMixin function in forms/utils.py write out the code it was returning to a temp file and I can see them in there:

└─$ cat /tmp/render
<tr>
    <th><label for="id_term">Search Term:</label></th>
    <td>
      []
      <input type="text" name="term" maxlength="25" required id="id_term">

    </td>
  </tr>

I’m not sure how to look any deeper down than that as I’m not familiar with the code base. This is happening off the back of a very simple form with nothing weird going on, it’s pretty much as per the official tutorials as I’m just learning this

{% block content %}
		<form action="{% url 'accounts:search' %}" method="post">
			{% csrf_token %}
			{{ form.as_table }}
			<input type="submit" value="Submit">
		</form>
{% endblock %}
class SearchForm(forms.Form):
	term = forms.CharField(label="Search Term", max_length=25)


def DisplaySearchForm(request):
	if request.method == "POST":
		form = SearchForm(request.POST)
		if form.is_valid():
			return HttpResponseRedirect(reverse("accounts:search_results", kwargs={'term': form.cleaned_data['term']}))
	else:
		form = SearchForm()

	return render(request, "accounts/search.html", {"form": form})

What version of Django are you using?

Also when you say:

Are you running your project using mod_wsgi, or do you have your Apache configured to proxy the requests through to a uwsgi instance?

The django is 5.0.3 (says PIP)

Requirement already satisfied: django in /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages (5.0.3)

I set up the Apache with mod_wsgi yes

LoadModule wsgi_module /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/mod_wsgi/server/mod_wsgi-py312.cpython-312-darwin.so

I did some screenshots but it doesn’t seem to want to attach them

To try and narrow this down, do you still get the brackets if you render this using as_div or as_p?

What do you get if you add a print(form) immediately before the return statement?

Have you overridden any of the system templates? (Such as django/forms/table.html)

Yes I’ve tried using the various options (div, table, p, ul) is doesn’t seem to make a difference they just appear within the tags.

Table:

<div class="row">
	<div class="col-2 col-12-small">
		<form action="/leodis_admin/search/" method="post">
			<input type="hidden" name="csrfmiddlewaretoken" value="LivzmTJw8dI3bbiOByKFaqcQhV3Zv1PLVRTqwgv1Qq5SLFUjgasqvgCzgr2Yn2td">
			<tr>
    <th><label for="id_term">Search Term:</label></th>
    <td>
      []
      <input type="text" name="term" maxlength="25" required id="id_term">
      
      
        
      
    </td>
  </tr>
			<input type="submit" value="Submit">
		</form>
	</div>
</div>

as p

<div class="row">
	<div class="col-2 col-12-small">
		<form action="/leodis_admin/search/" method="post">
			<input type="hidden" name="csrfmiddlewaretoken" value="DwB4W2r3jcebi2tqiDNh7BS4fbFkDxEQN5ZV6pdy1pB0Sw5VXfv2sriNeHEjvyii">
			[]


  []
  <p>
    <label for="id_term">Search Term:</label>
    <input type="text" name="term" maxlength="25" required id="id_term">
    
    
      
    
  </p>
			<input type="submit" value="Submit">
		</form>
	</div>
</div>

ul

<div class="row">
	<div class="col-2 col-12-small">
		<form action="/leodis_admin/search/" method="post">
			<input type="hidden" name="csrfmiddlewaretoken" value="2t8yGhxBymu3r3H8n5yXbFYocZIfXNLYc2wpQEj6gzRS1xjD2HgIwvo7bvHePOpq">
			<li>
    []
    <label for="id_term">Search Term:</label>
    <input type="text" name="term" maxlength="25" required id="id_term">
    
    
      
    
  </li>
			<input type="submit" value="Submit">
		</form>
	</div>
</div>

printing the form when running the test server they are not in there in console output:

Quit the server with CONTROL-C.

<div>
    <label for="id_term">Search Term:</label>



<input type="text" name="term" maxlength="25" required id="id_term">



</div>
[29/Mar/2024 20:40:44] "GET /search/ HTTP/1.1" 200 2461

For testing with the apache I had it write the same output to /tmp (not sure how else I’d see it), and they are there:

┌──(ian@phasma)-[~/code/python/_django]
└─$ cat /tmp/form
[]


  <div>
    <label for="id_term">Search Term:</label>


[]
<input type="text" name="term" maxlength="25" required id="id_term">



</div>

I haven’t fiddled with any of the templates no, I’ve also just done a pip force reinstall for Django just in case I’d done anything accidental to get them back to the commit and there’s no change.

Ian

Side note: If you’re using mod_wsgi, I thought there was an option to direct print output to the Apache error log file. (But it’s been at least 10 years since I’ve worked seriously with it.)

That’s helpful to know, because it almost certainly verifies that it’s not a template issue. (Each one uses a different template.)

What’s interesting is that I see two sets of brackets for the as_p

Actually, at this point, I’d need to agree with the other advice you’ve found. I’d try installing and running this with Python 3.11. It’s quite possible that there’s some incongruity between mod_wsgi and Python 3.12. (What version of mod_wsgi are you using?)

looks like the mod_wsgi is 5.0.0 I think

Is mod_wsgi not the recommended way to get these django sites up and running? For a long number of years I worked with perl+apache and then php+apache so went into this looking at python+apache as a natural progression but it doesn’t seem to work as nicely with it in general, I guess as it’s not primarily seen as a web type language,

That’s a question of who you ask. (It is one of the featured configurations in the docs.)
I’m not a fan, but that’s me. I’m a huge non-fan of mod_wsgi, it’s too limiting for what I need to support. If I had to use Apache again, I’d use it as a proxy in front of uwsgi in a manner similar to how I’d do it with nginx.

Just wanted to follow up on this (in case anyone arrives from Google) to say that I’ve switched over to nginx+uwsgi for my projects and this bug has gone away so must definitely be something to do with the mod_wsgi bit of Apache as expected.

Also probably should have just done it this way in the first place :slight_smile:

For the record, I am experiencing the same error. When forms are rendered with form.as_p or similar, the square brackets appear in front of the input fields (see screen shot of Django admin login). I haven’t found a solution yet (except to avoid the symptoms by building my forms in the template itself, which is not that hard).
Versions: Apache 2.4.59, mod_wsgi 5.0.0, Python 3.12.3 and Django 5.0.5
If I find out anything about the cause, I will report back here.
Screenshot 2024-05-07 at 18.57.38

1 Like

It seems to be the form errors are being converted from array to string


Server version: Apache/2.4.58 (Ubuntu)
Ubuntu 24.04
Python 3.12.3
Django==4.2

<section class="modal-container login-modal-container">
        <button class="close-dialog">
          <img src="{% static 'img/close-activity-button-bg.png' %}" alt="Close dialog"/>
        </button>
        <h2>
          Welcome to Safety Town!
        </h2>
		<div class="form-box login">
			<div class="form-header">
        I have an account already.
      </div>
			<form method="post" class="login-form">
        {% if patron_login_form.non_field_errors %}
          <ul class="errorlist">
          {% for error in patron_login_form.non_field_errors %}
            <li>{{ error|escape}}</li>
          {% endfor %}
          </ul>
        {% endif %}
				{% csrf_token %}
        <p>
        {{ patron_login_form.email.errors }}
        <label for="id_email">My email address is</label>
        {{ patron_login_form.email }}
        </p>
				<input type="hidden" name="form_id" value="login">
				<input type="submit" value="Log in" class="pulse-me">
			</form>
		</div>
		<div class="form-box register">
			<div class="form-header">I don't have an account yet. Sign me up!</div>
			<form method="post" class="register-form" id="register-form">
				{% csrf_token %}
                {{ register_form.non_field_errors }}
                <p>
                    {{ register_form.school.errors }}
                    <label for="id_school">Name of your school</label>
                    {{ register_form.school }}
                    <span id="school-help" class="form-help-text show">If you can't find your school in the list, please enter the name in the field above.</span>
                </p>
                <p>
                    {{ register_form.email.errors }}
                    <label for="id_email">Your email address</label>
                    {{ register_form.email }}
                </p>
                <p id="recaptcha-required" style="color:red;display:none">
                    Please check the recaptcha
                </p>
                <p>
                  <div class="g-recaptcha" data-sitekey="{{ re_captcha_site_key }}"></div>
                </p>
				<input type="hidden" name="form_id" value="register">
				<input type="submit" value="Register" class="pulse-me">
			</form>
		</div>
        <div class="clearfix"></div>
    </section>

After poking around in Django core, I believe this issue is caused by this Python 3.12 bug relating to subinterpreters: Weird `int.__str__` behaviour inside sub-interpreters · Issue #117482 · python/cpython · GitHub I was able to reproduce the problem using a modified version of the test case.

import _xxsubinterpreters as interpreters

script = """
import django
from django.conf import settings
from django.forms.utils import ErrorList

settings.configure()
django.setup()

empty = ErrorList([])

print(str(empty))
"""

exec(script)
# Output: ""

interp_id = interpreters.create(isolated=False)
interpreters.run_string(interp_id, script)
# Output: []
1 Like

Just chiming in with another case. I had been working on a project under Python 3.10.11, Django 5.0.7, and mod_wsgi 5.0.0 (Apache Server 2.4.61). Everything on my app’s login page was normal.

Then I re-created the virtual env with Python 3.12.4, keeping all other elements the same. When I pointed Apache to the new environment, the Login page now adds in 3 pairs of square brackets – two pairs of them above the Username entry, and one pair above the Password entry.

If I activate the exact same virtual environment and run the app in the Dev server from a Powershell command line, I do not get the square brackets. So it’s all Apache + mod_wsgi + Python 3.12.

I am experiencing same bug. Have you found the solution?
Capture

Your options are:

  1. Wait until the cpython bug referenced in my previous comment has been fixed
  2. Use a Python version not affected by the bug, eg, 3.11
  3. Use a different WSGI server. See the Django docs for some options besides mod_wsgi.