結合使用AngularJS和Django


原地址

好吧,我承認自己很懶,時間又不夠用。

翻譯的幾個文章都是虎頭蛇尾,但我保證這次肯定不太監。

關鍵的單詞不翻譯,實在覺得翻譯成漢語很別扭,括號里是參考翻譯。

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

 

Tutorial: Using AngularJS with Django

原文:http://glynjackson.org/weblog/entry/django-angular.html      點我進原文

Posted on: 31 Jan 2014, 4:58 p.m. Categories: Django Frameworks Python

     我原本打算寫一個如何結合Angular和Django的快速入門,但最后證明這只是一篇喝了紅牛后的沖動產物。抱歉草草結束。(這是作者原話)

     看了幾個結合使用Angular和Django的文章,我發現自己在重新發明輪子。盡管我給出的例子很粗糙,但是它們已經足夠展示我在項目中如何操作。

 

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. 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM