Вероятная проблема заключается в том, что список значений, представленных в текстовой области, не может быть нормализован в список моделей.
См. Документацию ModelMultipleChoiceField .
Поле ожидает список допустимых идентификаторов, но, вероятно, получает список текстовых значений, которые django не может преобразоватьк фактическим экземплярам модели.to_python
не будет работать в поле формы, а не в самой форме.Поэтому значения никогда не достигают формы.
Что-то не так с использованием встроенного ModelMultipleChoiceField?Это обеспечит самый простой подход, но потребует от ваших пользователей сканирования списка доступных актеров (я использую поле актеров в качестве примера здесь).
Прежде чем я покажу пример того, как я буду пытатьсяделать то, что вы хотите, я должен спросить;как вы хотите обрабатывать введенных актеров, которых еще нет в вашей базе данных?Вы можете создать их, если они существуют, или вы можете потерпеть неудачу.Вам нужно принять решение по этому вопросу.
# 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
Выше приведен весь непроверенный код, но что-то подходящее к этому должно работать, если вы действительно хотите использовать Textarea для ModelMultipleChoiceField.Если вы пойдете по этому пути и обнаружите ошибки в моем коде выше, пожалуйста, измените мой ответ или предоставьте комментарий, чтобы я мог.Удачи.
Редактировать:
Другой вариант - создать поле, которое понимает список значений через запятую, но ведет себя аналогично ModelMultipleChoiceField.Глядя на исходный код для ModelMultipleChoiceField, он унаследован от ModelChoiceField, который позволяет определить, какое значение модели используется для нормализации.
## removed code because it's no longer relevant. See Last Edit ##
Редактировать:
Ух, я действительно должен был проверить трек django, чтобы убедиться, что это уже исправлено.Это.См. следующий билет для информации.По сути, они сделали то же самое, что и я.Они заставили ModelMutipleChoiceField соблюдать аргумент to_field_name
. Это применимо только для django 1.3!
Проблема в том, что обычный ModelMultipleChoiceField увидит строку, разделенную запятыми, и завершится ошибкой, поскольку не является списком или кортежем.Итак, наша работа становится немного сложнее, потому что мы должны изменить строку на список или кортеж, прежде чем обычный метод clean сможет работать.
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)
Итак, теперь ваша форма должна выглядеть так:
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