Skip to main content
 首页 » 编程设计

python之如何从 Django 中的 ModelForm 手动创建选择字段

2025年05月04日36qq号

我有一个 ModelForm其中一个字段(名为 creator )是一个 ForeignKey , 所以对于 {{ form.creator }} Django 呈现 <select>像这样的标签:

<select id="id_approver" name="approver"> 
    <option selected="selected" value="">---------</option> 
    <option value="1">hobbes3</option> 
    <option value="2">tareqmd</option> 
    <option value="3">bob</option> 
    <option value="4">sam</option> 
    <option value="5">jane</option> 
</select> 

但是我想加一个onchange事件属性,以便我稍后可以使用 AJAX 来做其他事情。我也想改---------说点别的并显示批准人的全名,而不是他们的用户名。

那么是否可以获得可能的批准者列表并生成我自己的选择选项?有点像

<select id="id_approver" name="approver" onchange="some_ajax_function()"> 
    <option select="selected" value="0">Choose a user</option> 
{% for approver in form.approver.all %} <!-- This won't work --> 
    <option value="{{ approver.pk }}">{{ approver.get_full_name }}</option> 
{% endfor %} 
</select> 

而且我还认为大多数批准者列表都变得太大(比如超过 50 个),那么我最终会想要某种可搜索的批准者自动完成字段。那么我肯定需要编写自己的 HTML。

如果有人需要,我的ModelForm看起来像这样:

class OrderCreateForm( ModelForm ) : 
    class Meta : 
        model = Order 
        fields = ( 
            'creator', 
            'approver', 
            'work_type', 
            'comment', 
        ) 

请您参考如下方法:

ModelChoiceField documentation解释了如何做到这一点。

要更改空标签:

empty_label 
 
    By default the <select> widget used by ModelChoiceField 
    will have an empty choice at the top of the list. You can change the text 
    of this label (which is "---------" by default) with the empty_label 
    attribute, or you can disable the empty label entirely by setting 
    empty_label to None: 
 
    # A custom empty label 
    field1 = forms.ModelChoiceField(queryset=..., empty_label="(Nothing)") 
 
    # No empty label 
    field2 = forms.ModelChoiceField(queryset=..., empty_label=None) 

至于你的第二个查询,在文档中也有解释:

The __unicode__ method of the model will be called to generate string 
representations of the objects for use in the field's choices; 
to provide customized representations, subclass ModelChoiceField and override 
label_from_instance. This method will receive a model object, and should return 
a string suitable for representing it. For example: 
 
class MyModelChoiceField(ModelChoiceField): 
    def label_from_instance(self, obj): 
        return "My Object #%i" % obj.id 

最后,要传递一些自定义 ajax,请使用 attrs选择小部件的参数(在 ModelForm 字段中使用)。

最后,你应该有这样的东西:

creator = MyCustomField(queryset=..., 
                        empty_label="Please select", 
                        widget=forms.Select(attrs={'onchange':'some_ajax_function()'})