добавить кнопки, которые заполняют другие поля во встроенных шаблонах Flask-Admin - PullRequest
0 голосов
/ 03 июня 2018

Я хотел бы добавить кнопку в мое представление создания Flask-Admin, и после этого вопроса мне удалось это сделать.

Теперь, предположив, что модель, переданная в это представление, скажем, User имеет:

  • A отношение один ко многим с ClassA и ClassB
  • ClassA также имеет отношение один ко многим с ClassB

И предполагая, что в моем представлении создания я добавил некоторый экземплярClassA при создании экземпляра User, скажем my_class_a_instance, мне бы хотелось, чтобы эта кнопка:

  • выполняет запрос к my_class_a_instance, возвращая все экземпляры ClassB (илиmy_class_b_instance s) связанный с ним в этот момент
  • заполняет поле form.class_b в шаблоне создания с этими результатами
  • , если возможно, появляется какое-то модальное окно, запрашивающее у пользователя подтверждение.Возможно с @action

Пока мой подход выглядит так:

# templates/admin/cascade_button_create.html

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

{% block body %}

{% call lib.form_tag(form) %}
<div class="row">
  <div class="col-xg-10">
    {{ lib.render_form_fields([form.name])}}
  </div>
</div>

<div class="row">
    <div class="col-xg-10">
        <!-- form.cities follows the attributes of sqla model -->
      {{ lib.render_form_fields([form.instances_of_a])}}
    </div>
    <div class="col-xg-2">
        <!-- so this button should query any model related to form.cities 
        and populate the create form with whatever comes out.

        Say Street has a one to many relationship, I want this 
        button to run some method of the form get_instances_of_b_from_instance_of_a(form.instances_of_a) (query_method() for short) that fills
        the field form.instances_of_b

        If possible I would like to pop up a modal window prompting the user
        to confirm this before filling this field.-->
      <a href="{{ query_method() }}" class="btn btn-default">Add with cascade</a>
    </div>
</div>


<div class="form-buttons">
  {{ lib.render_form_buttons(return_url) }}
</div>
{% endcall %}
{% endblock %}-

Я бы зарегистрировал это представление, как сказано в документации

# admin/views.py

class CascadesView(ModelView):

    create_template = 'admin/cascade_button_create.html'

Я не нашел информации по этому поводу, и в шаблонах не так много комментариев, которые могут помочь.

Спасибо!

РЕДАКТИРОВАТЬ:

Я скопировал примеры из репо flask-admin и установил мой https://github.com/diegoquintanav/flask-admin-autopopulate для игры с

1 Ответ

0 голосов
/ 04 июня 2018

Я немного углубился в это, и это кажется очень специфическим поведением, которое не реализовано в flask-admin.Я все равно посмотрел на него, и единственный способ, с помощью которого я мог легко это сделать, - это использовать Ajax и специальный маршрут API.

Итак, я добавил это в ваш js:

<a href="#" class="btn btn-default" onClick="retrieve_location_b_ids()">Add with cascade</a>
<script>
function retrieve_location_b_ids(){

  // make sure that the user wants to preload the b locations
  if (confirm('load location b connected to location a?')){
    // look for the selected options
    var selected_a_locations = $('#s2id_sub_locations_a').select2("val");

    // request the b_ids using the a_ids provided by the user using ajax
    var oData = new FormData();
    oData.append('selected_a_locations', JSON.stringify(selected_a_locations));
    var oReq = new XMLHttpRequest();
    oReq.open("POST", "{{url_for('look_up_b_locations_connected_to_a_locations')}}", true);
    oReq.onload = function(oEvent) {
      if (oReq.status == 200) {
        // get the correct b ids back from the ajax request, and use them to load the select2 field
        var selected_b_ids_list = JSON.parse(oReq.responseText)
        $('#s2id_sub_locations_b').select2('val', selected_b_ids_list);
      } else {
        alert("Error " + oReq.status + " occurred when retrieving the ids")
      }
    };
    oReq.send(oData);
  }
}

</script>

и маршрут колбы, который обрабатывает этот запрос:

@app.route('/api/look_up_b_locations_connected_to_a_locations', methods=['POST'])
def look_up_b_locations_connected_to_a_locations():
    # use a set in case the same b location is in multiple a locations to prevent duplicates
    b_location_set = set()
    a_location_list = json.loads(request.form['selected_a_locations'])
    for a_location_id in a_location_list:
        a_location = SubLocationA.query.get_or_404(a_location_id)
        for b_location in a_location.sub_sub_locations_b:
            b_location_set.add(str(b_location.id))
    return jsonify(list(b_location_set))

Кажется, он работает довольно хорошо и работает с большинством крайних случаев (я надеюсь).

...