여기에이 방법이 있습니다. Github에 완전 독립형 예제 인 flask-admin-modal을 넣었습니다.
이 예제에서 SQLite 데이터베이스 모델은 이름 (문자열) 및 비용 (정수) 속성이있는 프로젝트이며 Flask-Admin 목록보기에서 선택된 행의 비용 값을 업데이트합니다. Flask 응용 프로그램이 시작되면 데이터베이스에 임의의 데이터가 채워집니다.
여기 모델의 :
class Project(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(255), nullable=False, unique=True)
cost = db.Column(db.Integer(), nullable=False)
def __str__(self):
return unicode(self).encode('utf-8')
def __unicode__(self):
return "Name: {name}; Cost : {cost}".format(name=self.name, cost=self.cost)
는 새로운 비용을 받아 정수 비용 필드 양식을 정의합니다. 이 양식에는 선택된 행 ID를 추적하는 숨겨진 필드도 있습니다.
class ChangeForm(Form):
ids = HiddenField()
cost = IntegerField(validators=[InputRequired()])
프로젝트보기 모델의 목록 템플릿을 재정의하십시오. 우리는 changeModel
이라는 ID를 가진 부트 스트랩 모달 형식을 {% block body %}
에 삽입 할 수 있도록 {{ super() }}
을 먼저 호출해야합니다.
또한 템플릿 변수 (change_model
)가 true로 평가되면 모달 폼을 표시하는 jQuery 문서 준비 함수를 추가합니다. 동일한 변수가 모델 본체에서 change_form
을 표시하는 데 사용됩니다. 우리는 Flask-Admin lib 매크로 인 render_form을 사용하여 폼을 부트 스트랩 스타일로 렌더링합니다.
조치 매개 변수의 값은 render_form
입니다. 이는 프로젝트보기에서 양식의 데이터를 처리 할 수있는 경로입니다. 또한 "닫기"버튼이 링크로 대체되었지만 버튼으로 스타일이 지정되었습니다. 링크는 작업이 시작된 원본 URL (페이지 및 필터 세부 정보 포함)입니다.
{% extends 'admin/model/list.html' %}
{% block body %}
{{ super() }}
<div class="modal fade" tabindex="-1" role="dialog" id="changeModal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<a href="{{ url }}" class="close" aria-label="Close"><span aria-hidden="true">×</span></a>
<h4 class="modal-title">Change Project Costs</h4>
</div>
<div class="modal-body">
{% if change_modal %}
{{ lib.render_form(change_form, action=url_for('project.update_view', url=url)) }}
{% endif %}
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
{% endblock body %}
{% block tail %}
{{ super() }}
<script>
{% if change_modal %}
$(document).ready(function(){
$("#changeModal").modal('show');
});
{% endif %}
</script>
{% endblock tail %}
프로젝트 뷰 클래스는 배치 작업 메서드의 동작을 수정하고 POST 요청을 받아들이는 몇 개의 경로를 정의해야합니다.
@action('change_cost', 'Change Cost', 'Are you sure you want to change Cost for selected projects?')
def action_change_cost(self, ids):
url = get_redirect_target() or self.get_url('.index_view')
return redirect(url, code=307)
직접 배치 행동을 ID를 처리하는 작업을 게시하는 URL을 가져옵니다 대신에,이 URL은 페이지 번호 및 필터 세부 사항이 포함됩니다. 그런 다음 307을 사용하여 목록보기로 다시 리디렉션합니다. 이렇게하면 선택한 행 ID가 본문에서 전달되고 POST 요청이라는 사실이 보장됩니다.
이 리디렉션을 처리 할 수있는 POST 경로를 정의하고 요청 본문 (예 : ChangeForm
)에서 ID와 URL을 가져온 다음 숨겨진 ids
양식 필드를 ID의 인코딩 된 목록으로 설정합니다. url
, change_form
및 change_model
변수를 템플릿 args에 추가 한 다음 목록보기를 다시 렌더링하십시오. 이번에는 모달 팝업 폼이보기에 표시됩니다.
@expose('/', methods=['POST'])
def index(self):
if request.method == 'POST':
url = get_redirect_target() or self.get_url('.index_view')
ids = request.form.getlist('rowid')
joined_ids = ','.join(ids)
encoded_ids = base64.b64encode(joined_ids)
change_form = ChangeForm()
change_form.ids.data = encoded_ids
self._template_args['url'] = url
self._template_args['change_form'] = change_form
self._template_args['change_modal'] = True
return self.index_view()
모달 양식의 데이터를 처리하기위한 POST 경로를 정의하십시오. 이것은 표준 양식/데이터베이스 처리이며 완료되면 작업을 시작한 원래 URL로 다시 리디렉션됩니다.
@expose('/update/', methods=['POST'])
def update_view(self):
if request.method == 'POST':
url = get_redirect_target() or self.get_url('.index_view')
change_form = ChangeForm(request.form)
if change_form.validate():
decoded_ids = base64.b64decode(change_form.ids.data)
ids = decoded_ids.split(',')
cost = change_form.cost.data
_update_mappings = [{'id': rowid, 'cost': cost} for rowid in ids]
db.session.bulk_update_mappings(Project, _update_mappings)
db.session.commit()
return redirect(url)
else:
# Form didn't validate
# todo need to display the error message in the pop-up
print change_form.errors
return redirect(url, code=307)
@pjcunningham 정말 멋진 해결책을 가져 주셔서 감사합니다. 나는 그것을 나의 응용을 위해 적용했고 그것은 잘 작동한다. 필자가 변경 한 것은'print change_form.errors' 대신'flash()'메시지 뿐이었고 이후에는'code = 307'을 삭제했습니다. (그럼에도 불구하고 그것은 여전히 나를 위해 마술처럼 보입니다.) –