【问题标题】:Django ModelForm foreign key filteringDjango ModelForm 外键过滤
【发布时间】:2018-01-06 09:50:22
【问题描述】:

我正在尝试过滤模型表单中的外键字段选择,但表单无法正常工作。我的脚本:

forms.py

from django import forms
from .models import Album, Song

class SongCreateForm(forms.ModelForm):

    class Meta:
        model = Song
        fields = [
            'album',
            'name',
            'is_favorite'
        ]
        widgets = {
            'album': forms.Select(attrs={'class': 'form-control'}),
            'name': forms.TextInput(attrs={'class': 'form-control'}),
            'is_favorite': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
        }

    def __init__(self, user, *args, **kwargs):
        super(SongCreateForm, self).__init__(*args, **kwargs)
        self.fields['album'].queryset = Album.objects.filter(owner=user)

views.py

from django.views.generic import CreateView

class SongCreateView(CreateView):
    template_name = 'music/song_create.html'
    success_url = '/songs/'

    def get_form(self, form_class=None):
        form_class = SongCreateForm(user=self.request.user)
        return form_class
        print(form_class.errors.as_data())
        print(form_class.is_valid())

song_create.html

{% extends 'base.html' %}

{% block content %}
<form method="post">{% csrf_token %}
  {% if form.errors %}
    <p>{{ form.errors }}</p>
  {% endif %}
  <div class="form-group">
    <label for="{{ form.album.id_for_label }}">Album</label>
    {{ form.album }}
  </div>
  <div class="form-group">
    <label for="{{ form.name.id_for_label }}">Name</label>
    {{ form.name }}
  </div>
  <div class="form-check">
    <label for="{{ form.is_favorite.id_for_label }}" class="form-check-label">
    {{ form.is_favorite }}Favorite
    </label>
  </div>
  <button type="submit" class="btn btn-primary" value="Save">Add</button>
</form>
{% endblock %}

过滤“专辑”字段的查询集工作正常。它仅显示与经过身份验证的用户关联的专辑,但是当我在表单浏览器中单击提交时,不会将我重定向到成功 url,并且歌曲不会添加到数据库中。我在 views.py 的末尾添加了两个打印语句来检查表单是否有效并且有任何错误。虽然 form.errors 返回 空字典,但 form.is_valid() 等于 False。如果没有任何错误,为什么 Django 将此表单视为无效?

注意: SongCreateView 工作成功,当我注释掉forms.py 中的init 函数和views.py 中的get_form 函数时。 p>

【问题讨论】:

    标签: python django django-forms


    【解决方案1】:

    首先,删除return 语句之后的那些print 语句,因为在方法返回值后它们将永远不会被执行。其次,将form_class 属性添加到您的视图类中,如下所示:

    class SongCreateView(CreateView):
        template_name = 'music/song_create.html'
        success_url = '/songs/'
        form_class = SongCreateForm
    

    然后在get_form方法中:

    def get_form(self, form_class=None):
        if form_class is None:
            form_class = self.get_form_class()
        return form_class(user=self.request.user, **self.get_form_kwargs())
    

    然后重写form_valid 方法以将登录用户与Song 实例相关联,如下所示:

    def form_valid(self, form):
        self.object = form.save(commit=False)
        self.object.user = self.request.user
        self.object.save()
        return redirect(self.get_success_url())
    

    从顶部的django.shortcuts 导入redirect。希望对您有所帮助!

    【讨论】:

      【解决方案2】:

      我的猜测是 Song 的 ID 丢失了。当你使用神奇的代码时

      {{ form }}
      

      这个字段是自动添加的,虽然输入是隐藏的。当您像您一样手动定义所有字段时,您必须确保添加了 ID,即您需要添加

      {{ form.pk }}
      

      或者你歌曲的 id 的名称(这里是 pk)。

      【讨论】:

      • 我听不懂。你说我应该在模板中写 {{ form.pk }} 而不是 {{ form.album }}?
      • 不是。您需要将主键字段添加到已有的内容中。我只是在这里使用 pk 作为变量名,因为我看不到你的模型所以我不知道你叫它什么。
      猜你喜欢
      • 2013-09-05
      • 1970-01-01
      • 2020-09-07
      • 2012-01-23
      • 1970-01-01
      • 2015-09-24
      • 1970-01-01
      • 2018-01-05
      • 2016-07-12
      相关资源
      最近更新 更多