結合使用AngularJS和Django

原地址javascript

好吧,我認可本身很懶,時間又不夠用。css

翻譯的幾個文章都是有始無終,但我保證此次確定不太監。html

關鍵的單詞不翻譯,實在以爲翻譯成漢語很彆扭,括號裏是參考翻譯。java

有問題和建議儘管提出來,我會改進完善。git

 

Tutorial: Using AngularJS with Django

原文: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'
複製代碼

 

 

 

On to AngularJS

爲了簡便,你須要建立以下三個模板。

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)
},
複製代碼

 

 

Where to go from here

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. 

相關文章
相關標籤/搜索