
春に、
クラウドバックアップサーバー用のシンプルなサービスを作成するというアイデアが生まれました。 当時、プロジェクトの作業は主に夕方と週末に行われていたため、プロセスを高速化するために、経験のある技術のみを使用することが決定されました。 バックエンド部分には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');
パブリックページとプライベートページ
特定のページへのユーザーアクセス権の差別化について考える時が来ました。 ユーザーがログインしていない場合、公開ページのみが表示され、プライベートページにアクセスしようとすると、ログイン画面にリダイレクトされます。 逆の場合も同じです。ユーザーが既にログインしている場合、ログイン、登録、パスワード回復ページは表示されません。
そのため、パブリックページに関するデータをルーター構成に追加します。
$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) {
認証
クライアント側の認証手順は、
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で
決まりました 。
その主な利点:
- 基本的なCRUD操作を実行する機能を提供します。
- django-formsとangle-controllersをしっかりと接続できます;
- 角度コントローラーから直接djangoのメソッドを呼び出す機能を提供します。
インストールと設定の詳細については、
ドキュメントをご覧ください。
まとめ
その結果、モジュールが相互に最小限に依存する、拡張可能で柔軟なアプリケーションができました。 すべてのモジュールのコードは個別のファイルに保存され、新しいモジュールを追加しても他のモジュールは変更されません。 さらに、django-angular機能は開発を大幅にスピードアップします。
bitcalm.comサーバーのクラウドバックアップサービスの作成方法に関するシリーズの2番目の記事。
最初の記事:
独自のDjango課金システムの開発