原地址javascript
好吧,我認可本身很懶,時間又不夠用。css
翻譯的幾個文章都是有始無終,但我保證此次確定不太監。html
關鍵的單詞不翻譯,實在以爲翻譯成漢語很彆扭,括號裏是參考翻譯。java
有問題和建議儘管提出來,我會改進完善。git
原文:http://glynjackson.org/weblog/entry/django-angular.html 點我進原文angularjs
Posted on: 31 Jan 2014, 4:58 p.m. Categories: Django Frameworks Pythongithub
我本來打算寫一個如何結合Angular和Django的快速入門,但最後證實這只是一篇喝了紅牛後的衝動產物。抱歉草草結束。(這是做者原話)web
看了幾個結合使用Angular和Django的文章,我發現本身在從新發明輪子。儘管我給出的例子很粗糙,可是它們已經足夠展現我在項目中如何操做。ajax
Models (模型)數據庫
一個標準Django模型
/jobs/models.py
class Job(models.Model): name = models.CharField(max_length=50) description = models.TextField(null=True, blank=True)
目前爲止還沒什麼特別之處。你所作的只是建立了一個簡單的模型來存基本的工做信息。
The REST API (Tastypie)
AngularJS被髮明來終結webservices,因此你只須要提供你剛建立的Job模型就足夠了。
Django在建立 RESTful APIs 上頗有一套。 TastyPie是爲Django建立的極好的web服務框架。 TastyPie及其強大,易於配置和使用。 拋開我的喜愛,使用Django REST framework也能作一樣的事情,甚至能直接用Django構造你本身的API響應。 使用哪一個的選擇權在你。 這篇文章我會使用 TastyPie。
若你不熟悉TastyPie ,看這個文檔(點我) 。我不會詳說安裝等細枝末節的東西。我假定你已經安裝配置好了TastyPie ,並卻已經準備好和我繼續下去了。
首先,你須要爲你的jobs建立一個resource。 TastyPie遵循「Resources」這樣的理念, 它把resource做爲end user和objects(這裏指的是Job模型)的中介。
爲Job模型建立一個適當的resource:
class JobResource(ModelResource): """ API Facet """ class Meta: queryset = Jobs.objects.all() resource_name = 'job' allowed_methods = ['post', 'get', 'patch', 'delete'] authentication = Authentication() authorization = Authorization() always_return_data = True
我記得TastyPies官方文檔建議在你的應用中用api.py來命名此文件。這也是個人作法,儘管它不是強制的。你能夠隨意命名,可是按照約定命名文件能夠保證一致性。
JobResource 的一些設置已經超出了本文章的範圍。但我樂於解釋JobResource是繼承自ModelResource的。 結合Tastypie與Django ORM二者使用。擴展它意味着你已經可以能深刻API的基本實現了。
TastyPie 也能處理非ORM數據。經過直接擴展Resource,你也可以獲得TastyPie提供的全部好處。 No SQL數據庫描述以下(點我)。
如今你已經建立了模型和與之交互的方式。接下來,你須要一個把resource鏈接到實際URL的步驟,如此,AngularJS才能發揮它的做用。 簡單的舉例說明如何在Django URLConf裏創建這樣的鏈接。:
from tastypie.api import Api from .apps.your_app.api import JobResource v1_api = Api(api_name='v1') v1_api.register(JobResource()) urlpatterns = patterns('', (r'^api/', include(v1_api.urls)), )
在JobResource指定resource_name屬性是最後一步。如今,你已經創立了一個有效綁定Resource到Job模型上的API。 檢查它在server上是否工做良好,用你的瀏覽器訪問 http://127.0.0.1:8000/api/job/?format=json 。
Forms
在你深刻AngularJS前,咱們來建立一個Job form。 Job form會讓你在你的應用中輕鬆編寫Jobs。我知道你會問,爲何要這麼作。
好吧,Django其中一個哲學就是,不作重複勞動(Don't repeat yourself (DRY))。 因此建立爲AngularJS寫HTML,而後在Django也這麼作就顯得極不合理,由於Django會幫你作這件事。你可能已經有了不少須要轉換的forms。爲何要重複這個過程? 點擊 django-angular. 這是一個很酷的包,你會喜歡它的。
Quote: "Django-Angular is a collection of utilities, which aim to ease the integration of Django with AngularJS by providing reusable components."
如今我架設你已經安裝好了 Django-Angular 。把這些放進一個如'crispy forms'的包裏,你會獲得一個一站式的解決方案 -- 這是我爲何喜歡Django和它的社區。
from .app.your_app.models import Job from .apps.djangular.forms import NgFormValidationMixin, NgModelFormMixin, AddPlaceholderFormMixin class JobForm(NgModelFormMixin, forms.ModelForm): """ Job Form with a little crispy forms added! """ def __init__(self, *args, **kwargs): super(JobForm, self).__init__(*args, **kwargs) setup_bootstrap_helpers(self) class Meta: model = Job fields = ('name', 'description',) def setup_bootstrap_helpers(object): object.helper = FormHelper() object.helper.form_class = 'form-horizontal' object.helper.label_class = 'col-lg-3' object.helper.field_class = 'col-lg-8'
爲了簡便,你須要建立以下三個模板。
templates jobs/index.html jobs/new.html base.html
這說明你有一個叫job的app而且已經安裝了。你的base模板會像下面同樣:
/jobs/base.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.0.2/css/bootstrap.min.css" rel="stylesheet"> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.js"></script> <script src="/angular-ui-router.min.js"></script> <script type="text/javascript" src="http://cdn.jsdelivr.net/restangular/latest/restangular.js"></script> </head> <body> {% block content %}{% endblock content %} {% block extra_javascript %}{% endblock extra_javascript %} </body> </html>
Django-Angular已經提供了不少很好的模板標籤,這些標籤包含了必要的javascript。我建議使用分佈式目錄網絡(CDN)來加載必要的文件。如此作,你會獲得明顯的地理上的和寬帶資源上的好處。
你須要建立一個page模板。index.html會做爲主頁,它會接收請求。
/jobs/index.html
{% extends "base.html" %} {% load i18n %} {% block content %} <div class="container content" ng-app="JobApp"> <div ui-view >Loading...</div> </div> {% endblock content %} {% block extra_javascript %} <script src="{{ STATIC_URL }}/javascript/app.js"></script> {% endblock extra_javascript %}
/javascript/app.js
var app = angular.module('JobApp', [ 'ui.router', 'restangular' ]) app.config(function ($stateProvider, $urlRouterProvider, RestangularProvider) { // For any unmatched url, send to /route1 $urlRouterProvider.otherwise("/"); $stateProvider .state('index', { url: "/", templateUrl: "/static/html/partials/_job_list.html", controller: "JobList" }) .state('new', { url: "/new", templateUrl: "/jobs/job-form", controller: "JobFormCtrl" }) }) app.controller("JobFormCtrl", ['$scope', 'Restangular', 'CbgenRestangular', '$q', function ($scope, Restangular, CbgenRestangular, $q) { }])// end controller
模板和js很是簡單,它們繼承自base模板。有幾個必需要明白的屬性你可能沒見過。
第一個是 ng-app='JobApp'。 沒有這個標籤,AngularJS不會起做用。這個指令告訴AngularJS哪個元素是應用的根元素。你所向根元素寫入的東西會成爲被AngularJS管理的一部分。
接下來,看你在index.html裏引入的的腳本文件。 app.js 腳本定義了angular模塊。 當應用被booted(啓動)時, 一個angular模塊就是函數的集合。
var app = angular.module('JobApp', [
上一行建立了名爲JobApp的模塊。 在index.html裏你已經經過聲明屬性爲ng-app='JobApp'來實例化它了。你所作的就是告訴AngularJS你想讓app.js包含所需的全部。
實際上,你能夠把ng-app設置成任何DOM中的元素。例如,若是你只想模板其中一個部分被AngularJS控制,你能夠這樣作:
<h2>I am not inside an AngularJS app</h2> <div ng-app="embeddedApp"> <h3>Inside an AngularJS app</h3> </div>
在app.js裏的app.config展現了你URL路由(routing)。AngularJS經過默認的變量 $route 來提供URL路由,可是不太適當,而且有限制。
其中你已經包括進來的模板是 AngularUI Router ‘ui.router’。 AngularUI Router是另外一個爲AngularJS擴展的圍繞狀態擴展的路由框架。
你提供了僅僅一個叫作new的state,其實能夠爲你的應用包含許多不一樣的state。 甚至當沒有state返回時,你能夠添加一個默認的行爲。
$urlRouterProvider.otherwise("/");
$stateProvider
.state('index', {
url: "/",
templateUrl: "static/html/somepage.html",
controller: "SomeController"
})
若是你還不熟悉這些,看完此文我建議你讀 AngularUI Router。
最後你要了解的元素是ui-view。 這也是AngularUI Router 模型的一部分。 ui-view 指令告訴 $state 哪裏放置你的模板,例如, templateUrl: "/job/new/"。
最後你要建立的模板是 /jobs/new.html。 這裏包括了你剛纔用 Django-Angular 建立的basic form。
{% load crispy_forms_tags %} {% crispy JobForm %} <button type="button" class="btn btn-default" ng-click="submitJob()">Create</button>
如今把view和URL鏈接到form。
/jobs/views.py
from .forms import JobForm class JobFormView(TemplateView): template_name = "jobs/new.html" def get_context_data(self, **kwargs): context = super(JobFormView, self).get_context_data(**kwargs) context.update(JobForm=JobForm()) return context
/jobs/urls.py
from django.conf.urls import url from django.conf.urls import patterns from .views import JobFormView urlpatterns = patterns('', url(r'^job-form/$', login_required(JobFormView.as_view()), name='job_form'), )
用你的瀏覽器訪問 http://127.0.0.1:8000/job/#new。 你會看到剛纔的勞動成果。
Restangular is an AngularJS service that simplifies common GET, DELETE, and UPDATE requests with a minimum of client code. It's a perfect fit for any WebApp that consumes data from a RESTful API. restangular
app.controller("JobFormCtrl", ['$scope', 'Restangular', 'CbgenRestangular', '$q', function ($scope, Restangular, CbgenRestangular, $q) { $scope.submitJob = function () { var post_update_data = create_resource($scope, CbgenRestangular); $q.when(post_update_data.then( function (object) { // success! }, function (object){ // error! console.log(object.data) } )) } }])// end controller app.factory('CbgenRestangular', function (Restangular) { return Restangular.withConfig(function (RestangularConfigurer) { RestangularConfigurer.setBaseUrl('/api/v1'); }); }) populate_scope_values = function ($scope) { return {name: $scope.name, description: $scope.description }; }, create_resource = function ($scope, CbgenRestangular) { var post_data = populate_scope_values($scope) return CbgenRestangular.all('job').post(post_data) },
Too much to cover in just one blog post. Best practices should be your next step and head over to egghead, best tutorials on the web in my opinion.