Skip to content

Commit

Permalink
- Fix bug with csrftoken in landing pages using dajaxice.
Browse files Browse the repository at this point in the history
- Improve reliability handling server errors.
- Update documentation
- Prepare 0.2 release
  • Loading branch information
Jorge Bastida committed Jul 3, 2011
1 parent aea9623 commit 3bdf3ea
Show file tree
Hide file tree
Showing 12 changed files with 118 additions and 43 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG
@@ -1,5 +1,7 @@
dajaxice (0.2) stable; urgency=normal
- Fix bug with the 'is_callback_a_function' variable in dajaxice.core.js
- Fix bug with csrftoken in landing pages using dajaxice.
- Improve reliability handling server errors.
- Exception handling was fully rewritten. Dajaxice default_error_callback is now configurable using Dajaxice.setup.
- Custom error messages per dajaxice call.
- Dajaxice now propagate docstrings to javascript dajaxice functions.
Expand Down
34 changes: 19 additions & 15 deletions dajaxice/templates/dajaxice/dajaxice.core.js
Expand Up @@ -2,7 +2,7 @@ var Dajaxice = {
{% for module in dajaxice_js_functions %}
{% include "dajaxice/dajaxice_core_loop.js" %}
{% endfor %}{% ifnotequal dajaxice_js_functions|length 0 %},{% endifnotequal %}

get_cookie: function(name)
{
var cookieValue = null;
Expand All @@ -19,25 +19,25 @@ var Dajaxice = {
}
return cookieValue;
},

call: function(dajaxice_function, dajaxice_callback, argv, custom_settings)
{
var send_data = [];
var is_callback_a_function = (typeof(dajaxice_callback) == 'function');

if(!is_callback_a_function){
alert("dajaxice_callback should be a function since dajaxice 0.2")
}

if(custom_settings == undefined){
custom_settings = {};
}

var error_callback = this.get_setting('default_exception_callback');
if('error_callback' in custom_settings && typeof(custom_settings['error_callback']) == 'function'){
error_callback = custom_settings['error_callback'];
}

send_data.push('argv='+encodeURIComponent(JSON.stringify(argv)));
send_data = send_data.join('&');
var oXMLHttpRequest = new XMLHttpRequest;
Expand All @@ -46,7 +46,7 @@ var Dajaxice = {
oXMLHttpRequest.setRequestHeader("X-CSRFToken",Dajaxice.get_cookie('csrftoken'));
oXMLHttpRequest.onreadystatechange = function() {
if (this.readyState == XMLHttpRequest.DONE) {
if(this.responseText == Dajaxice.EXCEPTION){
if(this.responseText == Dajaxice.EXCEPTION || !(this.status in this.valid_http_responses())){
error_callback();
}
else{
Expand All @@ -61,21 +61,25 @@ var Dajaxice = {
}
oXMLHttpRequest.send(send_data);
},

setup: function(settings)
{
this.settings = settings;
},

get_setting: function(key){
if(this.settings == undefined || this.settings[key] == undefined){
return this.default_settings[key];
}
return this.settings[key];
},

default_exception_callback: function(data){
alert('Something goes wrong');
},

valid_http_responses: function(){
return {200: null, 301: null, 302: null, 304: null}
}
};

Expand All @@ -87,19 +91,19 @@ window['Dajaxice'] = Dajaxice;
{% comment %}
/*
XMLHttpRequest.js Compiled with Google Closure
XMLHttpRequest.js Copyright (C) 2008 Sergey Ilinsky (http://www.ilinsky.com)
This work is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This work is distributed in the hope that it will be useful,
but without any warranty; without even the implied warranty of
merchantability or fitness for a particular purpose. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Expand Down Expand Up @@ -131,4 +135,4 @@ g=i;return c}}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSO
o=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,g,m,q={"\u0008":"\\b","\t":"\\t","\n":"\\n","\u000c":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},j;if(typeof JSON.stringify!=="function")JSON.stringify=function(a,c,d){var f;m=g="";if(typeof d==="number")for(f=0;f<d;f+=1)m+=" ";else if(typeof d==="string")m=d;if((j=c)&&typeof c!=="function"&&(typeof c!=="object"||typeof c.length!=="number"))throw new Error("JSON.stringify");return l("",
{"":a})};if(typeof JSON.parse!=="function")JSON.parse=function(a,c){function d(f,i){var e,b,h=f[i];if(h&&typeof h==="object")for(e in h)if(Object.hasOwnProperty.call(h,e)){b=d(h,e);if(b!==undefined)h[e]=b;else delete h[e]}return c.call(f,i,h)}p.lastIndex=0;if(p.test(a))a=a.replace(p,function(f){return"\\u"+("0000"+f.charCodeAt(0).toString(16)).slice(-4)});if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){a=eval("("+a+")");return typeof c==="function"?d({"":a},""):a}throw new SyntaxError("JSON.parse");}})();
{% endif %}
{% endif %}
2 changes: 1 addition & 1 deletion dajaxice/templates/dajaxice/dajaxice_js_import.html
@@ -1 +1 @@
<script src="/{{ DAJAXICE_MEDIA_PREFIX }}/dajaxice.core.js" type="text/javascript" charset="utf-8"></script>
<script src="{{ core_url }}" type="text/javascript" charset="utf-8"></script>
24 changes: 22 additions & 2 deletions dajaxice/templatetags/dajaxice_templatetags.py
Expand Up @@ -31,12 +31,32 @@
# DAMAGE.
#----------------------------------------------------------------------

import logging

from django import template
from django.conf import settings

from dajaxice.core import DajaxiceRequest
from django.middleware.csrf import get_token

register = template.Library()

log = logging.getLogger('dajaxice')


@register.inclusion_tag('dajaxice/dajaxice_js_import.html', takes_context=True)
def dajaxice_js_import(context):
return {'DAJAXICE_MEDIA_PREFIX': DajaxiceRequest.get_media_prefix()}
def dajaxice_js_import(context, core_url=None):
# We must force this request to add the csrftoken cookie.
request = context.get('request', None)
if request:
get_token(request)
else:
log.warning("The 'request' object must be accesible within the context. \
You must add 'django.contrib.messages.context_processors.request' \
to your TEMPLATE_CONTEXT_PROCESSORS and render your views\
using a RequestContext.")
if not core_url or DajaxiceRequest.get_debug():
core_url = '/%s/dajaxice.core.js' % DajaxiceRequest.get_media_prefix()
else:
core_url = '%s%s' % (settings.STATIC_URL or '', core_url,)
return {'core_url': core_url}
17 changes: 17 additions & 0 deletions docs/csrftoken-issues.rst
@@ -0,0 +1,17 @@
CSRF Token issues
====================

.. note::
New in **django-dajaxice 0.2**


The templatetag ``dajaxice_js_import`` ensures that django sets the ``csrftoken`` into the response when we use dajaxice in our templates.
This is the reason behind the new ``django.core.context_processors.request`` requirement in ``TEMPLATE_CONTEXT_PROCESSORS``. This templatetag
forces django to include the ``csrftoken`` in every response that uses a template with this decorator.::

{% dajaxice_js_import %}

Further information:

* https://github.com/jorgebastida/django-dajaxice/issues/30
* https://docs.djangoproject.com/en/1.2/ref/contrib/csrf/#ajax
3 changes: 2 additions & 1 deletion docs/index.rst
Expand Up @@ -36,6 +36,7 @@ If you’re new to dajaxice, you may want to start with these documents:
custom-error-callbacks
production-environment
migrating-to-02
csrftoken-issues
available-settings
modules.rst

Expand All @@ -59,6 +60,6 @@ Requirements
Dajaxice doesn't require any special package to start working.

* Python>=2.4
* Django>=1.1
* Django>=1.1.4


28 changes: 19 additions & 9 deletions docs/installation.rst
Expand Up @@ -5,32 +5,42 @@ Follow this instructions to start using dajaxice in your django project.
Installing dajaxice
--------------------------

Add `dajaxice` in your project settings.py inside **INSTALLED_APPS**::
Add `dajaxice` in your project settings.py inside ``INSTALLED_APPS``::

INSTALLED_APPS = (
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'dajaxice',
...
)
)

Ensure that **TEMPLATE_LOADERS**, looks like the following. Probably you need to uncomment the last line.::
Ensure that ``TEMPLATE_LOADERS``, looks like the following. Probably you need to uncomment the last line.::

TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
'django.template.loaders.eggs.Loader',
)

Add **DAJAXICE_MEDIA_PREFIX** in your settings.py::
Ensure that ``TEMPLATE_CONTEXT_PROCESSORS`` has ``django.core.context_processors.request``.::

TEMPLATE_CONTEXT_PROCESSORS = ("django.contrib.auth.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media",
"django.core.context_processors.static",
"django.core.context_processors.request",
"django.contrib.messages.context_processors.messages")

Add ``DAJAXICE_MEDIA_PREFIX`` to your settings.py::

DAJAXICE_MEDIA_PREFIX="dajaxice"

Configure dajaxice url
------------------------

Add the following code inside urls.py::

from dajaxice.core import dajaxice_autodiscover
Expand All @@ -51,7 +61,7 @@ Dajaxice needs to include some js in your template, you should load ``dajaxice_t
.. code-block:: html

{% load dajaxice_templatetags %}

<html>
<head>
<title>My base template</title>
Expand All @@ -60,8 +70,8 @@ Dajaxice needs to include some js in your template, you should load ``dajaxice_t
</head>
...
</html>
...


This templatetag include dynamic dajaxice core. It's a good idea in production environment serving this file statically.
Check :doc:`production-environment` for more production-performance help.

Expand Down
17 changes: 15 additions & 2 deletions docs/production-environment.rst
@@ -1,12 +1,25 @@
Dajaxice in production environment
===========================================

Dajaxice generates dynamically it's JS core in every request using::
Dajaxice generates dynamically its JS core in every request using::

{% load dajaxice_templatetags %}
{% dajaxice_js_import %}

This is a good feature when you run your project inside your development machine, but when you need performance in your production environment this file could be generated and served statically.
This is a good feature when you run your project in your development machine, but when you need performance in your production environment this file should be generated and served statically.

.. note::
New in **dango-dajaxice 0.2**

``dajaxice_js_import`` templatetag can also handle ``dajaxice.core.js`` statically generated files.
You can add as first argument the path where the static file will reside inside your ``STATIC_ROOT`` and the template tag
will include this file if your ``DAJAXICE_DEBUG`` is ``False``. If not or if this argument isn't present it will include
the dynamically generated file::

{% dajaxice_js_import "js/dajaxice.core.js"%}

This decorator also ensures that django sets the ``csrftoken`` into the response when we use dajaxice in the templates.


Generating Uncompiled version
-------------------------------
Expand Down
10 changes: 9 additions & 1 deletion examples/settings.py
Expand Up @@ -72,6 +72,14 @@
# Don't forget to use absolute paths, not relative paths.
)

TEMPLATE_CONTEXT_PROCESSORS = ("django.contrib.auth.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media",
"django.core.context_processors.static",
"django.core.context_processors.request",
"django.contrib.messages.context_processors.messages")

INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
Expand All @@ -83,7 +91,7 @@
)

DAJAXICE_MEDIA_PREFIX = "dajaxice"
DAJAXICE_DEBUG = False
DAJAXICE_DEBUG = True
DAJAXICE_JS_DOCSTRINGS = True
#DAJAXICE_NOTIFY_EXCEPTIONS = True

Expand Down
16 changes: 8 additions & 8 deletions examples/simple/templates/simple/simple_index.html
Expand Up @@ -6,33 +6,33 @@
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
{% dajaxice_js_import %}
<script type="text/javascript" charset="utf-8">

function callback_example1(data){
alert(data.message);
}

function callback_example2(data){
for (var i=0; i < data.numbers.length; i++) {
alert(data.numbers[i]);
}
}

function callback_example3(data){
alert(data.result);
}

function callback_example_error(data){
alert(data);
}

function callback_complex_example1(data){
alert(data.message);
}

function custom_error(){
alert('Custom error');
}

</script>
</head>
<body>
Expand All @@ -50,4 +50,4 @@ <h3>old string callback</h3>
<input type="button" name="some_name" value="Call Example 1! (String)" onclick="Dajaxice.simple.example1('callback_example1');"

</body>
</html>
</html>
4 changes: 2 additions & 2 deletions examples/simple/views.py
@@ -1,5 +1,5 @@
from django.shortcuts import render_to_response
from django.shortcuts import render


def simple_index(request):
return render_to_response('simple/simple_index.html')
return render(request, 'simple/simple_index.html')
4 changes: 2 additions & 2 deletions setup.py
Expand Up @@ -2,11 +2,11 @@

setup(
name = "django-dajaxice",
version = "0.1.8.1",
version = "0.2",
author = "Benito Jorge Bastida Perez",
author_email = "jorge@thecodefarm.com",
description = "Agnostic and easy to use ajax library for django",
download_url = "http://cloud.github.com/downloads/jorgebastida/django-dajaxice/django-dajaxice-0.1.8.1.tar.gz",
download_url = "http://cloud.github.com/downloads/jorgebastida/django-dajaxice/django-dajaxice-0.2.tar.gz",
url = "http://dajaxproject.com",
packages= ['dajaxice', 'dajaxice.templatetags', 'dajaxice.core', 'dajaxice.management', 'dajaxice.management.commands'],
package_data = {'dajaxice': ['templates/dajaxice/*']},
Expand Down

0 comments on commit 3bdf3ea

Please sign in to comment.