Opened 7 years ago
Closed 7 years ago
#29201 closed Bug (invalid)
Rendering issues when using ArrayField(models.BooleanField())
Reported by: | linluc | Owned by: | |
---|---|---|---|
Component: | contrib.postgres | Version: | 2.0 |
Severity: | Normal | Keywords: | ArrayField BooleanField SplitArrayWidget rendering |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
My goal is to replace 50 Boolean fields with one ArrayField(models.BooleanField(), size=50) so I am prototyping this approach. I have not found a single online example with such combination (ArrayField + BooleanField) and also this area is very poorly documented. I am running into numerous issues and that makes me feel that it was never properly tested. Well, I am offering my help in future testing regarding this issue.
Here is my simple model (using Django 2.0.3):
class Test1Model(models.Model): user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) user_choices = ArrayField(models.BooleanField(), default=(), size=5, null=True)
form:
class Test1Form(forms.ModelForm): class Meta: model = Test1Model fields = ('user_choices',) widgets = { 'user_choices' : SplitArrayWidget(forms.CheckboxInput(),5) }
view:
def run_test1(request): if request.method == 'POST': test_form = Test1Form(instance=request.user.test1model, data=request.POST) if test_form.is_valid(): test_form.save() else: print(test_form.errors) else: test_form = Test1Form(instance=request.user.test1model) return render(request, 'test1/test1.html' , {'test_form': test_form})
template (test1.html):
<!DOCTYPE html> <html> <head> <title>TEST1</title> </head> <body> <form action="." method="post" autocomplete="off"> {{ test_form.as_p }} {% csrf_token %} <p><input type="submit" value="Submit"></p> </form> </body> </html>
Here you will encounter a bug which I already reported (https://code.djangoproject.com/ticket/29197) but it is easy to fix by moving the template directory.
After fixing the template issue the initial page renders OK, 5 check-boxes are present (see attached image, section A).
Problem 1: by default all check-boxes are required and I was unable to reverse that. Adding "required = False" caused the following error:
TypeError: __init__() got an unexpected keyword argument 'required'
See the image, section B.
OK, for the purpose of prototyping I checked all check boxes and submitted the form. The output was highly unexpected (image, section C).
The output page includes 24 check-boxes and by looking at the generated HTML we can see why (hint: value=""):
<p><label for="id_user_choices_0">User choices:</label> <input type="checkbox" name="user_choices_0" value="T" checked required id="id_user_choices_0" /> <input type="checkbox" name="user_choices_1" value="r" checked required id="id_user_choices_1" /> <input type="checkbox" name="user_choices_2" value="u" checked required id="id_user_choices_2" /> <input type="checkbox" name="user_choices_3" value="e" checked required id="id_user_choices_3" /> <input type="checkbox" name="user_choices_4" value="," checked required id="id_user_choices_4" /> <input type="checkbox" name="user_choices_5" value="T" checked required id="id_user_choices_5" /> <input type="checkbox" name="user_choices_6" value="r" checked required id="id_user_choices_6" /> <input type="checkbox" name="user_choices_7" value="u" checked required id="id_user_choices_7" /> <input type="checkbox" name="user_choices_8" value="e" checked required id="id_user_choices_8" /> <input type="checkbox" name="user_choices_9" value="," checked required id="id_user_choices_9" /> <input type="checkbox" name="user_choices_10" value="T" checked required id="id_user_choices_10" /> <input type="checkbox" name="user_choices_11" value="r" checked required id="id_user_choices_11" /> <input type="checkbox" name="user_choices_12" value="u" checked required id="id_user_choices_12" /> <input type="checkbox" name="user_choices_13" value="e" checked required id="id_user_choices_13" /> <input type="checkbox" name="user_choices_14" value="," checked required id="id_user_choices_14" /> <input type="checkbox" name="user_choices_15" value="T" checked required id="id_user_choices_15" /> <input type="checkbox" name="user_choices_16" value="r" checked required id="id_user_choices_16" /> <input type="checkbox" name="user_choices_17" value="u" checked required id="id_user_choices_17" /> <input type="checkbox" name="user_choices_18" value="e" checked required id="id_user_choices_18" /> <input type="checkbox" name="user_choices_19" value="," checked required id="id_user_choices_19" /> <input type="checkbox" name="user_choices_20" value="T" checked required id="id_user_choices_20" /> <input type="checkbox" name="user_choices_21" value="r" checked required id="id_user_choices_21" /> <input type="checkbox" name="user_choices_22" value="u" checked required id="id_user_choices_22" /> <input type="checkbox" name="user_choices_23" value="e" checked required id="id_user_choices_23" /> </p>
I should note that the values are saved in the database correctly, but still the Django included rendering choices (as_p, as_ul, as_table) are broken here.
Please also note that the label assignment is broken as well, there is only one label generated for all check-boxes.
Attachments (1)
Change History (2)
by , 7 years ago
Attachment: | ArrayError.png added |
---|
comment:1 by , 7 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
The default form field is
SimpleArrayField
which isn't compatible with your widget override ofSplitArrayWidget
. You need to use theSplitArrayField
form field with that widget.