首页 > 解决方案 > 为什么我的 django 表单清理数据每次都返回 None ?

问题描述

我在我的模型中使用自引用外键。在我使用它的视图中form.cleaned_data.get('parent')它返回None但是当我使用它时request.POST.get('parent')它返回值。为什么cleaned_data这里不工作?

楷模

class Category(models.Model):
    parent = models.ForeignKey('self', blank=True, null=True, on_delete=models.SET_NULL)
    slug = models.SlugField(unique=True, max_length=50)
    title = models.CharField(max_length=255, unique=True)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

形式

class CreateCategoryForm(forms.ModelForm):
    class Meta:
        model = Category
        fields = ['title', 'slug']

意见

def create_category(request):
    form = CreateCategoryForm()
    categories = Category.objects.order_by('-created')
    if request.method == 'POST':
        form = CreateCategoryForm(request.POST)
        if form.is_valid():
            # parent = request.POST.get('parent') # works
            # parent = form.cleaned_data.get('parent') # returns None
            category = form.save(commit=False)
            category.parent = form.cleaned_data.get('parent')
            category.save()
            messages.success(request, 'Created Successfully.')
            return redirect('list_categories')
    return render(request, 'add_category.html', {'form':form, 'categories':categories})

模板

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

            <div class="form-group">
              <label>Category Name</label>
              <input type="text" name="title" class="form-control"
              value="{{form.title.value|default_if_none:''}}"/>
                {% if form.title.errors %}
                 <span class="error">{{form.title.errors|striptags}}</span>
                {% endif %}
            </div>
            <div class="form-group">
            <label for="select" class="">Category Parent</label>
                <select name="parent" id="exampleSelect"
              class="form-control">
                 <option selected>Select</option>
                {% for category in categories %}
              <option value="{{category.pk}}">{{category.title}}</option>
                {% endfor %}
            </select>
            </div>

标签: djangodjango-formsdjango-views

解决方案


因此,您的第一个问题是您没有在模型表单中包含该字段,因此请修复:

class CreateCategoryForm(forms.ModelForm):
    class Meta:
        model = Category
        fields = ['title', 'slug', 'parent']

其次是您自己在模板中渲染表单字段,因此不使用 Django 的属性处理。要解决这个问题:

            <div class="form-group">
                <label for="{{form.parent.id_for_label}}">Category Parent</label>
                {{form.parent}}
            </div>

现在 select 将没有正确的 html 类,但我们可以将它传递给表单字段。完整的解决方案:

class CreateCategoryForm(forms.ModelForm):
    # ModelForm will take care of setting required to False
    parent = forms.ModelChoiceField(queryset=Category.objects.order_by('-created'), attrs={'class': 'form-control'})
    class Meta:
        model = Category
        fields = ['title', 'slug', 'parent']

# view
def create_category(request):
    form = CreateCategoryForm()
    if request.method == 'POST':
        form = CreateCategoryForm(request.POST)
        if form.is_valid():
            category = form.save(commit=False)
            category.parent = form.cleaned_data.get('parent')
            category.save()
            messages.success(request, 'Created Successfully.')
            return redirect('list_categories')
    return render(request, 'add_category.html', {'form':form})

推荐阅读