A ideia desse artigo é explicar uma maneira de usar AngularJS em um projeto Django. Se você não conhece Django, saiba que é um framework web, escrito em Python, muito popular. Já o AngularJS é um framework em JavaScript que faz umas coisas bem legais com o HTML: adiciona funcionalidades, manipula elementos e tem se tornado uma grande tendência entre desenvolvedores front-end. Neste artigo, vamos ver como integrar o AngularJS em um projeto Django sem utilizar pacotes prontos.
Lembramos que esse artigo é apenas um guia de integração entre as ferramentas, por isso seria ideal que o leitor tenha alguma experiência com AngularJS e Django, além de aplicações assíncronas.
Vale lembrar que essa é uma solução dita híbrida, como forma de obter alguns benefícios do Angular.js, dentro do contexto de uma aplicação Django. A solução pura de uma Single Page Application usaria somente o Angular.js ou similares e implementaria a API com Django ou outros web application frameworks, BaaS ou outros frameworks server side, como o Node.js.
Hoje, vamos usar o exemplo de desenvolvimento de um site com um carrinho de compras. Vamos lá!
Definição da estrutura
Comece criando uma aplicação para carrinho de compras:
$ django-admin startapp cart
Crie a estrutura para os arquivos estáticos.
$ mkdir -p cart/static/controllers cart/static/directives cart/static/filters cart/static/services cart/static/tests
Importante: A estrutura que utilizaremos para AngularJS não é uma obrigação. Você pode usufruir dele da forma que achar mais conveniente.
Adicione a app no settings do projeto:
STORE = (‘cart’) INSTALLED_APPS += STORE views.py
Crie uma view básica para renderizar o carrinho e outras duas para serem usadas como APIs:
from django.shortcuts import render
from django.http import HttpResponse
import json
def index(request):
return render(request, 'cart.html', {})
def adicionar_item(request):
itens_pedido = request.session.get('itens_pedido', [])
item = json.loads(request.body)['item']
itens_pedido.append(item)
request.session['itens_pedido'] = itens_pedido
return HttpResponse(json.dumps(itens_pedido))
def excluir_item(request, index):
itens_pedido = request.session.get('itens_pedido', [])
del itens_pedido[int(index)]
request.session['itens_pedido'] = itens_pedido
return HttpResponse(json.dumps(itens_pedido))
urls.py
Crie as rotas das views:
from django.conf.urls import patterns, url
urlpatterns = patterns('cart.views',
url(r'^#039;, 'index'), # NOQA
url(r'^adicionar/', 'adicionar_item'),
url(r'^atualizar/', 'atualizar_item'),
url(r'^excluir/(?P<index>[0-9]+)', 'excluir_item'),
)
Adicione-as no urls.py do projeto:
urlpatterns += patterns('',
url(r'', include('cart.urls')),
)
app.js
Atenção, esta é a parte mais importante do artigo! Sem essa configuração surgirá uma série de problemas. Vá na pasta cart/static/app e crie um arquivo chamado app.js com o seguinte conteúdo:
(function() {
'use strict';
angular.module('app',[
'ngCookies'
], function($interpolateProvider){
// Contorna prroblema de interpolação da renderização de template do django
$interpolateProvider.startSymbol('{[{');
$interpolateProvider.endSymbol('}]}');
})
.run( function run($http, $cookies ){
// Evita problemas relacionados ao CSRF
$http.defaults.headers.post['X-CSRFToken'] = $cookies['csrftoken'];
});
})();
cart-controller.js
Vá na pasta cart/static/app/controllers e crie um arquivo chamado cart-controller.js com o seguinte conteúdo:
(function() {
'use strict';
angular.module('app').controller('CartController', function($scope, $http) {
$scope.pedido = {
itens: [],
total: function() {
var total = 0;
angular.forEach($scope.pedido.itens, function(item) {
total += item.qtd * item.preco;
})
return total;
}
}
$scope.adicionarItem = function() {
var produto = {
descricao: 'A guerra dos tronos - The Board Game',
preco: 150.0,
qtd: 1
}
$http.post('/adicionar/', {item: produto})
.success(function(data) {
$scope.pedido.itens = data;
})
}
$scope.excluirItem = function(index) {
$http.post('/excluir/' + index)
.success(function(data) {
$scope.pedido.itens = data;
})
}
});
})();
cart.html
Agora, iremos criar a página do carrinho. Crie um html em cart/templates/cart.html:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular-cookies.min.js"></script>
<script src="{{ STATIC_URL }}app.js"></script>
<script src="{{ STATIC_URL }}controllers/cart-controller.js"></script>
</head>
<body ng-app="app">
<h2>Carrinho de Compras</h2>
<div ng-controller="CartController">
<table class="table">
<tr>
<th>Descrição</th>
<th>Quantidade</th>
<th>Custo</th>
<th>Total</th>
<th></th>
</tr>
<tr ng-repeat="item in pedido.itens">
<td>{[{ item.descricao }]}</td>
<td><input type="number" ng-model="item.qtd" min="1" max="10"></td>
<td>{[{ item.preco }]}</td>
<td>{[{item.qtd * item.preco | currency}]}</td>
<td>
[<a href ng-click="excluirItem($index)">X</a>]
</td>
</tr>
<tr>
<td><a href ng-click="adicionarItem()" class="btn btn-small">Adicionar Item</a></td>
<td></td>
<td>Total:</td>
<td>{[{pedido.total() | currency}]}</td>
</tr>
</table>
</div>
</body>
</html>
Conclusão
Mostramos neste artigo um exemplo de uso do AngularJS com o Django, definindo uma forma híbrida entre os dois frameworks. A solução foi simplificada ao ponto de não tratar possíveis problemas e requisitos básicos, mas a ideia mais importante era demonstrar o uso dessas ferramentas no mundo real. Às vezes, implementar uma solução com menos dependências externas é mais interessante do que contornar o problema com aplicações de terceiros, simplesmente por termos mais controle sobre o que estamos criando. Veremos mais desse conceito em um próximo artigo, que abordará como criar testes para AngularJS.
Ah! Caso você queira, veja o repositório pronto no bitbucket da Concrete. Se ficou alguma dúvida, tem alguma sugestão ou crítica, deixe seu comentário abaixo.



