Flask_admin 筆記六 modelView的內置方法

增長model後端
Flask-Admin對與之配合的數據庫模型作了一些假設。 若是要實現本身的數據庫後端,而且Flask-Admin的模型視圖仍可按預期工做,則應注意如下事項:
1) 每個model必須有主鍵,但不限定數據類型和主鍵名
2) 確保每個model的屬性都是能夠訪問的數據庫

在此基礎上,你能夠經過繼承BaseMiodelView類來實現數據庫後端的擴展,並實現下面列出的一系列方法:
1 擴展BaseModelView
首先定義一個從BaseModelView派生的新類:後端

class MyDbModel(BaseModelView):
        pass

這個類繼承了BaseModelView的__init__方法,它接受一個模型類做爲第一個參數。 模型類存儲爲屬性self.model,以便其餘方法能夠訪問它。緩存

如今,爲新的類實現如下腳手架方法:
1.1 get_pk_value()
該方法從模型實例中返回一個主鍵值。 在SQLAlchemy後端,它使用scaffold_pk()從模型得到主鍵,緩存它,而後在須要時從模型返回值。
例子:app

class MyDbModel(BaseModelView):
    def get_pk_value(self, model):
    return self.model.id

1.2 scaffold_list_columns()
返回列表視圖要展現的列。例子:spa

class MyDbModel(BaseModelView):
    def scaffold_list_columns(self):
          columns = []

          for p in dir(self.model):
            attr = getattr(self.model, p)
            if isinstance(attr, MyDbColumn):
                columns.append(p)

           return columns

1.3 scaffold_sortable_columns()
返回可排序列的字典。 字典中的鍵應該對應於模型的字段名稱。 值應該是那些將用於排序的變量。code

例如,在SQLAlchemy後端能夠按外鍵字段進行排序。 因此,若是有一個名爲user的字段,它是Users表的一個外鍵,而且Users表也有一個名稱字段,那麼這個鍵將是user的value將是:Users.name。orm

若是您的後端不支持排序,則返回None或空字典。對象

1.4 init_search()
初始化搜索功能。 若是您的後端支持全文搜索,請進行初始化並返回True。 若是您的後端不支持全文搜索,請返回False。blog

例如,SQLAlchemy後端讀取self.searchable_columns的值,並驗證是否全部字段都是文本類型,若是它們定位到當前的模型(若是不是,則會添加一個鏈接等)並緩存這些信息以備未來使用。
1.5 scaffold_form()
在模型裏定義WTForms表單,例子:排序

class MyDbModel(BaseModelView):
        def scaffold_form(self):
        class MyForm(Form):
              pass

      # Do something
       return MyForm

1.6 get_list()
這個方法應該返回帶有分頁,排序等應用的模型實例列表。

對於SQLAlchemy後端,它看起來像:
1)若是搜索已啓用且提供的搜索值不爲空,將會爲self.searchable_columns中的每一個字段生成LIKE語句

2)若是傳遞過濾值,請使用值調用apply方法:

for flt, value in filters:
    query = self._filters[flt].apply(query, value)

3)執行查詢獲取數據庫中的總行數(count)
4)若是sort_column被傳遞,會作相似的事情(帶有一些額外的FK邏輯,在這個例子中省略):

if sort_desc:
     query = query.order_by(desc(sort_field))
else:
     query = query.order_by(sort_field)

5)應用分頁
6)返回總條數和列表的元組

1.7 get_one()
根據主鍵返回model數據
1.8 create_model()
經過表單建立一個model的實例
1.9 update_model()
更新表單model的實例
1.10 delete_model()
從數據存儲中刪除特定的model數據
1.11 is_valid_filter()
驗證返回的數據是不是有效的
1.12scaffold_filters()
返回一個模型字段的過濾器對象列表。
對於self.column_filters設置中的每一個條目,該方法都會被調用一次。
若是後端不知道如何爲提供的字段生成過濾器,則應該返回None。

例如:

class MyDbModel(BaseModelView):
       def scaffold_filters(self, name):
       attr = getattr(self.model, name)

        if isinstance(attr, MyDbTextField):
        return [MyEqualFilter(name, name)]

2,實現過濾
每一個模型後端都應該有本身的一組過濾器實現。 在非SQLAlchemy後端不能使用SQLAlchemy模型中的過濾器。 這也意味着不一樣的後端可能有不一樣的可用過濾器集合。

過濾器是從BaseFilter派生的類,它實現了至少兩種方法:
1. apply()
2. operation()
apply方法接受兩個參數:查詢對象和來自客戶端的值。 在這裏您能夠爲過濾器類型添加過濾邏輯。

讓咱們以SQLAlchemy模型後端爲例:
全部SQLAlchemy過濾器都從BaseSQLAFilter類派生。
每一個過濾器都實現一個簡單的過濾器SQL操做(如,not like,大於等),並接受一列做爲輸入參數。每當模型視圖要將篩選器應用於查詢對象時,它將在具備查詢和值的篩選器類中調用apply方法。 過濾器將應用實際的過濾器操做。

class MyBaseFilter(BaseFilter):
    def __init__(self, column, name, options=None, data_type=None):
        super(MyBaseFilter, self).__init__(name, options, data_type)

        self.column = column

class MyEqualFilter(MyBaseFilter):
    def apply(self, query, value):
        return query.filter(self.column == value)

    def operation(self):
        return gettext('equals')

    # You can validate values. If value is not valid,
    # return `False`, so filter will be ignored.
    def validate(self, value):
        return True

    # You can "clean" values before they will be
    # passed to the your data access layer
    def clean(self, value):
        return value

若是您在添加新模型後端時遇到問題,請隨時提問。 此外,若是遇到困難,請嘗試查看SQLAlchemy模型後端並將其用做參考。

相關文章
相關標籤/搜索