Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#21568 closed Bug (fixed)

ModelMultipleChoiceField + show_hidden_initial + has_changed = TypeError

Reported by: dibrovsd@… Owned by: Claude Paroz
Component: Forms Version: 1.6
Severity: Release blocker Keywords: ModelMultipleChoiceField show_hidden_initial
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

hi

def test(request):
    u""" for debug and test's """

    from django import forms
    from django.http import HttpResponse
    from django.template import RequestContext, Template

    user = models.User.objects.get(pk=1)
    changed = None

    class TestForm(forms.Form):
        users = forms.ModelMultipleChoiceField(show_hidden_initial=True, queryset=models.User.objects.all())

    if request.method == 'POST':
        form = TestForm(data=request.POST)
        form.is_valid()

        ### next line raised: TypeError int() argument must be a string or a number, not 'list' ###
        ### django/db/models/fields/__init__.py in get_prep_value, line 613 ###
        changed = form.has_changed() 
    else:
        form = TestForm(initial={'users': [user]})
    
    c = RequestContext(request, {'form': form, 'changed': changed})
    
    t = Template("""
        <form method=POST>
            {% csrf_token %}
            {{form}}
            <input type=submit>
        </form>

        {{changed}}
        """) 

    return HttpResponse(t.render(c))

if change to:
users = forms.ModelMultipleChoiceField(queryset=models.User.objects.all())
and
form = TestForm(data=request.POST, initial={'users': [user]})

This works, but may lead to loss of the changes made by other users

Change History (8)

comment:1 Changed 3 years ago by Claude Paroz

Needs documentation: unset
Needs tests: unset
Owner: changed from nobody to Claude Paroz
Patch needs improvement: unset
Status: newassigned

I'll investigate...

comment:2 Changed 3 years ago by Aymeric Augustin

Can you provide a full traceback please? If you're seeing Django's error debug page, there's a button to show a copy-pasteable backtrace. Please add it in a comment.

comment:3 Changed 3 years ago by Claude Paroz

Severity: NormalRelease blocker
Triage Stage: UnreviewedAccepted

The base issue is that ModelMultipleChoiceField has currently no to_python method. Previously (1.5), has_changed did not call to_python on values coming from hidden initial widgets, so this issue remained unnoticed. Hence, this is also a regression.

comment:4 in reply to:  2 Changed 3 years ago by anonymous

Replying to aaugustin:

Can you provide a full traceback please? If you're seeing Django's error debug page, there's a button to show a copy-pasteable backtrace. Please add it in a comment.

traceback still needed?

comment:5 Changed 3 years ago by Claude Paroz

Has patch: set

Generally, traceback is appreciated, yes. But now that we have a patch to fix the issue, it's not useful any more. Please check if the following patch solves your issue.

https://github.com/django/django/pull/2040

comment:6 Changed 3 years ago by dibrovsd@…

It works. Thank you!

comment:7 Changed 3 years ago by Claude Paroz <claude@…>

Resolution: fixed
Status: assignedclosed

In 8a9c8bb90736451e6bdea82723cbb23a695146fb:

Fixed #21568 -- Added missing ModelMultipleChoiceField to_python method

Thanks dibrovsd at gmail.com for the report and Simon Charette
for the review.

comment:8 Changed 3 years ago by Claude Paroz <claude@…>

In 34c4b93c84e86665d66d0b31da8e30fd581d5b5f:

[1.6.x] Fixed #21568 -- Added missing ModelMultipleChoiceField to_python method

Thanks dibrovsd at gmail.com for the report and Simon Charette
for the review.
Backport of 8a9c8bb90 from master.

Note: See TracTickets for help on using tickets.
Back to Top