2015-01-29 2 views
0

У меня есть форма с некоторыми Флажки и какой-то текст, когда пользователь представить данные, которые я с помощью следующей формы объекта:Не удалось получить пост данные в multipleChoiceField с Джанго

class PostForm(forms.Form): 
    product = forms.MultipleChoiceField(
     label='product', 
     widget=forms.CheckboxSelectMultiple) 
    text = forms.CharField(label='text', max_length=1000) 

    def __init__(self, choices, *args, **kwargs): 
     super(PostForm, self).__init__(*args, **kwargs) 
     self.fields['product'].choices = choices 

Но когда я отладки кода , пост cleaned_data совершенно пуст, и data объект содержит все данные:

<QueryDict: {'text': ['Hello world, this is a test\r\n'], 'product': ['7', '9'], 'csrfmiddlewaretoken': ['QYuwBoW3O5D42oScF2GzYuesTBIZZqRa']}> 

Update:

Здесь шаблон:

<h1>Create post</h1> 

<textarea rows="10" cols="50" name="text" form="post_form"> 
Hello world, this is a test 
</textarea> 

<form action="" method="post" id="post_form"> 
    {% csrf_token %} 

    <label for="product_id" id="product_id">products: </label> 
    {% for product in products %} 
     <input type="checkbox" name="product" value="{{product.id}}">{{product.name}} 
    {% endfor %} 
    </select> 
    <br> 
    <input type="submit" value="OK"> 
</form> 

А вот вид:

class PostView(AuthenticatedUserView): 
    template_name = 'trendby/post.html' 

    def get_if_authenticated(self, request, user): 
     products = models.Product.objects.filter(user=user) 
     return render(request, self.template_name, {'products': products}) 

    def post_if_authenticated(self, request, user): 
     products = models.Product.objects.filter(user=user) 
     choices = [] 
     for product in products: 
      choices += [str(product.id)] 

     form = PostForm(choices, request.POST) 
     if form.is_valid(): 
      text = form.cleaned_data['text'] 
      post = models.Post(text=text, user=user) 
      post.save() 
      return HttpResponse("Post: " + text) 

     return render(request, self.template_name) 

Может кто-нибудь сказать мне, что я могу сделать, чтобы исправить `cleaned_data '?

Спасибо!

+1

Что на ваш взгляд выглядит? –

+0

Я только что обновил сообщение –

ответ

0

Я заканчиваю с этим кодом работы:

class PostForm(ModelForm): 
    class Meta: 
     model = models.Post 
     fields = ['text', 'products', 'image'] 
     widgets = { 
      'text': Textarea(attrs={'cols': 80, 'rows': 10}), 
      'products': SelectMultiple(), 
     } 

class PostView(AuthenticatedUserView): 
    template_name = 'myapp/post.html' 

    def get_if_authenticated(self, request, user): 
     form = PostForm() 
     return render(request, self.template_name, {"form": form}) 

    def post_if_authenticated(self, request, user): 
     form = PostForm(request.POST, request.FILES) 
     if form.is_valid(): 
      post = form.save(commit=False) 
      post.user = user 
      post.save() 
      return HttpResponseRedirect(reverse('myapp:actions')) 
     return render(request, self.template_name, {"form": form}) 

И шаблон:

{% if form.errors %}<p><strong>{{ form.errors }}</strong></p>{% endif %} 

<form method="post" enctype="multipart/form-data" action=""> 
    {% csrf_token %} 
    {% for field in form %} 
     {{ field.label_tag }} {{ field }} <br> 
    {% endfor %} 
    <input type="submit" value="OK"> 
</form> 
0

Эта форма никогда не будет успешно проверяться, так как выбор должен быть списком пар (id, name). Вы отправляете простой список идентификаторов. Поскольку вы не показываете ошибки формы в шаблоне, вы скрываете причину, по которой форма не сохраняется.

Однако ваш подход ошибочен несколькими способами. На самом деле вы должны использовать ModelMultipleChoiceField с настраиваемым набором запросов, а не напрямую устанавливать выбор. И вы должны отправить недопустимую форму в шаблон и использовать ее для отображения полей и ошибок.

class PostForm(forms.Form): 
    product = forms.ModelMultipleChoiceField(
    label='product', 
    queryset=Post.objects.none()) 
    text = forms.CharField(label='text', max_length=1000) 

    def __init__(self, *args, **kwargs): 
    user = kwargs.pop('user') 
    super(PostForm, self).__init__(*args, **kwargs) 
    self.fields['product'].queryset = Post.objects.filter(user=user) 


class PostView(AuthenticatedUserView): 
    template_name = 'trendby/post.html' 

    def get_if_authenticated(self, request, user): 
    form = PostForm(user=user) 
    return render(request, self.template_name, {'form': form}) 

    def post_if_authenticated(self, request, user): 
    form = PostForm(request.POST, user=user) 
    if form.is_valid(): 
     text = form.cleaned_data['text'] 
     post = models.Post(text=text, user=user) 
     post.save() 
     return HttpResponse("Post: " + text) 

    return render(request, self.template_name, {'form': form}) 


<form action="" method="post" id="post_form"> 
    {% csrf_token %} 
    {{ form.products.label_tag }} 
    {{ form.products }} 
    {{ form.products.errors }} 
    <input type='submit'> 
</form> 

Этот код намного короче, более идиоматичен и обеспечивает обратную связь валидации с пользователем.

Чтобы сделать его еще короче, вы должны изучить различные виды на основе редактирования, которые удаляют множество шаблонов обработки формы.

0

После Джанго документации во время учебы я взял ваш совет, и я обновил форму, теперь код чист:

Модель:

class Post(models.Model): 
    text = models.CharField(max_length=1000) 
    user = models.ForeignKey(User) 
    products = models.ManyToManyField(Product) 

От:

class PostForm(ModelForm): 
    class Meta: 
     model = models.Post 
     fields = ['text', 'products'] 
     widgets = { 
      'text': Textarea(attrs={'cols': 80, 'rows': 10}), 
     } 

И вот вид:

class PostView(AuthenticatedUserView): 
    template_name = 'trendby/post.html' 

    def get_if_authenticated(self, request, user): 
     PostSetForm = modelformset_factory(
      models.Post, 
      form=PostForm) 

     formset = PostSetForm(queryset=models.Post.objects.none()) 
     return render(request, self.template_name, { 
      "form": formset[0], 
     }) 

    def post_if_authenticated(self, request, user): 
     PostFormSet = modelformset_factory(
      models.Post, 
      form=PostForm) 
     formset = PostFormSet(request.POST) 
     if formset.is_valid(): 
      post = formset.save(commit=False)[0] 
      post.user = user 
      post.save() 
      return HttpResponseRedirect(reverse('trendby:actions')) 
     return render(request, self.template_name) 

Наконец, шаблон меняется:

<form method="post" action=""> 
    {% csrf_token %} 
    {% for field in form %} 
     {{ field.label_tag }} {{ field }}<br> 
    {% endfor %} 
    <input type="submit" value="OK"> 
</form> 

Теперь Джанго создает палитру продукции, но когда я отправить форму, я получаю следующее сообщение об ошибке:

Exception Type: ValidationError 
Exception Value:  
['ManagementForm data is missing or has been tampered with'] 

И почтовые данные содержат только один идентификатор для продукта, и оно должно содержать более одного:

form-0-id 
'' 
csrfmiddlewaretoken 
'FIWwI9VW48lOjZLd7yT6vqtpK2IZaJ1K' 
form-0-products 
'2' 
form-0-text 
'' 

Как я могу сделать это, чтобы отправить все продукты и исправить ValidationError?

Смежные вопросы