UPDATE: Dynamic MultipleChoiceField changes instances to strings

89 Views Asked by At

I have a django form that has a multiple choice field. The field should be dynamic, that is, only the records associated with the user who is currently logged in should be displayed. I've managed to put this together so far;

forms.py

class myForm(forms.ModelForm):

    def __init__(self, someUser, *args, **kwargs):
        super(myForm, self).__init__(*args, **kwargs)

        someRecords = models.SomeModel.objects.filter(someUser = someUser)
        #The line above gets records associated with a specific user

        displayNames = []
        for i in someRecords:
            displayNames.append((i.someField, i.someOtherField + ' ' + i.someOtherField2))
            #I am basically making a list of tuples, containing a field and a concatnation of two other fields. The latter will be what is displayed in the select box

        self.fields['theSelectField'] = forms.ChoiceField(choices = displayNames)

        class Meta:
            #I defined model, fields and labels here

views.py

def myFormPage(request):
    someUser = request.user.someextensionofuser.someUser
    form = forms.myForm(someUser)
    context = {'form': form}
    if request.method == 'POST':
        form = forms.myForm(someUser, data = request.POST)
        if form.is_valid():
            #Do Stuff if form is valid. However,this stuff doesn't get done, the page refreshes instead

So I've managed to make the select options dynamic. However, now I can't submit data.

EDIT: One of the comments helped me solve the previously stated problem. I've updated the views.py code. However, now I'm running into this error;

Cannot assign "'someString'": "someModel.someField" must be a "someForeignModel" instance

The option values seem to be strings instead of references to objects. How do I solve this?

2

There are 2 best solutions below

0
On

I firgured it out. Since my main problem was with how the options are displayed to a user, I decided to go with changing my str method in models.py to;

class someModel(models.Model):
    #my fields

    def __str__(self):
        return self.someField + ' ' + self.someOtherField

Then in my forms.py, I went with @dmoe's answer;

self.fields['theSelectField'] = forms.ModelChoiceField(queryset = models.SomeModel.objects.filter(someUser = someUser))

So now both problems are solved. My options have custom labels, and I can submit my data without running into valueError.

1
On

This limits the possible options of your select field:

self.fields['theSelectField'].queryset = SomeModel.objects.filter(someUser = someUser)

In your views you might want to use a Class Based View, because it handles a lot of stuff automatically and saves you time. Take a look here: https://ccbv.co.uk/