2015-10-07 55 views
7

Tôi vẫn còn mới để Flask, vì vậy có thể có một cách rõ ràng để thực hiện điều này, nhưng tôi đã không thể tìm ra nó cho đến nay từ các tài liệu hướng dẫn. Ứng dụng của tôi được chia thành nhiều phần khác nhau, chia sẻ những thứ như người dùng/phiên/bảo mật và mẫu cơ bản và mọi thứ nhưng hầu hết không tương tác nhiều và phải được định tuyến theo các đường dẫn khác nhau như /part1/.... Tôi nghĩ rằng đây là khá nhiều chính xác những gì bản thiết kế được cho. Nhưng nếu tôi cần phải nhóm các tuyến đường và logic hơn nữa theo một kế hoạch chi tiết?Blueprints lồng nhau trong Flask?

Ví dụ: tôi có blueprint1 với url_prefix='/blueprint1' và có thể theo đó tôi muốn có bộ sưu tập lượt xem xoay quanh người dùng chia sẻ ảnh và người dùng khác nhận xét về họ. Tôi không thể nghĩ ra một cách tốt hơn để làm việc đó hơn:

# app/blueprints/blueprint1/__init__.py 

blueprint1 = Blueprint('blueprint1', __name__, template_folder='blueprint1') 

@blueprint1.route('/photos') 
def photos_index(): 
    return render_template('photos/index.html') 

@blueprint.route('/photos/<int:photo_id>') 
def photos_show(photo_id): 
    photo = get_a_photo_object(photo_id) 
    return render_template('photos/show.html', photo=photo) 

@blueprint.route('/photos', methods=['POST']) 
def photos_post(): 
    ... 

Vấn đề ở đây là tất cả các quan điểm liên quan đến những bức ảnh phần của blueprint1 đang nằm ở "cấp cao nhất", đúng với lẽ đồ án cho video hoặc âm thanh hoặc bất kỳ thứ gì (có tên là videos_index() ...). Có cách nào để nhóm chúng theo cách phân cấp hơn, giống như cách các mẫu nằm trong thư mục con 'blueprint1/photos'? Tất nhiên tôi có thể đặt tất cả các chế độ xem ảnh trong mô-đun riêng của họ để giữ cho chúng được tổ chức riêng biệt, nhưng điều gì sẽ xảy ra nếu tôi muốn thay đổi đường dẫn của phụ huynh là 'blueprint1/photos' thành một thứ khác? Tôi chắc chắn rằng tôi có thể phát minh ra một hàm hoặc trang trí nhóm các tuyến có liên quan dưới cùng một đường dẫn gốc, nhưng sau đó tôi vẫn phải đặt tên tất cả các hàm với tiền tố photos_ và tham chiếu chúng như url_for('blueprint1.photos_show'). ứng dụng trở nên lớn và bạn cần phải nhóm và ngăn các phần tương tự lại với nhau, nhưng bạn không thể làm điều tương tự khi bản thiết kế bản thân chúng lớn lên.

Để tham khảo, trong Laravel bạn có thể nhóm "lượt xem" có liên quan trong một lớp Controller trong đó chế độ xem là phương thức. Bộ điều khiển có thể cư trú trong không gian tên thứ bậc như app\Http\Controllers\Blueprint1\Photocontroller, các tuyến đường có thể được nhóm lại với nhau như

Route::group(['prefix' => 'blueprint1'], function() { 

    Route::group(['prefix' => 'photos'], function() { 

     Route::get('/', ['as' => 'blueprint.photos.index', 'uses' => '[email protected]']); 
     Route::post('/', ['as' => 'blueprint.photos.store', 'uses' => '[email protected]']); 
     Route::get('/{id}', ['as' => 'blueprint.photos.get', 'uses' => '[email protected]']) 
      ->where('id', '[0-9]+'); 

    }); 

}); 

và các tuyến đường có thể được nhận như action('Blueprint1\[email protected]').

Nếu chỉ tôi có thể tạo bản thiết kế ảnh, thì chỉ cần thực hiện blueprint1.register_blueprint(photos_blueprint, url_prefix='/photos') hoặc tương tự, những sự cố này sẽ được giải quyết khá nhiều. Thật không may Flask dường như không hỗ trợ các bản thiết kế làm tổ như thế này. Có cách nào khác để xử lý vấn đề này không?

Trả lời

7

Thật không may, các bản thiết kế lồng nhau không phải là tính năng hiện tại trong Flask. Bạn sẽ phải làm điều đó bằng tay. Bạn có thể có thể mã một cái gì đó mà làm việc cho trường hợp cụ thể của bạn, nhưng một giải pháp chung chưa được thêm vào Flask. Hiện đã có một số cuộc thảo luận về theo dõi vấn đề:

4

tôi đã thực hiện một lớp được gọi là NestedBlueprint để hack nó.

class NestedBlueprint(object): 
    def __init__(self, blueprint, prefix): 
     super(NestedBlueprint, self).__init__() 
     self.blueprint = blueprint 
     self.prefix = '/' + prefix 

    def route(self, rule, **options): 
     rule = self.prefix + rule 
     return self.blueprint.route(rule, **options) 

Đây là tập tin cơ sở của tôi, trong đó có kế hoạch chi tiết: panel/__init__.py

from flask import Blueprint 

panel_blueprint = Blueprint(PREFIX, __name__, url_prefix='/panel') 

from . import customize 

Dưới đây là cụ thể/lồng tập tin trong đó có kế hoạch chi tiết lồng nhau: panel/customize.py

from rest.api.panel import panel_blueprint 
from rest.api.util.nested_blueprint import NestedBlueprint 

nested_blueprint = NestedBlueprint(panel_blueprint, 'customize') 


@nested_blueprint.route('/test', methods=['GET']) 
def test(): 
    return ':)' 

Sau đó bạn có thể gọi như này:

$ curl http://localhost:5000/panel/customize/test 
:) 
+0

phương pháp này không hoạt động với @ blueprint_name.before_request –

0

Dưới đây là cách giải quyết của tôi:

Khi nhập một kế hoạch chi tiết, tôi xác định các tuyến đường lồng nhau của tôi:

app.register_blueprint(product_endpoints, url_prefix='/sites/<int:site_id>/menus/<int:menu_id>/categories/<int:category_id>/products/<int:product_id>') 
app.register_blueprint(category_endpoints, url_prefix='/sites/<int:site_id>/menus/<int:menu_id>/categories/<int:category_id>') 
app.register_blueprint(menu_endpoints, url_prefix='/sites/<int:site_id>/menus/<int:menu_id>') 
app.register_blueprint(site_endpoints, url_prefix='/sites/<int:site_id>') 

Và bên trong bản thiết kế, tôi tái sử dụng chức năng tuyến đường phân tích cú pháp. Ví dụ, trong product_endpoints file:

from category_endpoints import get_category_data 

product_endpoints = Blueprint('product_endpoints', __name__) 

@product_endpoints.url_value_preprocessor 
def get_product_data(endpoint, values): 
    if 'category_id' in values: 
     get_category_data(endpoint, values) 

    product = Product.get_by_id(int(values.pop('product_id'))) 

    if not product: 
     abort(404) 

    g.product = product 

và trong category_endpoints file:

from menu_endpoints import get_menu_data 

category_endpoints = Blueprint('category_endpoints', __name__) 

@category_endpoints.url_value_preprocessor 
def get_category_data(endpoint, values): 
    if 'menu_id' in values: 
     get_menu_data(endpoint, values) 
    category = ProductCategory.get_by_id(int(values.pop('category_id'))) 

    if not category: 
     abort(404) 

    g.category = category 

vv ... Với cách tiếp cận đó, kế hoạch chi tiết của tôi cũng là có thể sử dụng với các tuyến đường trực tiếp như /products/<int:product_id>.

Cách tiếp cận này phù hợp với tôi rất tốt. Tôi hy vọng nó cũng có thể giúp bạn.