AngularJSおよびDjangoでのアプリケーションフレームワークの実行方法

画像



春に、 クラウドバックアップサーバー用のシンプルなサービスを作成するというアイデアが生まれました。 当時、プロジェクトの作業は主に夕方と週末に行われていたため、プロセスを高速化するために、経験のある技術のみを使用することが決定されました。 バックエンド部分にはDjangoが選択され、クライアント部分の実装は、AngularJSに基づくSPAであると想定されていました。 アイデアは次のとおりでした:最小限の機能を備えた製品を作り、徐々に新しい機能を追加します。 これを行うには、十分に柔軟でスケーラブルなシステムを作成する必要がありました。 私たちの頭の中で少し考えて、私たちは取り掛かりました。





ルーティング



そして最初に発生した質問は、クライアント部分のルーティングに関連していました。 互いに埋め込まれたテンプレートをサポートし、特定のURLを特定のテンプレートに明確にマッピングできる信頼性の高いシンプルなシステムが必要でした。 短い検索の後、 ui-routerを選択しました。



次のスキームが承認されました。

途中/



ユーザーには、アプリケーションに関連付けられていないランディングページが表示されます。 /app/



切り替えると/app/



サーバーapp.html



ヘッド全体、本文の最後にあるすべてのスクリプト、および控えめなui-view



属性を持つ1つのdiv



を含むファイルapp.html



ます。 アプリケーション全体がロードされるのは、このdiv



です。 ユーザーがログインしているかどうかに応じて、このdiv



さまざまな塗りつぶしがユーザーに表示されます。



自分より先に進むことはしませんが、認証されたユーザーの場合を考えてみましょう。 したがって、この場合、 /app/



後のURLにハッシュがない場合、次のレイヤーが内部にロードされます: index.html



。 このファイルには、作業領域全体を囲むアプリケーションの静的な部分(ヘッダー、フッター、サイドメニュー)が含まれています。 index.html



には、さらに1つのアプリケーションレベルが読み込まれるui-view



属性を持つdiv



もあります。具体的には、さまざまな画面(この場合、メイン画面、サーバーの詳細画面、請求画面、バックアップ復旧画面など) 。



画像



ui-routerを使用して、これらすべてがどのように記述されるかを見てみましょう。



 app.config(['$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider) { $stateProvider .state('index', { url: '/', templateUrl: '/static/views/index.html' }) .state('index.main', { url: '^/main', templateUrl: '/static/views/pages/main.html' }) .state('index.client', { url: '^/main/c/:id', templateUrl: '/static/views/pages/client.html' }) .state('index.billing', { url: '^/billing', templateUrl: '/static/views/pages/billing.html' }) .state('index.restore', { url: '^/restore', templateUrl: '/static/views/pages/restore.html' }); $urlRouterProvider.otherwise('/main'); //       ,     /main }])
      
      







パブリックページとプライベートページ



特定のページへのユーザーアクセス権の差別化について考える時が来ました。 ユーザーがログインしていない場合、公開ページのみが表示され、プライベートページにアクセスしようとすると、ログイン画面にリダイレクトされます。 逆の場合も同じです。ユーザーが既にログインしている場合、ログイン、登録、パスワード回復ページは表示されません。



そのため、パブリックページに関するデータをルーター構成に追加します。



 $stateProvider .state('login', { url: '/login', templateUrl: '/static/views/login.html' }) .state('signup', { url: '/signup', templateUrl: '/static/views/signup.html' }) .state('recovery', { url: '/recovery', templateUrl: '/static/views/recovery.html' });
      
      







認可を担当するモジュールでは、ユーザーがログインしているかどうかを判断するファクトリが作成されています。



 AuthModule.factory('Auth', ['$cookieStore', function ($cookieStore) { var currentUser = $cookieStore.get('login') || 0, publicStates = ['login', 'signup', 'recovery']; return { authorize: function(state) { return (this.isLoggedIn() && (publicStates.indexOf(state) < 0)) || (!this.isLoggedIn() && (publicStates.indexOf(state) >= 0)) }, isLoggedIn: function() { return !!currentUser; } } }])
      
      







isLoggedIn



メソッドは、ユーザーがログインしている場合はtrue



返し、 true



ない場合はfalse



返しtrue



authorize



メソッドは、現在の状態について、ユーザーがそれに参加する権利を持っているかどうかを判断します。



これらのメソッドの使用は、状態変更の開始時に発生する$stateChangeStart



イベントハンドラーで実行されます。



 $rootScope.$on("$stateChangeStart", function (event, toState, toParams, fromState, fromParams) { //          if (!Auth.authorize(toState.name)) { //       event.preventDefault(); //      (   /app/  - ) if (fromState.url === '^') { if (Auth.isLoggedIn()) { $state.go('index.main'); } else { $state.go('auth'); } } } });
      
      







認証



クライアント側の認証手順は、 Auth



ファクトリーの関数を使用して実装されます。



 login: function (user, success, error) { $http.post('/login/', user) .success(function () { currentUser = 1; success(); }) .error(error); }
      
      







この関数は、コントローラーで呼び出されます。 ユーザー名、 password



およびコールバックは引数として渡されます:



 Auth.login({ username: $scope.login.username, password: $scope.login.password }, function () { $state.go('index.main'); }, function () { $scope.login.error = true; });
      
      







サーバーは標準のdjango-sessionsを使用して、ユーザーに関する情報(彼のID)を保存します。 このために、標準メソッドdjango.contrib.auth



ます。



 from django.contrib.auth import authenticate, login def login_service(request): data = json.loads(request.body) user = authenticate(username=data['username'], password=data['password']) if user is not None: login(request, user) return HttpResponse(status=200) else: return HttpResponse('Login error', status=401)
      
      







各http要求中に、サーバーはユーザーがログインしているかどうかを確認し、対応する値を「Set-Cookie」ヘッダーに設定します。 この値は、クライアント側で$cookieStore.get('login')



を使用してチェックされます。



サーバーモデルとクライアントモデル間のリンク



開発を高速化し、アプリケーションの柔軟性を高めるために、DjangoとAngularJSの間でミドルウェアを使用することが決定されました。 選択はdjango-angular決まりました



その主な利点:







インストールと設定の詳細については、 ドキュメントをご覧ください。



まとめ



その結果、モジュールが相互に最小限に依存する、拡張可能で柔軟なアプリケーションができました。 すべてのモジュールのコードは個別のファイルに保存され、新しいモジュールを追加しても他のモジュールは変更されません。 さらに、django-angular機能は開発を大幅にスピードアップします。






bitcalm.comサーバーのクラウドバックアップサービスの作成方法に関するシリーズの2番目の記事。



最初の記事: 独自のDjango課金システムの開発



All Articles