python-3.x Flask-Admin:如何根据另一个字段的选择动态预填充表单字段?

3vpjnl9f  于 2023-08-08  发布在  Python
关注(0)|答案(1)|浏览(103)

在flask admin中,我有一个内联模型,它有一个名为'Type'的Select 2字段和一个名为'URL'的文本输入字段。
x1c 0d1x的数据
当用户在“类型”字段中选择一个值时,我希望“URL”字段的值能够使用预定义和Map的值动态更新。
举例来说:如果选择的“类型”是“Wikidata”,我想在“URL”字段中预先填充“https://www.wikidata.org/wiki/”,或者如果选择的“类型”是“DataBnf”,则在“URL”字段中预先填充“https:data.bnf.fr/fr/”等。
我尝试使用jQuery拦截选择事件(select 2),但似乎不起作用。我想知道在Flask-Admin中是否有更简单的方法来根据下拉列表选择预填充字段。
提前感谢您的建议
[Edit 1]
这是我的模型视图:
views.py(简化版):

class PersonView(ModelView):
    can_export = True
    can_view_details = False
    column_display_pk = True
    create_template = 'admin/edit.html'
    edit_template = 'admin/edit.html'
    #...    
    #... some formaters functions for specific fields ...
    extra_js = ['//cdn.ckeditor.com/4.6.0/basic/ckeditor.js']
    #...
    inline_models = [
        (
            # This inline model I try to customize
            PersonHasKbLinks,
            dict(
                form_columns=["id", "type_kb", "url"],
                column_labels={"type_kb": "Type", "url": "URL"},
            )
        ),
        # ... others inline models
    ]
    # ...
    form_choices = {
        'type_kb': format_enum(KnowledgeBaseLabels),
        'relation_type': format_enum(FamilyRelationshipLabels)
    }
    #...

字符串
edit.html

{% extends 'admin/model/edit.html' %}

{% block tail_js %}
   {{ super() }}
   <script type="text/javascript" src="{{ url_for('static', filename='js/_prefill_kb_url.js') }}"></script>
{% endblock %}


master.html

{% extends admin_base_template %}

{% block head %}
   {{ super() }}
   <!-- add jquery -->
   <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min.js" integrity="sha512-3gJwYpMe3QewGELv8k/BX9vcqhryRdzRMxVfq6ngyWXwo03GFEzjsUm8Q7RZcHPHksttq7/GFoxjCVUjkjvPdw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
   <!-- add select2 dependencies -->
   <link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
{% endblock %}


_prefill_kb_url.js(目前我只是试图捕捉select 2列表上的事件(更改或选择),但我失败了,我不确定这是否是在flask admin中完成我想做的事情的最佳策略):

// I try this (no output) : 
$(document).ready(function() {
    $('#s2id_kb_links-0-type_kb').on('change', function() {
        console.log('select change');
    });
});

// and I try this (no output also) : 

$(document).ready(function() {
    $('body').on('select2:select', '#s2id_kb_links-0-type_kb', function (e) {
        console.log('select change');
        }
    });
});


我注意到在我的浏览器中,创建了一个select元素(id="kb_links-0-type_kb"),但它默认为CSS属性display:none,好像flask-admin overide select 2(也许我错了...?)


9bfwbjaz

9bfwbjaz1#

经过一番研究,我终于找到了解决办法:
首先,在views.py中,我创建了一个自定义的SelectField

class Select2DynamicField(SelectField):
    def __init__(self, label=None, validators=None, coerce=int, choices=None, **kwargs):
        super(Select2DynamicField, self).__init__(label, validators, coerce, choices, **kwargs)
        choices = [(label, label) for i, label in enumerate(_get_enum_values(KnowledgeBaseLabels))]
        coerce = str
        kwargs['widget'] = Select2Widget() 
        kwargs['render_kw'] = {'onchange': 'fetchCorrectUrlStringFromKbSelect(this)'} # link a JQuery function here 

        return super(Select2DynamicField, self).__init__(label, validators, coerce, choices, **kwargs)

字符串
总是在views.py中,在我的模型PersonView中,我将新的自定义SelectField链接到inline_models中的字段:

class PersonView(ModelView):
      edit_template = 'admin/edit.html'
      create_template = 'admin/edit.html'
      ...
      inline_models = [
        (PersonHasKbLinks, {
            'form_columns': ['type_kb', 'url'],
            'column_labels': {'type_kb': 'Base de connaissance', 'url': 'URL'},
            'form_overrides': dict(type_kb=Select2DynamicField),
            'form_args': dict(url=dict(default='www.wikidata.org/entity/<ID>')) # here I set a default value for url,

        }), ...
]
...


然后我在JS脚本person.form.fields.js中编写了一个特定的函数,当用户在type_kb字段中选择一个值时,动态替换url字段中的正确值:

// Collections of KB URLs
const KB_URL_MAP = {
        "Wikidata": "www.wikidata.org/entity/<ID>",
        "Biblissima": "data.biblissima.fr/w/Item:<ID>",
        "VIAF": "www.viaf.org/viaf/<ID>/",
        "DataBnF": "data.bnf.fr/fr/<ID>/",
        "Studium Parisiense": "studium-parisiense.univ-paris1.fr/individus/<ID>",
        "Collecta": "www.collecta.fr/p/COL-IMG-<ID>",
};

/**
 * Function to fetch the correct URL string from a Select2 input based on the selected option.
 * @param {Event} event - The event object triggered by the Select2 input.
 */
function fetchCorrectUrlStringFromKbSelect(event) {
    // get id of the select2 input
    let UserKbSelected = event.id;
    // Extract the number from the ID
    let number = UserKbSelected.split('-')[1];
    // Get the value of the selected option
    let KbType = $(event).select2('val');
    // Format the string to get the correct input ID
    let formattedString = `#kb_links-${number}-url`;
    // Set the value of the input with the correct URL
    $(formattedString).val(KB_URL_MAP[KbType]);
}


最后,我将我的js脚本附加到edit.html模板:

{% extends 'admin/model/edit.html' %}

{% block tail_js %}
    {{ super() }}
    <script type="text/javascript" src="{{ url_for('static', filename='js/person.form.fields.js') }}"></script>
{% endblock %}


下面是表单中的结果:


的数据
注意:我使用Flask-Admin==1.6.1

相关问题