Django post-форма не может быть проверена при использовании формы с дополнительными входными данными

#django #django-forms

Вопрос:

У меня есть форма, содержащая автофокус MultipleChoiceField , где выбор создается динамично на основе данного пользователя

 class UpdateForm(forms.Form):
    def __init__(self,names,*args,**kwargs):
        super(UpdateForm,self).__init__(*args,**kwargs)
        self.fields["list_names"] = forms.MultipleChoiceField(choices = zip(names,names),widget=forms.CheckboxSelectMultiple,label="Pick some names")

    add_new = forms.BooleanField(initial=True, label="Add new names?",required=False)
    delete_missing = forms.BooleanField(label = "Delete names?",required=False)
 

и это прекрасно работает как GET-запрос, проблемы возникают вместе с post-запросом:

Мое мнение заключается в следующем:

 def update(request):
    user = request.user
    list_names = MyModel.objects.filter(user=user).all().values_list("nick_name",flat=True).distinct()
    form = UpdateWishlistForm(names =list_names)

    if request.method == "POST":
        post_form = UpdateForm(request.POST)    
        if post_form.is_valid():
            list_names = post_form.cleaned_data["list_names"] 
            add_new = post_form.cleaned_data["add_new"]
            delete_missing = post_form.cleaned_data["delete_missing"]

            messages.success(request, "Success")
            context = {
                "form":form,
            }

            redirect("home")
        else:
            #invalid post_form
            messages.error(request, "Error")
            context = {
                "form":form,
            }
            return render(request, "discounttracker/update.html")        
    else: #Get request
        context = {
            "form":form,
        }
        
    return render(request, "myapp/update.html",context=context)

 

Значение post_form = UpdateForm(request.POST) не проверяется, и post_form.errors оно пустое.

Однако он содержит данные (перед вызовом post_form.is_valid() ).

 print(post_form)
# UpdateForm: <UpdateForm bound=False, valid=Unknown, fields=(add_new;delete_missing;list_names)>

print(request.POST.dict())
#<QueryDict: {'csrfmiddlewaretoken': ['...'], 'add_new': ['on'], 'list_names': ['test_name_1']}>
 

но я замечаю, что он не связан, следовательно, не имеет силы. Но я не могу понять, почему это не «привязка» при разборе request.POST ?

Ответ №1:

В запросе на публикацию вам также нужно указать имена, поэтому:

 list_names = MyModel.objects.filter(user=user).values_list("nick_name",flat=True).distinct()
form = UpdateWishlistForm(names=list_names)
if request.method == 'POST':
    post_form = UpdateForm(names=list_names, data=request.POST)
    # …
# … 

Но я бы посоветовал работать с ModelMultipleChoiceField [Django-doc] и, таким образом, передавать набор запросов. Поскольку имена ников, по-видимому, могут содержать дубликаты, возможно, было бы лучше создать Nickname модель и использовать ForeignKey s для этой модели.

Комментарии:

1. Я тоже пробовал это, но это бросает __init__() got multiple values for argument 'names'

2. @CutePoison: вы, вероятно, использовали UpdateForm(request.POST, names=list_names) . Поскольку names это первый параметр конструктора формы, это означает, что request.POST он рассматривается как значение names параметра, а также второго, и это приводит к ошибке, поскольку для одного и того же параметра существует два значения.

3. Да, я только что понял, что, написав это так, как ты, сделал разницу — в чем разница между этими двумя?

4. @CutePoison: см. редактирование комментария. Возможно , это было тесто для работы def __init__(*args, names=None, **kwargs) , а затем для создания этого UpdateForm(request.POST, names=list_names) .

5. @CutePoison В UpdateForm(request.POST, names=list_names) request.POST является позиционным аргументом, и, поскольку в вашем определении сигнатура метода имеет names первое значение, это значение для этого и сразу после того, как у вас есть ключевое слово arg для names .