好吧,我认可本身很懒,时间又不够用。javascript
翻译的几个文章都是有始无终,但我保证此次确定不太监。css
关键的单词不翻译,实在以为翻译成汉语很别扭,括号里是参考翻译。html
有问题和建议尽管提出来,我会改进完善。java
原文:http://glynjackson.org/weblog/entry/django-angular.html 点我进原文git
Posted on: 31 Jan 2014, 4:58 p.m. Categories: Django Frameworks Pythonangularjs
我本来打算写一个如何结合Angular和Django的快速入门,但最后证实这只是一篇喝了红牛后的冲动产物。抱歉草草结束。(这是做者原话)github
看了几个结合使用Angular和Django的文章,我发现本身在从新发明轮子。尽管我给出的例子很粗糙,可是它们已经足够展现我在项目中如何操做。web
Models (模型)ajax
一个标准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.