Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The probable problem is that the list of values provided in the text area can not be normalized into a list of Models. </p> <p>See the <a href="http://docs.djangoproject.com/en/dev/ref/forms/fields/#modelmultiplechoicefield" rel="noreferrer">ModelMultipleChoiceField documentation</a>.</p> <p>The field is expecting a list of valid IDs, but is probably receiving a list of text values, which django has no way of converting to the actual model instances. The <code>to_python</code> will be failing within the form field, not within the form itself. Therefore, the values never even reach the form.</p> <p>Is there something wrong with using the built in ModelMultipleChoiceField? It will provide the easiest approach, but will require your users to scan a list of available actors (I'm using the actors field as the example here).</p> <p>Before I show an example of how I'd attempt to do what you want, I must ask; how do you want to handle actors that have been entered that don't yet exist in your database? You can either create them if they exist, or you can fail. You need to make a decision on this.</p> <pre><code># only showing the actor example, you can use something like this for other fields too class MovieModelForm(forms.ModelForm): actors_list = fields.CharField(required=False, widget=forms.Textarea()) class Meta: model = MovieModel exclude = ('actors',) def clean_actors_list(self): data = self.cleaned_data actors_list = data.get('actors_list', None) if actors_list is not None: for actor_name in actors_list.split(','): try: actor = Actor.objects.get(actor=actor_name) except Actor.DoesNotExist: if FAIL_ON_NOT_EXIST: # decide if you want this behaviour or to create it raise forms.ValidationError('Actor %s does not exist' % actor_name) else: # create it if it doesnt exist Actor(actor=actor_name).save() return actors_list def save(self, commit=True): mminstance = super(MovieModelForm, self).save(commit=commit) actors_list = self.cleaned_data.get('actors_list', None) if actors_list is not None: for actor_name in actors_list.split(","): actor = Actor.objects.get(actor=actor_name) mminstance.actors.add(actor) mminstance.save() return mminstance </code></pre> <p>The above is all untested code, but something approaching this should work if you really want to use a Textarea for a ModelMultipleChoiceField. If you do go down this route, and you discover errors in my code above, please either edit my answer, or provide a comment so I can. Good luck.</p> <p>Edit:</p> <p>The other option is to create a field that understands a comma separated list of values, but behaves in a similar way to ModelMultipleChoiceField. Looking at the source code for ModelMultipleChoiceField, it inhertis from ModelChoiceField, which DOES allow you to define which value on the model is used to normalize.</p> <pre><code>## removed code because it's no longer relevant. See Last Edit ## </code></pre> <p><strong>Edit:</strong></p> <p>Wow, I really should have checked the django trac to see if this was already fixed. It is. See the <a href="http://code.djangoproject.com/ticket/9161" rel="noreferrer">following ticket</a> for information. Essentially, they've done the same thing I have. They've made ModelMutipleChoiceField respect the <code>to_field_name</code> argument. <strong>This is only applicable for django 1.3!</strong></p> <p>The problem is, the regular ModelMultipleChoiceField will see the comma separated string, and fail because it isn't a List or Tuple. So, our job becomes a little more difficult, because we have to change the string to a list or tuple, before the regular clean method can run.</p> <pre><code>class ModelCommaSeparatedChoiceField(ModelMultipleChoiceField): widget = Textarea def clean(self, value): if value is not None: value = [item.strip() for item in value.split(",")] # remove padding return super(ModelCommaSeparatedChoiceField, self).clean(value) </code></pre> <p>So, now your form should look like this:</p> <pre><code>class MovieModelForm(forms.ModelForm): actors = ModelCommaSeparatedChoiceField( required=False, queryset=Actor.objects.filter(), to_field_name='actor') equipments = ModelCommaSeparatedChoiceField( required=False, queryset=Equipment.objects.filter(), to_field_name='equip') lights = ModelCommaSeparatedChoiceField( required=False, queryset=Light.objects.filter(), to_field_name='light') class Meta: model = MovieModel </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload