【问题标题】:Django forms extra empty radio buttonDjango 形成额外的空单选按钮
【发布时间】:2015-08-04 13:49:57
【问题描述】:

在渲染模型表单时,会生成一个额外的单选按钮,但我不知道它来自哪里:

>>> f = DocumentForm()
>>> print f['document_type']
<ul id="id_document_type">
<li><label for="id_document_type_0"><input checked="checked" id="id_document_type_0" name="document_type" type="radio" value="" /> ---------</label></li>
<li><label for="id_document_type_1"><input id="id_document_type_1" name="document_type" type="radio" value="1" /> Campus LAN</label></li>
<li><label for="id_document_type_2"><input id="id_document_type_2" name="document_type" type="radio" value="2" /> WAN</label></li>
<li><label for="id_document_type_3"><input id="id_document_type_3" name="document_type" type="radio" value="3" /> UC</label></li>
</ul>

第一个带有value="" 和文本为--------- 的单选按钮,我已经搜索了我的代码,但无法确定它的来源?

models.py

class DocumentType(models.Model):
    name = models.CharField("Document Type", max_length=240)

class Document(models.Model):
    document_type = models.ForeignKey(DocumentType,
                                      verbose_name="Document Type")

>>> DocumentType.objects.all()
[<DocumentType: Campus LAN>, <DocumentType: WAN>, <DocumentType: UC>]
>>> d = Document.objects.all()
>>> for x in d:
...     print x.document_type
... 
Campus LAN
Campus LAN

模板:

<form role="form" action="" method="POST">{% csrf_token %}
                {{ form.as_p}}
                <input type="submit" value="Save" />
            </form>

forms.py:

class DocumentForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(DocumentForm, self).__init__(*args, **kwargs)
        self.fields['sections'].queryset = Section.objects.filter(associated_document="Original Section")
        self.fields['document_type'].queryset = DocumentType.objects.all()

    class Meta:
        model = Document
        fields = ('customer', 'title', 'document_type', 'sections',)
        widgets = {
            'sections': forms.widgets.CheckboxSelectMultiple,
            'document_type': forms.widgets.RadioSelect,
            }

views.py

def new_lld(request):
    if request.method == "POST":
        form = DocumentForm(request.POST)
        if form.is_valid():
            document = form.save(commit=False)
            document.author = request.user
            document.save()
            form.save_m2m()
            return redirect('lld:index')
    else:
        form = DocumentForm()
    return render(request, 'lld/new_lld.html', {'form': form})

admin.py

class DocumentAdmin(admin.ModelAdmin):
    fieldsets = [
        ('Document Info', {'fields':    ['author', 'customer', 'title',
                                         'slug']}),
        ('Document Type', {'fields':    ['document_type', 'sections']}),
    ]
    inlines = [VersionInline]
    prepopulated_fields = {"slug": ("customer", "title",)}
    list_display = ('title', 'customer', 'author', 'document_type',
                    'date_created', 'date_updated')
    list_filter = ['date_updated', 'author']

【问题讨论】:

  • 你能把 DocumentForm 的代码贴出来,还有你用的是什么版本的 Django?
  • 你的模板是什么样子的?
  • {% csrf_token %} {{ form.as_p}}

标签: python html django


【解决方案1】:

【讨论】:

    【解决方案2】:

    解决方法是用 css 隐藏它:

    #id_document_type li:first-child {display:none}
    

    【讨论】:

    • 啊,好简单,我喜欢! (尽管在我解决真正的问题之前它会困扰我。与此同时,CSS FTW)谢谢。
    • 您可以将您的 view.py 和 admin.py 添加到您的问题中吗?我将把它转储到我的演示应用程序中,看看我能找到什么。看起来它像下拉菜单一样输出。你用的是 django 1.8 吗?
    • 已添加,是的 1.8。塔。
    【解决方案3】:

    正如奥古斯汀所说,ModelChoiceFields must be set to required in order to remove the blank choice

    def __init__(self, queryset, empty_label="---------",
                 required=True, widget=None, label=None, initial=None,
                 help_text='', to_field_name=None, limit_choices_to=None,
                 *args, **kwargs):
        if required and (initial is not None):
            self.empty_label = None
        else:
            self.empty_label = empty_label
    

    Required 默认设置为 False,因此您需要将以下内容添加到 Document Form 中的 init

    self.fields['document_type'].required=True
    

    【讨论】:

      【解决方案4】:

      Django 必须有一种方法允许为可空字段(带有required=False 的字段)设置 None 值,并通过附加一个带有空值的选项来实现。 Select 元素也会发生同样的事情。

      现在,要让 Django 将该选项添加到您的表单,document_type 字段必须可以为空(确实有 required=False),我只能假设您在表单定义中的某个地方将该选项设置为领域。

      PS:如果表单是为模型自动生成的(即您使用的是 Django 的 ModelForm),那么模型应该说 Field set with blank=True, null=True,但这显然是缺失的。不过,ModelForm 很不错,所以如果您不熟悉它,请尝试一下。

      更新:

      TBH 我也不知道为什么它可以为空,但请尝试以@Alistair 指定的相同方式在表单中手动设置required=True

      self.fields['document_type'].required = True
      

      就在您修改该字段以设置查询集的行下方。我认为这应该可行。

      【讨论】:

      • 谢谢,这听起来很合理,我找不到我设置的任何地方 required=False 但我会尝试编辑我的模型以反映你的建议。
      • 好吧,老实说,我也不知道它的来源。据我所知,没有blank=True, null=TrueForeignKey 将设置required=False。嗯...查看我的更新答案。
      • 设置这个没有帮助,除非我需要更新我的数据库,我不应该这样做吗?
      • 不,通过修改你不应该的表单......奇怪,我希望 required=True 工作。对不起,我必须说我尝试了很多方法,设置 required、extra_label、default 等等,但我似乎无法删除那个该死的空选项!恐怕我不能再帮助你了,但我希望我的意见能对你有所帮助。
      • 哦,伙计,是的,您帮了大忙,谢谢。如果我确实设法解决了这个问题,我一定会发布答案。令人沮丧!
      【解决方案5】:

      我通过将这些参数添加到我在模型中的字段声明中解决了这个问题:

      blank=False, default=None

      所以在这种情况下,您的模型将如下所示:

          document_type = models.ForeignKey(DocumentType,
                             verbose_name="Document Type", blank=False, default=None)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-07-30
        • 2013-07-18
        • 1970-01-01
        • 1970-01-01
        • 2017-12-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多