他のモデルの編集ビューへのリンクを編集ビューで表示する簡単な例を以下に示します。それはあなたを助けるかもしれません。
![enter image description here](https://i.stack.imgur.com/qiKAM.png)
私は、ユーザーを使用しました - アドレスの関係、ユーザーはアドレスおよびアドレスを持つには、多くのユーザーを持つことができます。
Fakerを使用してサンプルデータを生成しましたので、ご使用の環境にpip install faker
が必要です。
Flask-Admin form rulesを使用し、この場合はform_edit_rules
を設定しています。
私は2つのカスタムルールを作成しました:BaseRule
を継承し、
Link
を。コンストラクタには3つの値があります。エンドポイント、Flask url_for
メソッドでエンドポイントと一緒に渡す属性の名前、最後にリンクとして表示されるテキスト。この例では、リンク先のビューであるため、エンドポイントは'address.edit_view'
です。
MultiLink
と同様に、Link
と同様に関係で動作します。
from random import randint
from flask import Flask, url_for
from flask_admin.contrib import sqla
from flask_admin import Admin
from flask_admin.form.rules import BaseRule
from faker import Faker
from flask_sqlalchemy import SQLAlchemy
from markupsafe import Markup
from sqlalchemy import func, select
from sqlalchemy.ext.hybrid import hybrid_property
fake = Faker()
# Create application
app = Flask(__name__)
# Create dummy secrey key so we can use sessions
app.config['SECRET_KEY'] = '123456790'
# Create in-memory database
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'
# app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app)
# Flask views
@app.route('/')
def index():
return '<a href="/admin/">Click me to get to Admin!</a>'
class Address(db.Model):
__tablename__ = 'addresses'
id = db.Column(db.Integer, primary_key=True)
number = db.Column(db.String(255))
street = db.Column(db.String(255))
city = db.Column(db.String(255))
country = db.Column(db.String(255))
@hybrid_property
def user_count(self):
return len(self.users)
@user_count.expression
def user_count(cls):
return select([func.count(User.id)]).where(User.address_id == cls.id).label("user_count")
def __unicode__(self):
return ', '.join(filter(None, [self.number, self.street, self.city, self.country]))
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.String(255))
last_name = db.Column(db.String(255))
email = db.Column(db.String(254))
address_id = db.Column(db.Integer, db.ForeignKey('addresses.id'), index=True)
address = db.relationship(Address, backref=db.backref('users'))
def __str__(self):
return unicode(self).encode('utf-8')
def __unicode__(self):
return '{} {}'.format(self.first_name, self.last_name)
class Link(BaseRule):
def __init__(self, endpoint, attribute, text):
super(Link, self).__init__()
self.endpoint = endpoint
self.text = text
self.attribute = attribute
def __call__(self, form, form_opts=None, field_args={}):
_id = getattr(form._obj, self.attribute, None)
if _id:
return Markup('<a href="{url}">{text}</a>'.format(url=url_for(self.endpoint, id=_id), text=self.text))
class MultiLink(BaseRule):
def __init__(self, endpoint, relation, attribute):
super(MultiLink, self).__init__()
self.endpoint = endpoint
self.relation = relation
self.attribute = attribute
def __call__(self, form, form_opts=None, field_args={}):
_hrefs = []
_objects = getattr(form._obj, self.relation)
for _obj in _objects:
_id = getattr(_obj, self.attribute, None)
_link = '<a href="{url}">Edit {text}</a>'.format(url=url_for(self.endpoint, id=_id), text=str(_obj))
_hrefs.append(_link)
return Markup('<br>'.join(_hrefs))
class UserAdmin(sqla.ModelView):
can_view_details = True
form_edit_rules = (
'first_name',
'last_name',
'email',
'address',
Link(endpoint='address.edit_view', attribute='address_id', text='Edit Address')
)
class AddressAdmin(sqla.ModelView):
can_view_details = True
column_list = ['number', 'street', 'city', 'country', 'user_count', 'users']
form_edit_rules = (
'number',
'street',
'city',
'country',
'users',
MultiLink(endpoint='user.edit_view', relation='users', attribute='id')
)
admin = Admin(app, template_mode="bootstrap3")
admin.add_view(UserAdmin(User, db.session))
admin.add_view(AddressAdmin(Address, db.session))
def build_db():
db.drop_all()
db.create_all()
for _ in range(0, 20):
_users = []
for _ in range(0, randint(1, 10)):
_user = User(
first_name=fake.first_name(),
last_name=fake.last_name(),
email=fake.safe_email(),
)
_users.append(_user)
_address = Address(
number=fake.random_digit_not_null(),
street=fake.secondary_address(),
city=fake.city(),
country=fake.country(),
users = _users
)
db.session.add(_address)
db.session.commit()
@app.before_first_request
def first_request():
build_db()
if __name__ == '__main__':
app.run(port=5000, debug=True)
あなたが子供のコレクションに対処する方法を説明するために、これを更新することができるだろう:
ここでは、コード(チェック少しの誤差があります)ですか?たとえば、ユーザーが複数のアドレスを持つことができますか? – melchoir55
@ melchoir55 - リレーションで動作する 'MultiLink'フォームルールを追加しました。 – pjcunningham