Cấu trúc dự án và cấu trúc dự án AngularJS điển hình (với Python Flask)


226

Tôi khá mới với toàn bộ khung công tác khách hàng MV * này. Nó không phải là AngularJS, nhưng tôi đã chọn nó vì tôi cảm thấy tự nhiên hơn so với Knockout, Ember hoặc Backbone. Dù sao quy trình làm việc như thế nào? Mọi người có bắt đầu với việc phát triển ứng dụng phía máy khách trong AngularJS và sau đó kết nối back-end với nó không?

Hoặc cách khác bằng cách đầu tiên xây dựng back-end trong Django, Flask, Rails và sau đó đính kèm ứng dụng AngularJS vào nó? Có một cách "đúng" để làm điều đó, hay cuối cùng nó chỉ là một sở thích cá nhân?

Tôi cũng không chắc chắn liệu cấu trúc dự án của tôi theo Flask hay AngularJS? thực hành cộng đồng.

Ví dụ: ứng dụng minitwit của Flask có cấu trúc như vậy:

minitwit
|-- minitwit.py
|-- static
   |-- css, js, images, etc...
`-- templates
   |-- html files and base layout

Ứng dụng hướng dẫn AngularJS có cấu trúc như thế này:

angular-phonecat
|-- app
    `-- css
    `-- img
    `-- js
    `-- lib
    `-- partials
    `-- index.html
|-- scripts
 `-- node.js server and test server files

Tôi có thể tự hình dung một ứng dụng Flask và khá dễ dàng để thấy ứng dụng AngularJS như Danh sách ToDo nhưng khi sử dụng cả hai công nghệ này, tôi không hiểu cách chúng hoạt động cùng nhau. Có vẻ như tôi không cần một khung web phía máy chủ khi bạn đã có AngularJS, một máy chủ web Python đơn giản sẽ đủ. Ví dụ, trong ứng dụng việc cần làm AngularJS, họ sử dụng MongoLab để nói chuyện với cơ sở dữ liệu bằng API đầy đủ. Không cần phải có khung web ở mặt sau.

Có lẽ tôi đang rất bối rối và AngularJS không gì khác hơn là một thư viện jQuery ưa thích vì vậy tôi nên sử dụng giống như tôi sẽ sử dụng jQuery trong các dự án Flask của mình (giả sử tôi thay đổi cú pháp khuôn mẫu AngularJS thành một thứ không xung đột với Jinja2). Tôi hy vọng câu hỏi của tôi có ý nghĩa. Tôi chủ yếu làm việc ở mặt sau và khung phía khách hàng này là một lãnh thổ không xác định đối với tôi.

Câu trả lời:


171

Tôi sẽ bắt đầu bằng cách tổ chức ứng dụng Flask theo cấu trúc tiêu chuẩn như sau:

app
|-- app.py
|-- static
    |-- css
    |-- img
    |-- js
|-- templates

Và như btford đã đề cập, nếu bạn đang làm một ứng dụng Angular, bạn sẽ muốn tập trung vào việc sử dụng các mẫu phía máy khách Angular và tránh xa các mẫu phía máy chủ. Sử dụng render_template ('index.html') sẽ khiến Flask diễn giải các mẫu góc của bạn dưới dạng mẫu jinja, vì vậy chúng sẽ không hiển thị chính xác. Thay vào đó, bạn sẽ muốn làm như sau:

@app.route("/")
def index():
    return send_file('templates/index.html')

Lưu ý rằng sử dụng send_file () có nghĩa là các tệp sẽ được lưu trong bộ nhớ cache, vì vậy bạn có thể muốn sử dụng make_response (), ít nhất là để phát triển:

    return make_response(open('templates/index.html').read())

Sau đó, xây dựng phần AngularJS trong ứng dụng của bạn, sửa đổi cấu trúc ứng dụng để nó trông như thế này:

app
|-- app.py
|-- static
    |-- css
    |-- img
    |-- js
        |-- app.js, controllers.js, etc.
    |-- lib
        |-- angular
            |-- angular.js, etc.
    |-- partials
|-- templates
    |-- index.html

Đảm bảo index.html của bạn bao gồm AngularJS, cũng như mọi tệp khác:

<script src="static/lib/angular/angular.js"></script>

Tại thời điểm này, bạn chưa xây dựng API RESTful của mình, do đó bạn có thể yêu cầu bộ điều khiển js trả về dữ liệu mẫu được xác định trước (chỉ thiết lập tạm thời). Khi bạn đã sẵn sàng, hãy triển khai API RESTful và nối nó với ứng dụng góc của bạn với angular-resource.js.

EDIT: Tôi kết hợp một mẫu ứng dụng, mặc dù phức tạp hơn một chút so với những gì tôi đã mô tả ở trên, minh họa cách người ta có thể xây dựng một ứng dụng với AngularJS + Flask, hoàn thành với giao tiếp giữa AngularJS và API Flask đơn giản. Đây là nếu bạn muốn xem thử: https://github.com/rxl/angular-flask


1
Tôi đã gặp vấn đề này: bối cảnh của tệp không được bảo tồn khi tôi cố gắng phục vụ index.html một cách tĩnh. Tôi đã khắc phục điều này bằng cách thêm vào tệp tĩnh của mình với app.root_path. Nếu không, đây là vị trí đẹp.
Makoto

Bạn có thể giải thích thêm về "Lưu ý rằng sử dụng send_file () có nghĩa là các tệp sẽ được lưu trong bộ nhớ cache, vì vậy bạn có thể muốn sử dụng make_response (), ít nhất là để phát triển"? Cảm ơn
nam

Làm thế nào để bạn quản lý các bản dựng, chẳng hạn như sử dụng grunt với phương pháp này?
Saad Farooq

1
@nam, tôi nghĩ ý của anh ấy là nếu bạn thực hiện một số thay đổi nhỏ trong js của mình, v.v. có nhiều cách để ghi đè lên điều này nhưng đơn giản hơn nhiều là chỉ sử dụng make_response cho đến khi bạn sẵn sàng triển khai.
ars-longa-vita-brevis

@SaadFarooq Tôi không bao gồm tiếng cằn nhằn ở đây vì nó làm phức tạp mọi thứ khá nhiều. Nếu bạn đã sẵn sàng sử dụng một cái gì đó như Grunt, thì thật hợp lý khi có một repo riêng cho mã mặt trước, sau đó kết hợp mọi thứ lại với nhau, sao chép và dán nó vào repo Flask hoặc đẩy nó vào CDN và tham chiếu nó từ index.html.
Ryan

38

Bạn có thể bắt đầu ở một trong hai.

Bạn đúng rằng có lẽ bạn không cần một khung công tác phía máy chủ đầy đủ với AngularJS. Thông thường tốt hơn là phục vụ các tệp HTML / CSS / JavaScript tĩnh và cung cấp API RESTful cho phần cuối để khách hàng sử dụng. Một điều mà có lẽ bạn nên tránh là trộn các mẫu phía máy chủ với các mẫu phía máy khách AngularJS.

Nếu bạn muốn sử dụng Flask để phục vụ các tệp của mình (có thể là quá mức cần thiết, nhưng dù sao bạn cũng có thể sử dụng nó), bạn sẽ sao chép nội dung của "ứng dụng" từ "angular-phonecat" vào thư mục "tĩnh" của "minitwit".

AngularJS được nhắm mục tiêu nhiều hơn vào các ứng dụng giống AJAX, trong khi đó, jar cung cấp cho bạn khả năng thực hiện cả các ứng dụng web kiểu cũ cũng như tạo API RESTful. Có những ưu điểm và nhược điểm đối với từng phương pháp, vì vậy nó thực sự phụ thuộc vào những gì bạn muốn làm. Nếu bạn cung cấp cho tôi một số hiểu biết, tôi có thể có thể đưa ra khuyến nghị thêm.


26
+1 - nhưng tôi không nói rằng Flask được nhắm mục tiêu vào các ứng dụng web kiểu cũ - nó cũng cung cấp tất cả các trợ giúp bạn cần để sử dụng làm phụ trợ API web ;-) Ngoài ra còn có Flask-Restless nếu bạn muốn có thể tạo API phục vụ JSON cho ứng dụng web của bạn thực sự dễ dàng bằng Flask-SQLAlchemy - chỉ FYI :-)
Sean Vieira

Điểm tốt! Tôi không đặc biệt quen thuộc với Flask; cảm ơn đã cung cấp một số chuyên môn về chủ đề này.
btford

3
đồng thời xem hướng dẫn của chúng tôi, hướng dẫn cách xây dựng các ứng dụng thô sơ
Igor Minar

2
Đối với tôi, có vẻ công bằng khi đặt thư mục "ứng dụng" từ "angular-phonecat" vào thư mục tĩnh. Nhưng tôi nghĩ rằng tệp index.html nên được đặt vào thư mục mẫu minitwit. Các thư mục css và img nên được chuyển sang "tĩnh".
Nezo

22

Video JetChins JetChins chính thức này của John Lindquist (angular.js và jetbrains guru) là một điểm khởi đầu tốt đẹp vì nó cho thấy sự tương tác của dịch vụ web, cơ sở dữ liệu và angular.js trong bình.

Anh ta xây dựng một bản sao pinterest với bình, sqlalchemy, không ngừng nghỉ và angular.js trong vòng chưa đầy 25 phút.

Thưởng thức: http://www.youtube.com/watch?v=2geC50roans


17

chỉnh sửa : Hướng dẫn kiểu Angular2 mới gợi ý tương tự, nếu không cùng cấu trúc chi tiết hơn nhiều.

Câu trả lời dưới đây nhắm vào các dự án quy mô lớn. Tôi đã dành khá nhiều thời gian để suy nghĩ và thử nghiệm một số cách tiếp cận để tôi có thể kết hợp một số khung bên máy chủ (Flask với App Engine trong trường hợp của tôi) cho chức năng back-end cùng với khung phía máy khách như Angular. Cả hai câu trả lời đều rất hay, nhưng tôi muốn đề xuất một cách tiếp cận hơi khác (ít nhất là trong suy nghĩ của tôi) mở rộng theo cách nhân văn hơn.

Khi bạn đang thực hiện một ví dụ TODO, mọi thứ khá đơn giản. Khi bạn bắt đầu thêm chức năng mặc dù và các chi tiết nhỏ đẹp để cải thiện trải nghiệm người dùng, không khó để bị lạc trong sự hỗn loạn của các kiểu, javascript, v.v.

Ứng dụng của tôi bắt đầu phát triển khá lớn, vì vậy tôi phải lùi lại một bước và suy nghĩ lại. Ban đầu, một cách tiếp cận như được đề xuất ở trên sẽ hoạt động, bằng cách kết hợp tất cả các kiểu và tất cả JavaScript với nhau, nhưng nó không phải là mô-đun và không dễ bảo trì.

Điều gì xảy ra nếu chúng tôi tổ chức mã máy khách cho mỗi tính năng chứ không phải cho mỗi loại tệp:

app
|-- server
    |-- controllers
        |-- app.py
    |-- models
        |-- model.py
    |-- templates
        |-- index.html
|-- static
    |-- img
    |-- client
        |-- app.js
        |-- main_style.css
        |-- foo_feature
            |-- controller.js
            |-- directive.js
            |-- service.js
            |-- style.css
            |-- html_file.tpl.html
        |-- bar_feature
            |-- controller.js
            |-- directive.js
            |-- service.js
            |-- style.css
            |-- html_file.tpl.html
    |-- lib
        |-- jquery.js
        |-- angular.js
        |-- ...

và như thế.

Nếu chúng ta xây dựng nó như thế này, chúng ta có thể bọc mọi thư mục của chúng ta trong một mô-đun góc. Và chúng tôi đã phân chia các tệp của mình theo cách tốt đẹp mà chúng tôi không phải trải qua mã không liên quan khi chúng tôi đang làm việc với một tính năng cụ thể.

Một trình chạy tác vụ như Grunt được cấu hình đúng cách, sẽ có thể tìm và ghép và biên dịch các tệp của bạn mà không gặp nhiều rắc rối.


1

Một lựa chọn khác là tách hoàn toàn hai.

dự án
| - máy chủ
| - khách hàng

Các tệp liên quan đến bình nằm trong thư mục máy chủ và các tệp liên quan đến angularjs nằm trong thư mục máy khách. Bằng cách này, sẽ dễ dàng hơn để thay đổi phụ trợ hoặc front-end. Ví dụ: bạn có thể muốn chuyển từ Flask sang Django hoặc AngularJS sang ReactJS trong tương lai.


Kevin: Bạn có thể muốn xem lại liên kết, như hướng dẫn đến trang đăng nhập facebook.
RussellB

0

Tôi nghĩ điều quan trọng là xác định ở đầu nào bạn muốn thực hiện hầu hết việc xử lý dữ liệu của mình - mặt trước hoặc mặt sau.
Nếu đó là giao diện người dùng, thì hãy thực hiện quy trình làm việc góc cạnh, điều đó có nghĩa là ứng dụng bình của bạn sẽ hoạt động giống như một api trong đó một phần mở rộng như bình tĩnh sẽ kết thúc.

Nhưng nếu giống như tôi, bạn đang làm hầu hết các công việc phụ trợ, sau đó đi với cấu trúc bình và chỉ cắm góc (hoặc trong trường hợp của tôi là vue.js) để xây dựng mặt trước (khi cần thiết)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.