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",$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 andhead over toegghead,best tutorials on the web in my opinion.

Tutorial: Using AngularJS with Django的更多相关文章

  1. Android Studio是否支持用于Android UI设计的AngularJS?

    我对AndroidStudio有疑问:AS在设计XML文件时是否支持AngularJS代码,例如:对于小动画或效果?

  2. 难以在Android和iPhone上部署Django应用程序..计划切换到PHP而不是Django

    .我是否需要学习PHP,C,Java或其他任何东西,或者只要知道django和python就可以做到这一点?

  3. android – 如何使用ClientID和ClientSecret在Phonegap中使用Angularjs登录Google OAuth2

    我正尝试使用Angularjs(使用IonicFramework)通过GoogleOAuth2从我的Phonegap应用程序登录.目前我正在使用http://phonegap-tips.com/articles/google-api-oauth-with-phonegaps-inappbrowser.html进行登录.但是当我使用Angular-UI-RouterforIonic时,它正在创建非常

  4. Android发送发送请求到django服务器csrf失败

    我想我的Android应用程序能够发送一些信息到我的django服务器.所以我做的Android应用程序发送一个发布请求到mysite/上传页面,django的这个页面的视图将基于post数据工作.问题是服务器对post请求的响应,关于csrf验证失败.看看这个问题,似乎我可能必须先从服务器获取一个csrf令牌,然后用该令牌做帖子但是我不知道我该怎么做.编辑:我已经发现,我可以使用视图装饰器@cs

  5. 利用require.js与angular搭建spa应用的方法实例

    这篇文章主要给大家介绍了关于利用require.js与angular搭建spa应用的方法实例,文中通过示例代码给大家介绍的非常详细,对大家的理解和学习具有一定的参考学习价值,需要的朋友们下面跟着小编来一起看看吧。

  6. 详解Angular动态组件

    本文主要介绍了Angular动态组件,对此感兴趣的同学,可以亲自实验一下。

  7. 详解如何使用webpack+es6开发angular1.x

    本篇文章主要介绍了详解如何使用webpack+es6开发angular1.x,具有一定的参考价值,有兴趣的可以了解一下

  8. angular2系列之路由转场动画的示例代码

    本篇文章主要介绍了angular2系列之路由转场动画的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  9. 一种angular的方法级的缓存注解(装饰器)

    本篇文章主要介绍了一种angular的方法级的缓存注解(装饰器),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  10. pycharm社区版安装django并创建一个简单项目的全过程

    社区版的pycharm跟专业版的pycharm应用差别还是不太大,下面这篇文章主要给大家介绍了关于pycharm社区版安装django并创建一个简单项目的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下

随机推荐

  1. Angular2 innerHtml删除样式

    我正在使用innerHtml并在我的cms中设置html,响应似乎没问题,如果我这样打印:{{poi.content}}它给了我正确的内容:``但是当我使用[innerHtml]=“poi.content”时,它会给我这个html:当我使用[innerHtml]时,有谁知道为什么它会剥离我的样式Angular2清理动态添加的HTML,样式,……

  2. 为Angular根组件/模块指定@Input()参数

    我有3个根组件,由根AppModule引导.你如何为其中一个组件指定@input()参数?也不由AppModalComponent获取:它是未定义的.据我所知,你不能将@input()传递给bootstraped组件.但您可以使用其他方法来做到这一点–将值作为属性传递.index.html:app.component.ts:

  3. angular-ui-bootstrap – 如何为angular ui-bootstrap tabs指令指定href参数

    我正在使用角度ui-bootstrap库,但我不知道如何为每个选项卡指定自定义href.在角度ui-bootstrap文档中,指定了一个可选参数select(),但我不知道如何使用它来自定义每个选项卡的链接另一种重新定义问题的方法是如何使用带有角度ui-bootstrap选项卡的路由我希望现在还不算太晚,但我今天遇到了同样的问题.你可以通过以下方式实现:1)在控制器中定义选项卡href:2)声明一个函数来改变控制器中的散列:3)使用以下标记:我不确定这是否是最好的方法,我很乐意听取别人的意见.

  4. 离子框架 – 标签内部的ng-click不起作用

    >为什么标签标签内的按钮不起作用?>但是标签外的按钮(登陆)工作正常,为什么?>请帮我解决这个问题.我需要在点击时做出回复按钮workingdemo解决方案就是不要为物品使用标签.而只是使用divHTML

  5. Angular 2:将值传递给路由数据解析

    我正在尝试编写一个DataResolver服务,允许Angular2路由器在初始化组件之前预加载数据.解析器需要调用不同的API端点来获取适合于正在加载的路由的数据.我正在构建一个通用解析器,而不是为我的许多组件中的每个组件设置一个解析器.因此,我想在路由定义中传递指向正确端点的自定义输入.例如,考虑以下路线:app.routes.ts在第一个实例中,解析器需要调用/path/to/resourc

  6. angularjs – 解释ngModel管道,解析器,格式化程序,viewChangeListeners和$watchers的顺序

    换句话说:如果在模型更新之前触发了“ng-change”,我可以理解,但是我很难理解在更新模型之后以及在完成填充更改之前触发函数绑定属性.如果您读到这里:祝贺并感谢您的耐心等待!

  7. 角度5模板形式检测形式有效性状态的变化

    为了拥有一个可以监听其包含的表单的有效性状态的变化的组件并执行某些组件的方法,是reactiveforms的方法吗?

  8. Angular 2 CSV文件下载

    我在springboot应用程序中有我的后端,从那里我返回一个.csv文件WheniamhittingtheURLinbrowsercsvfileisgettingdownloaded.现在我试图从我的角度2应用程序中点击此URL,代码是这样的:零件:服务:我正在下载文件,但它像ActuallyitshouldbeBook.csv请指导我缺少的东西.有一种解决方法,但您需要创建一个页面上的元

  9. angularjs – Angular UI-Grid:过滤后如何获取总项数

    提前致谢:)你应该避免使用jQuery并与API进行交互.首先需要在网格创建事件中保存对API的引用.您应该已经知道总行数.您可以使用以下命令获取可见/已过滤行数:要么您可以使用以下命令获取所选行的数量:

  10. angularjs – 迁移gulp进程以包含typescript

    或者我应该使用tsc作为我的主要构建工具,让它解决依赖关系,创建映射文件并制作捆绑包?

返回
顶部