Upgrade Dajaxice to latest version from github (0.5.5) to make meeting agenda code work with CSRF, with url conf import fix and using json instead of deprecated simplejson from Django - add a simple view to serve dajaxice.core.js which we need because we are not using the staticfiles collection step (apparently Dajaxice hooks into that through a somewhat complicated hack)

- Legacy-Id: 7028
This commit is contained in:
Ole Laursen 2013-12-20 11:59:09 +00:00
parent 88860edba4
commit fa489ce37a
27 changed files with 504 additions and 998 deletions

View file

@ -1 +1 @@
VERSION = (0, 2, 0, 0, 'beta')
__version__ = (0, 5, 5, 'beta')

View file

@ -1,156 +1,107 @@
#import logging
import logging
from django.conf import settings
from django.utils.importlib import import_module
# Python 2.7 has an importlib with import_module.
# For older Pythons, Django's bundled copy provides it.
# For older Django's dajaxice reduced_import_module.
try:
from importlib import import_module
except:
try:
from django.utils.importlib import import_module
except:
from dajaxice.utils import simple_import_module as import_module
#log = logging.getLogger('dajaxice.DajaxiceRequest')
import syslog
def warning(msg):
syslog.syslog(syslog.LOG_WANRNING, msg)
log = syslog
log.warning = warning
log = logging.getLogger('dajaxice')
class DajaxiceFunction(object):
""" Basic representation of a dajaxice ajax function."""
def __init__(self, name, path, doc=None):
def __init__(self, function, name, method):
self.function = function
self.name = name
self.path = path
self.doc = doc
self.method = method
def get_callable_path(self):
return '%s.%s' % (self.path.replace('.ajax', ''), self.name)
def __cmp__(self, other):
return (self.name == other.name and self.path == other.path)
def call(self, *args, **kwargs):
""" Call the function. """
return self.function(*args, **kwargs)
class DajaxiceModule(object):
def __init__(self, module):
self.functions = []
self.sub_modules = []
self.name = module[0]
""" Basic representation of a dajaxice module. """
sub_module = module[1:]
if len(sub_module) != 0:
self.add_submodule(sub_module)
def __init__(self, name=None):
self.name = name
self.functions = {}
self.submodules = {}
def get_module(self, module):
"""
Recursively get_module util we found it.
"""
if len(module) == 0:
return self
def add(self, name, function):
""" Add this function at the ``name`` deep. If the submodule already
exists, recusively call the add method into the submodule. If not,
create the module and call the add method."""
for dajaxice_module in self.sub_modules:
if dajaxice_module.name == module[0]:
return dajaxice_module.get_module(module[1:])
return None
def add_function(self, function):
self.functions.append(function)
def has_sub_modules(self):
return len(self.sub_modules) > 0
def add_submodule(self, module):
"""
Recursively add_submodule, if it's not registered, create it.
"""
if len(module) == 0:
return
# If this is not the final function name (there are more modules)
# split the name again an register a new submodule.
if '.' in name:
module, extra = name.split('.', 1)
if module not in self.submodules:
self.submodules[module] = DajaxiceModule(module)
self.submodules[module].add(extra, function)
else:
sub_module = self.exist_submodule(module[0])
if type(sub_module) == int:
self.sub_modules[sub_module].add_submodule(module[1:])
else:
self.sub_modules.append(DajaxiceModule(module))
def exist_submodule(self, name):
"""
Check if submodule name was already registered.
"""
for module in self.sub_modules:
if module.name == name:
return self.sub_modules.index(module)
return False
self.functions[name] = function
class Dajaxice(object):
def __init__(self):
self._registry = []
self._callable = []
self._registry = {}
self._modules = None
for function in getattr(settings, 'DAJAXICE_FUNCTIONS', ()):
function = function.rsplit('.', 1)
self.register_function(function[0], function[1])
def register(self, function):
self.register_function(function.__module__, function.__name__, function.__doc__)
def register_function(self, module, name, doc=None):
def register(self, function, name=None, method='POST'):
"""
Register function at 'module' depth
"""
#Create the dajaxice function.
function = DajaxiceFunction(name=name, path=module, doc=doc)
Register this function as a dajaxice function.
#Check for already registered functions.
full_path = '%s.%s' % (module, name)
if full_path in self._callable:
log.warning('%s already registered as dajaxice function.' % full_path)
If no name is provided, the module and the function name will be used.
The final (customized or not) must be unique. """
method = self.clean_method(method)
# Generate a default name
if not name:
module = ''.join(str(function.__module__).rsplit('.ajax', 1))
name = '.'.join((module, function.__name__))
if ':' in name:
log.error('Ivalid function name %s.' % name)
return
self._callable.append(full_path)
# Check for already registered functions
if name in self._registry:
log.error('%s was already registered.' % name)
return
#Dajaxice path without ajax.
module_without_ajax = module.replace('.ajax', '').split('.')
# Create the dajaxice function.
function = DajaxiceFunction(function=function,
name=name,
method=method)
#Register module if necessary.
exist_module = self._exist_module(module_without_ajax[0])
# Register this new ajax function
self._registry[name] = function
if type(exist_module) == int:
self._registry[exist_module].add_submodule(module_without_ajax[1:])
else:
self._registry.append(DajaxiceModule(module_without_ajax))
def is_callable(self, name, method):
""" Return if the function callable or not. """
return name in self._registry and self._registry[name].method == method
#Register Function
module = self.get_module(module_without_ajax)
if module:
module.add_function(function)
def clean_method(self, method):
""" Clean the http method. """
method = method.upper()
if method not in ['GET', 'POST']:
method = 'POST'
return method
def get_module(self, module):
"""
Recursively get module from registry
"""
for dajaxice_module in self._registry:
if dajaxice_module.name == module[0]:
return dajaxice_module.get_module(module[1:])
return None
def is_callable(self, name):
return name in self._callable
def _exist_module(self, module_name):
for module in self._registry:
if module.name == module_name:
return self._registry.index(module)
return False
def get_functions(self):
return self._registry
def get(self, name):
""" Return the dajaxice function."""
return self._registry[name]
@property
def modules(self):
""" Return an easy to loop module hierarchy with all the functions."""
if not self._modules:
self._modules = DajaxiceModule()
for name, function in self._registry.items():
self._modules.add(name, function)
return self._modules
LOADING_DAJAXICE = False
@ -158,8 +109,8 @@ LOADING_DAJAXICE = False
def dajaxice_autodiscover():
"""
Auto-discover INSTALLED_APPS ajax.py modules and fail silently when
not present.
NOTE: dajaxice_autodiscover was inspired/copied from django.contrib.admin autodiscover
not present. NOTE: dajaxice_autodiscover was inspired/copied from
django.contrib.admin autodiscover
"""
global LOADING_DAJAXICE
if LOADING_DAJAXICE:

View file

@ -1,228 +0,0 @@
#----------------------------------------------------------------------
# Copyright (c) 2009-2011 Benito Jorge Bastida
# All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# o Redistributions of source code must retain the above copyright
# notice, this list of conditions, and the disclaimer that follows.
#
# o Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# o Neither the name of Digital Creations nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
# IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
# CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.
#----------------------------------------------------------------------
import os
import sys
#import logging
import traceback
import json
from django.conf import settings
from django.http import HttpResponse
from dajaxice.core import dajaxice_functions
from dajaxice.exceptions import FunctionNotCallableError, DajaxiceImportError
#log = logging.getLogger('dajaxice.DajaxiceRequest')
import syslog
def debug(msg):
syslog.syslog(syslog.LOG_DEBUG, msg)
def info(msg):
syslog.syslog(syslog.LOG_INFO, msg)
def warning(msg):
syslog.syslog(syslog.LOG_WANRNING, msg)
def error(msg):
syslog.syslog(syslog.LOG_ERR, msg)
log = syslog
log.debug = debug
log.info = info
log.warning = warning
log.error = error
# Python 2.7 has an importlib with import_module.
# For older Pythons, Django's bundled copy provides it.
# For older Django's dajaxice reduced_import_module.
try:
from importlib import import_module
except:
try:
from django.utils.importlib import import_module
except:
from dajaxice.utils import simple_import_module as import_module
def safe_dict(d):
"""
Recursively clone json structure with UTF-8 dictionary keys
http://www.gossamer-threads.com/lists/python/bugs/684379
"""
if isinstance(d, dict):
return dict([(k.encode('utf-8'), safe_dict(v)) for k, v in d.iteritems()])
elif isinstance(d, list):
return [safe_dict(x) for x in d]
else:
return d
class DajaxiceRequest(object):
def __init__(self, request, call):
call = call.rsplit('.', 1)
self.app_name = call[0]
self.method = call[1]
self.request = request
self.project_name = os.environ['DJANGO_SETTINGS_MODULE'].split('.')[0]
self.module = "%s.ajax" % self.app_name
self.full_name = "%s.%s" % (self.module, self.method)
@staticmethod
def get_js_functions():
return dajaxice_functions.get_functions()
@staticmethod
def get_media_prefix():
return getattr(settings, 'DAJAXICE_MEDIA_PREFIX', "dajaxice")
@staticmethod
def get_functions():
return getattr(settings, 'DAJAXICE_FUNCTIONS', ())
@staticmethod
def get_debug():
return getattr(settings, 'DAJAXICE_DEBUG', True)
@staticmethod
def get_notify_exceptions():
return getattr(settings, 'DAJAXICE_NOTIFY_EXCEPTIONS', False)
@staticmethod
def get_cache_control():
if settings.DEBUG:
return 0
return getattr(settings, 'DAJAXICE_CACHE_CONTROL', 5 * 24 * 60 * 60)
@staticmethod
def get_xmlhttprequest_js_import():
return getattr(settings, 'DAJAXICE_XMLHTTPREQUEST_JS_IMPORT', True)
@staticmethod
def get_json2_js_import():
return getattr(settings, 'DAJAXICE_JSON2_JS_IMPORT', True)
@staticmethod
def get_exception_message():
return getattr(settings, 'DAJAXICE_EXCEPTION', u'DAJAXICE_EXCEPTION')
@staticmethod
def get_js_docstrings():
return getattr(settings, 'DAJAXICE_JS_DOCSTRINGS', False)
def _is_callable(self):
"""
Return if the request function was registered.
"""
return dajaxice_functions.is_callable(self.full_name)
def _get_ajax_function(self):
"""
Return a callable ajax function.
This function should be imported according the Django version.
"""
return self._modern_get_ajax_function()
def _modern_get_ajax_function(self):
"""
Return a callable ajax function.
This function uses django.utils.importlib
"""
self.module_import_name = "%s.%s" % (self.project_name, self.module)
try:
return self._modern_import()
except:
self.module_import_name = self.module
return self._modern_import()
def _modern_import(self):
try:
mod = import_module(self.module_import_name)
return mod.__getattribute__(self.method)
except:
raise DajaxiceImportError()
def process(self):
"""
Process the dajax request calling the apropiate method.
"""
if self._is_callable():
log.debug('Function %s is callable' % self.full_name)
argv = self.request.POST.get('argv')
if argv != 'undefined':
try:
argv = json.loads(self.request.POST.get('argv'))
argv = safe_dict(argv)
except Exception, e:
log.error('argv exception %s' % e)
argv = {}
else:
argv = {}
log.debug('argv %s' % argv)
try:
thefunction = self._get_ajax_function()
response = '%s' % thefunction(self.request, **argv)
except Exception, e:
trace = '\n'.join(traceback.format_exception(*sys.exc_info()))
log.error(trace)
response = '%s' % DajaxiceRequest.get_exception_message()
if DajaxiceRequest.get_notify_exceptions():
self.notify_exception(self.request, sys.exc_info())
log.info('response: %s' % response)
return HttpResponse(response, mimetype="application/x-json")
else:
log.debug('Function %s is not callable' % self.full_name)
raise FunctionNotCallableError(name=self.full_name)
def notify_exception(self, request, exc_info):
"""
Send Exception traceback to ADMINS
Similar to BaseHandler.handle_uncaught_exception
"""
from django.conf import settings
from django.core.mail import mail_admins
subject = 'Error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), request.path)
try:
request_repr = repr(request)
except:
request_repr = "Request repr() unavailable"
trace = '\n'.join(traceback.format_exception(*(exc_info or sys.exc_info())))
message = "%s\n\n%s" % (trace, request_repr)
mail_admins(subject, message, fail_silently=True)

View file

@ -1,5 +1,38 @@
from Dajaxice import Dajaxice
dajaxice_functions = Dajaxice()
from django.conf import settings
from DajaxiceRequest import DajaxiceRequest
from Dajaxice import dajaxice_autodiscover
from Dajaxice import Dajaxice, dajaxice_autodiscover
class DajaxiceConfig(object):
""" Provide an easy to use way to read the dajaxice configuration and
return the default values if no configuration is present."""
default_config = {'DAJAXICE_XMLHTTPREQUEST_JS_IMPORT': True,
'DAJAXICE_JSON2_JS_IMPORT': True,
'DAJAXICE_EXCEPTION': 'DAJAXICE_EXCEPTION',
'DAJAXICE_MEDIA_PREFIX': 'dajaxice'}
def __getattr__(self, name):
""" Return the customized value for a setting (if it exists) or the
default value if not. """
if name in self.default_config:
if hasattr(settings, name):
return getattr(settings, name)
return self.default_config.get(name)
return None
@property
def dajaxice_url(self):
return r'^%s/' % self.DAJAXICE_MEDIA_PREFIX
@property
def django_settings(self):
return settings
@property
def modules(self):
return dajaxice_functions.modules
dajaxice_functions = Dajaxice()
dajaxice_config = DajaxiceConfig()

View file

@ -1,10 +1,48 @@
import functools
from dajaxice.core import dajaxice_functions
def dajaxice_register(original_function):
"""
Register the original funcion and returns it
def dajaxice_register(*dargs, **dkwargs):
""" Register some function as a dajaxice function
For legacy purposes, if only a function is passed register it a simple
single ajax function using POST, i.e:
@dajaxice_register
def ajax_function(request):
...
After 0.5, dajaxice allow to customize the http method and the final name
of the registered function. This decorator covers both the legacy and
the new functionality, i.e:
@dajaxice_register(method='GET')
def ajax_function(request):
...
@dajaxice_register(method='GET', name='my.custom.name')
def ajax_function(request):
...
You can also register the same function to use a different http method
and/or use a different name.
@dajaxice_register(method='GET', name='users.get')
@dajaxice_register(method='POST', name='users.update')
def ajax_function(request):
...
"""
dajaxice_functions.register(original_function)
return original_function
if len(dargs) and not dkwargs:
function = dargs[0]
dajaxice_functions.register(function)
return function
def decorator(function):
@functools.wraps(function)
def wrapper(request, *args, **kwargs):
return function(request, *args, **kwargs)
dajaxice_functions.register(function, *dargs, **dkwargs)
return wrapper
return decorator

View file

@ -1,41 +1,10 @@
#----------------------------------------------------------------------
# Copyright (c) 2009-2011 Benito Jorge Bastida
# All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# o Redistributions of source code must retain the above copyright
# notice, this list of conditions, and the disclaimer that follows.
#
# o Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# o Neither the name of Digital Creations nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
# IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
# CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.
#----------------------------------------------------------------------
class FunctionNotCallableError(Exception):
def __init__(self, name):
self.name = name
class DajaxiceImportError(Exception):
class DajaxiceError(Exception):
pass
class FunctionNotCallableError(DajaxiceError):
pass
class DajaxiceImportError(DajaxiceError):
pass

View file

@ -44,7 +44,7 @@ class VirtualStorage(finders.FileSystemStorage):
for f in self.files:
if f.startswith(path):
f = f.replace(path, '', 1)
if os.sep in f:
if os.sep in f:
folders.append(f.split(os.sep, 1)[0])
else:
files.append(f)
@ -60,7 +60,7 @@ class VirtualStorage(finders.FileSystemStorage):
class DajaxiceStorage(VirtualStorage):
files = {'dajaxice/dajaxice.core.js': 'dajaxice_core_js'}
files = {os.path.join('dajaxice', 'dajaxice.core.js'): 'dajaxice_core_js'}
def dajaxice_core_js(self):
from dajaxice.core import dajaxice_autodiscover, dajaxice_config
@ -68,7 +68,7 @@ class DajaxiceStorage(VirtualStorage):
dajaxice_autodiscover()
c = Context({'dajaxice_config': dajaxice_config})
return get_template('dajaxice/dajaxice.core.js').render(c)
return get_template(os.path.join('dajaxice', 'dajaxice.core.js')).render(c)
class DajaxiceFinder(finders.BaseStorageFinder):

View file

@ -1,83 +0,0 @@
#----------------------------------------------------------------------
# Copyright (c) 2009-2011 Benito Jorge Bastida
# All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# o Redistributions of source code must retain the above copyright
# notice, this list of conditions, and the disclaimer that follows.
#
# o Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# o Neither the name of Digital Creations nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
# IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
# CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.
#----------------------------------------------------------------------
import httplib
import urllib
from django.core.management.base import BaseCommand
from django.template.loader import render_to_string
from optparse import make_option
from dajaxice.core import DajaxiceRequest
from dajaxice.core import dajaxice_autodiscover
dajaxice_autodiscover()
class Command(BaseCommand):
help = "Generate dajaxice.core.js file to import it as static file"
args = "[--compile]"
option_list = BaseCommand.option_list + (
make_option('--compile', default='no', dest='compile', help='Compile output using Google closure-compiler'),
)
requires_model_validation = False
def handle(self, *app_labels, **options):
compile_output = options.get('compile', 'yes')
data = {'dajaxice_js_functions': DajaxiceRequest.get_js_functions(),
'DAJAXICE_URL_PREFIX': DajaxiceRequest.get_media_prefix(),
'DAJAXICE_XMLHTTPREQUEST_JS_IMPORT': DajaxiceRequest.get_xmlhttprequest_js_import(),
'DAJAXICE_JSON2_JS_IMPORT': DajaxiceRequest.get_json2_js_import(),
'DAJAXICE_EXCEPTION': DajaxiceRequest.get_exception_message()}
js = render_to_string('dajaxice/dajaxice.core.js', data)
if compile_output.lower() == "closure":
print self.complie_js_with_closure(js)
else:
print js
def complie_js_with_closure(self, js):
params = urllib.urlencode([
('js_code', js),
('compilation_level', 'ADVANCED_OPTIMIZATIONS'),
('output_format', 'text'),
('output_info', 'compiled_code'),
])
# Always use the following value for the Content-type header.
headers = {"Content-type": "application/x-www-form-urlencoded"}
conn = httplib.HTTPConnection('closure-compiler.appspot.com')
conn.request('POST', '/compile', params, headers)
response = conn.getresponse()
data = response.read()
conn.close()
return data

View file

@ -0,0 +1 @@
# Don't delete me

View file

@ -1,8 +1,14 @@
{% load url from future %}
var Dajaxice = {
{% for module in dajaxice_js_functions %}
{% include "dajaxice/dajaxice_core_loop.js" %}
{% endfor %}{% ifnotequal dajaxice_js_functions|length 0 %},{% endifnotequal %}
{% with module=dajaxice_config.modules top='top' %}
{% include "dajaxice/dajaxice_function_loop.js" %}
{% endwith %}
{% for name, module in dajaxice_config.modules.submodules.items %}
{% include "dajaxice/dajaxice_module_loop.js" %},
{% endfor %}
get_cookie: function(name)
{
var cookieValue = null;
@ -19,95 +25,106 @@ var Dajaxice = {
}
return cookieValue;
},
call: function(dajaxice_function, dajaxice_callback, argv, exception_callback)
call: function(dajaxice_function, method, 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")
var custom_settings = custom_settings || {},
error_callback = Dajaxice.get_setting('default_exception_callback');
if('error_callback' in custom_settings && typeof(custom_settings['error_callback']) == 'function'){
error_callback = custom_settings['error_callback'];
}
if(exception_callback==undefined || typeof(dajaxice_callback) != 'function'){
exception_callback = this.get_setting('default_exception_callback');
var send_data = 'argv='+encodeURIComponent(JSON.stringify(argv)),
oXMLHttpRequest = new XMLHttpRequest,
endpoint = '{% url 'dajaxice-endpoint' %}'+dajaxice_function+'/';
if(method == 'GET'){
endpoint = endpoint + '?' + send_data;
}
send_data.push('argv='+encodeURIComponent(JSON.stringify(argv)));
send_data = send_data.join('&');
var oXMLHttpRequest = new XMLHttpRequest;
oXMLHttpRequest.open('POST', '/{{DAJAXICE_URL_PREFIX}}/'+dajaxice_function+'/');
oXMLHttpRequest.open(method, endpoint);
oXMLHttpRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
oXMLHttpRequest.setRequestHeader("X-Requested-With", "XMLHttpRequest");
oXMLHttpRequest.setRequestHeader("X-CSRFToken",Dajaxice.get_cookie('csrftoken'));
oXMLHttpRequest.setRequestHeader("X-CSRFToken", Dajaxice.get_cookie('{{ dajaxice_config.django_settings.CSRF_COOKIE_NAME }}'));
oXMLHttpRequest.onreadystatechange = function() {
if (this.readyState == XMLHttpRequest.DONE) {
if(this.responseText == Dajaxice.EXCEPTION){
exception_callback();
if(this.responseText == Dajaxice.EXCEPTION || !(this.status in Dajaxice.valid_http_responses())){
error_callback();
}
else{
try{
dajaxice_callback(JSON.parse(this.responseText));
var response;
try {
response = JSON.parse(this.responseText);
}
catch(exception){
dajaxice_callback(this.responseText);
catch (exception) {
response = this.responseText;
}
dajaxice_callback(response);
}
}
}
oXMLHttpRequest.send(send_data);
if(method == 'POST'){
oXMLHttpRequest.send(send_data);
}
else{
oXMLHttpRequest.send();
}
return oXMLHttpRequest;
},
setup: function(settings)
{
this.settings = settings;
},
get_setting: function(key){
if(this.settings == undefined || this.settings[key] == undefined){
return this.default_settings[key];
return Dajaxice.default_settings[key];
}
return this.settings[key];
},
default_exception_callback: function(data){
alert('Something goes wrong');
}
};
Dajaxice.EXCEPTION = '{{ DAJAXICE_EXCEPTION }}';
Dajaxice.default_settings = {'default_exception_callback': Dajaxice.default_exception_callback}
valid_http_responses: function(){
return {200: null, 301: null, 302: null, 304: null}
},
EXCEPTION: '{{ dajaxice_config.DAJAXICE_EXCEPTION }}',
default_settings: {'default_exception_callback': function(){ console.log('Dajaxice: Something went wrong.')}}
};
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
*/
{% endcomment %}
{% if DAJAXICE_XMLHTTPREQUEST_JS_IMPORT %}
(function(){function b(){this._object=i?new i:new window.ActiveXObject("Microsoft.XMLHTTP");this._listeners=[]}function k(a){b.onreadystatechange&&b.onreadystatechange.apply(a);a.dispatchEvent({type:"readystatechange",bubbles:false,cancelable:false,timeStamp:new Date+0})}function p(a){var c=a.responseXML,d=a.responseText;if(h&&d&&c&&!c.documentElement&&a.getResponseHeader("Content-Type").match(/[^\/]+\/[^\+]+\+xml/)){c=new window.ActiveXObject("Microsoft.XMLDOM");c.async=false;c.validateOnParse=false;
c.loadXML(d)}if(c)if(h&&c.parseError!=0||!c.documentElement||c.documentElement&&c.documentElement.tagName=="parsererror")return null;return c}function o(a){try{a.responseText=a._object.responseText}catch(c){}try{a.responseXML=p(a._object)}catch(d){}try{a.status=a._object.status}catch(g){}try{a.statusText=a._object.statusText}catch(e){}}function l(a){a._object.onreadystatechange=new window.Function}var i=window.XMLHttpRequest,j=!!window.controllers,h=window.document.all&&!window.opera;if(j&&i.wrapped)b.wrapped=
i.wrapped;b.UNSENT=0;b.OPENED=1;b.HEADERS_RECEIVED=2;b.LOADING=3;b.DONE=4;b.prototype.readyState=b.UNSENT;b.prototype.responseText="";b.prototype.responseXML=null;b.prototype.status=0;b.prototype.statusText="";b.prototype.onreadystatechange=null;b.onreadystatechange=null;b.onopen=null;b.onsend=null;b.onabort=null;b.prototype.open=function(a,c,d,g,e){delete this._headers;if(arguments.length<3)d=true;this._async=d;var f=this,m=this.readyState,n;if(h&&d){n=function(){if(m!=b.DONE){l(f);f.abort()}};window.attachEvent("onunload",
n)}b.onopen&&b.onopen.apply(this,arguments);if(arguments.length>4)this._object.open(a,c,d,g,e);else arguments.length>3?this._object.open(a,c,d,g):this._object.open(a,c,d);if(!j&&!h){this.readyState=b.OPENED;k(this)}this._object.onreadystatechange=function(){if(!(j&&!d)){f.readyState=f._object.readyState;o(f);if(f._aborted)f.readyState=b.UNSENT;else{if(f.readyState==b.DONE){l(f);h&&d&&window.detachEvent("onunload",n)}m!=f.readyState&&k(f);m=f.readyState}}}};b.prototype.send=function(a){b.onsend&&b.onsend.apply(this,
arguments);if(a&&a.nodeType){a=window.XMLSerializer?(new window.XMLSerializer).serializeToString(a):a.xml;this._headers["Content-Type"]||this._object.setRequestHeader("Content-Type","application/xml")}this._object.send(a);if(j&&!this._async){this.readyState=b.OPENED;for(o(this);this.readyState<b.DONE;){this.readyState++;k(this);if(this._aborted)return}}};b.prototype.abort=function(){b.onabort&&b.onabort.apply(this,arguments);if(this.readyState>b.UNSENT)this._aborted=true;this._object.abort();l(this)};
b.prototype.getAllResponseHeaders=function(){return this._object.getAllResponseHeaders()};b.prototype.getResponseHeader=function(a){return this._object.getResponseHeader(a)};b.prototype.setRequestHeader=function(a,c){if(!this._headers)this._headers={};this._headers[a]=c;return this._object.setRequestHeader(a,c)};b.prototype.addEventListener=function(a,c,d){for(var g=0,e;e=this._listeners[g];g++)if(e[0]==a&&e[1]==c&&e[2]==d)return;this._listeners.push([a,c,d])};b.prototype.removeEventListener=function(a,
c,d){for(var g=0,e;e=this._listeners[g];g++)if(e[0]==a&&e[1]==c&&e[2]==d)break;e&&this._listeners.splice(g,1)};b.prototype.dispatchEvent=function(a){a={type:a.type,target:this,currentTarget:this,eventPhase:2,bubbles:a.bubbles,cancelable:a.cancelable,timeStamp:a.timeStamp,stopPropagation:function(){},preventDefault:function(){},initEvent:function(){}};if(a.type=="readystatechange"&&this.onreadystatechange)(this.onreadystatechange.handleEvent||this.onreadystatechange).apply(this,[a]);for(var c=0,d;d=
this._listeners[c];c++)if(d[0]==a.type&&!d[2])(d[1].handleEvent||d[1]).apply(this,[a])};b.prototype.toString=function(){return"[object XMLHttpRequest]"};b.toString=function(){return"[XMLHttpRequest]"};if(!window.Function.prototype.apply)window.Function.prototype.apply=function(a,c){c||(c=[]);a.__func=this;a.__func(c[0],c[1],c[2],c[3],c[4]);delete a.__func};window.XMLHttpRequest=b})();
{% if dajaxice_config.DAJAXICE_XMLHTTPREQUEST_JS_IMPORT %}
(function(){function n(){this._object=h&&!p?new h:new window.ActiveXObject("Microsoft.XMLHTTP");this._listeners=[]}function a(){return new n}function j(b){a.onreadystatechange&&a.onreadystatechange.apply(b);b.dispatchEvent({type:"readystatechange",bubbles:!1,cancelable:!1,timeStamp:new Date+0})}function o(b){try{b.responseText=b._object.responseText}catch(a){}try{var d;var g=b._object,c=g.responseXML,f=g.responseText;i&&(f&&c&&!c.documentElement&&g.getResponseHeader("Content-Type").match(/[^\/]+\/[^\+]+\+xml/))&&
(c=new window.ActiveXObject("Microsoft.XMLDOM"),c.async=!1,c.validateOnParse=!1,c.loadXML(f));d=c&&(i&&0!==c.parseError||!c.documentElement||c.documentElement&&"parsererror"==c.documentElement.tagName)?null:c;b.responseXML=d}catch(h){}try{b.status=b._object.status}catch(k){}try{b.statusText=b._object.statusText}catch(j){}}function l(b){b._object.onreadystatechange=new window.Function}var h=window.XMLHttpRequest,m=!!window.controllers,i=window.document.all&&!window.opera,p=i&&window.navigator.userAgent.match(/MSIE 7.0/);
a.prototype=n.prototype;m&&h.wrapped&&(a.wrapped=h.wrapped);a.UNSENT=0;a.OPENED=1;a.HEADERS_RECEIVED=2;a.LOADING=3;a.DONE=4;a.prototype.readyState=a.UNSENT;a.prototype.responseText="";a.prototype.responseXML=null;a.prototype.status=0;a.prototype.statusText="";a.prototype.priority="NORMAL";a.prototype.onreadystatechange=null;a.onreadystatechange=null;a.onopen=null;a.onsend=null;a.onabort=null;a.prototype.open=function(b,e,d,g,c){delete this._headers;arguments.length<3&&(d=true);this._async=d;var f=
this,h=this.readyState,k=null;if(i&&d){k=function(){if(h!=a.DONE){l(f);f.abort()}};window.attachEvent("onunload",k)}a.onopen&&a.onopen.apply(this,arguments);arguments.length>4?this._object.open(b,e,d,g,c):arguments.length>3?this._object.open(b,e,d,g):this._object.open(b,e,d);this.readyState=a.OPENED;j(this);this._object.onreadystatechange=function(){if(!m||d){f.readyState=f._object.readyState;o(f);if(f._aborted)f.readyState=a.UNSENT;else if(f.readyState==a.DONE){delete f._data;l(f);i&&d&&window.detachEvent("onunload",
k);h!=f.readyState&&j(f);h=f.readyState}}}};a.prototype.send=function(b){a.onsend&&a.onsend.apply(this,arguments);arguments.length||(b=null);if(b&&b.nodeType){b=window.XMLSerializer?(new window.XMLSerializer).serializeToString(b):b.xml;this._headers["Content-Type"]||this._object.setRequestHeader("Content-Type","application/xml")}this._data=b;a:{this._object.send(this._data);if(m&&!this._async){this.readyState=a.OPENED;for(o(this);this.readyState<a.DONE;){this.readyState++;j(this);if(this._aborted)break a}}}};
a.prototype.abort=function(){a.onabort&&a.onabort.apply(this,arguments);if(this.readyState>a.UNSENT)this._aborted=true;this._object.abort();l(this);this.readyState=a.UNSENT;delete this._data};a.prototype.getAllResponseHeaders=function(){return this._object.getAllResponseHeaders()};a.prototype.getResponseHeader=function(b){return this._object.getResponseHeader(b)};a.prototype.setRequestHeader=function(b,a){if(!this._headers)this._headers={};this._headers[b]=a;return this._object.setRequestHeader(b,
a)};a.prototype.addEventListener=function(a,e,d){for(var g=0,c;c=this._listeners[g];g++)if(c[0]==a&&c[1]==e&&c[2]==d)return;this._listeners.push([a,e,d])};a.prototype.removeEventListener=function(a,e,d){for(var g=0,c;c=this._listeners[g];g++)if(c[0]==a&&c[1]==e&&c[2]==d)break;c&&this._listeners.splice(g,1)};a.prototype.dispatchEvent=function(a){a={type:a.type,target:this,currentTarget:this,eventPhase:2,bubbles:a.bubbles,cancelable:a.cancelable,timeStamp:a.timeStamp,stopPropagation:function(){},preventDefault:function(){},
initEvent:function(){}};a.type=="readystatechange"&&this.onreadystatechange&&(this.onreadystatechange.handleEvent||this.onreadystatechange).apply(this,[a]);for(var e=0,d;d=this._listeners[e];e++)d[0]==a.type&&!d[2]&&(d[1].handleEvent||d[1]).apply(this,[a])};a.prototype.toString=function(){return"[object XMLHttpRequest]"};a.toString=function(){return"[XMLHttpRequest]"};window.Function.prototype.apply||(window.Function.prototype.apply=function(a,e){e||(e=[]);a.__func=this;a.__func(e[0],e[1],e[2],e[3],
e[4]);delete a.__func});window.XMLHttpRequest=a})();
{% endif %}
{% comment %}
@ -117,12 +134,12 @@ this._listeners[c];c++)if(d[0]==a.type&&!d[2])(d[1].handleEvent||d[1]).apply(thi
I hope that in the future this code won't be neccessary, but today all browsers doesn't supports JSON.stringify().
*/
{% endcomment %}
{% if DAJAXICE_JSON2_JS_IMPORT %}
if(!this.JSON)this.JSON={};
(function(){function k(a){return a<10?"0"+a:a}function n(a){o.lastIndex=0;return o.test(a)?'"'+a.replace(o,function(c){var d=q[c];return typeof d==="string"?d:"\\u"+("0000"+c.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+a+'"'}function l(a,c){var d,f,i=g,e,b=c[a];if(b&&typeof b==="object"&&typeof b.toJSON==="function")b=b.toJSON(a);if(typeof j==="function")b=j.call(c,a,b);switch(typeof b){case "string":return n(b);case "number":return isFinite(b)?String(b):"null";case "boolean":case "null":return String(b);case "object":if(!b)return"null";
g+=m;e=[];if(Object.prototype.toString.apply(b)==="[object Array]"){f=b.length;for(a=0;a<f;a+=1)e[a]=l(a,b)||"null";c=e.length===0?"[]":g?"[\n"+g+e.join(",\n"+g)+"\n"+i+"]":"["+e.join(",")+"]";g=i;return c}if(j&&typeof j==="object"){f=j.length;for(a=0;a<f;a+=1){d=j[a];if(typeof d==="string")if(c=l(d,b))e.push(n(d)+(g?": ":":")+c)}}else for(d in b)if(Object.hasOwnProperty.call(b,d))if(c=l(d,b))e.push(n(d)+(g?": ":":")+c);c=e.length===0?"{}":g?"{\n"+g+e.join(",\n"+g)+"\n"+i+"}":"{"+e.join(",")+"}";
g=i;return c}}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+k(this.getUTCMonth()+1)+"-"+k(this.getUTCDate())+"T"+k(this.getUTCHours())+":"+k(this.getUTCMinutes())+":"+k(this.getUTCSeconds())+"Z":null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(){return this.valueOf()}}var p=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
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 %}
{% if dajaxice_config.DAJAXICE_JSON2_JS_IMPORT %}
var JSON;JSON||(JSON={});
(function(){function k(a){return 10>a?"0"+a:a}function o(a){p.lastIndex=0;return p.test(a)?'"'+a.replace(p,function(a){var c=r[a];return"string"===typeof c?c:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+a+'"'}function m(a,j){var c,d,h,n,g=e,f,b=j[a];b&&("object"===typeof b&&"function"===typeof b.toJSON)&&(b=b.toJSON(a));"function"===typeof i&&(b=i.call(j,a,b));switch(typeof b){case "string":return o(b);case "number":return isFinite(b)?String(b):"null";case "boolean":case "null":return String(b);case "object":if(!b)return"null";
e+=l;f=[];if("[object Array]"===Object.prototype.toString.apply(b)){n=b.length;for(c=0;c<n;c+=1)f[c]=m(c,b)||"null";h=0===f.length?"[]":e?"[\n"+e+f.join(",\n"+e)+"\n"+g+"]":"["+f.join(",")+"]";e=g;return h}if(i&&"object"===typeof i){n=i.length;for(c=0;c<n;c+=1)"string"===typeof i[c]&&(d=i[c],(h=m(d,b))&&f.push(o(d)+(e?": ":":")+h))}else for(d in b)Object.prototype.hasOwnProperty.call(b,d)&&(h=m(d,b))&&f.push(o(d)+(e?": ":":")+h);h=0===f.length?"{}":e?"{\n"+e+f.join(",\n"+e)+"\n"+g+"}":"{"+f.join(",")+
"}";e=g;return h}}"function"!==typeof Date.prototype.toJSON&&(Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+k(this.getUTCMonth()+1)+"-"+k(this.getUTCDate())+"T"+k(this.getUTCHours())+":"+k(this.getUTCMinutes())+":"+k(this.getUTCSeconds())+"Z":null},String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(){return this.valueOf()});var q=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
p=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,e,l,r={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},i;"function"!==typeof JSON.stringify&&(JSON.stringify=function(a,j,c){var d;l=e="";if(typeof c==="number")for(d=0;d<c;d=d+1)l=l+" ";else typeof c==="string"&&(l=c);if((i=j)&&typeof j!=="function"&&(typeof j!=="object"||typeof j.length!=="number"))throw Error("JSON.stringify");return m("",{"":a})});
"function"!==typeof JSON.parse&&(JSON.parse=function(a,e){function c(a,d){var g,f,b=a[d];if(b&&typeof b==="object")for(g in b)if(Object.prototype.hasOwnProperty.call(b,g)){f=c(b,g);f!==void 0?b[g]=f:delete b[g]}return e.call(a,d,b)}var d,a=String(a);q.lastIndex=0;q.test(a)&&(a=a.replace(q,function(a){return"\\u"+("0000"+a.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,""))){d=eval("("+a+")");return typeof e==="function"?c({"":d},""):d}throw new SyntaxError("JSON.parse");})})();
{% endif %}

View file

@ -1,16 +0,0 @@
{{ module.name }}: {
{% for function in module.functions %}
{% if function.doc and DAJAXICE_JS_DOCSTRINGS %}/* {{ function.doc|default:'' }}*/ {% endif %}
{{ function.name }}: function(callback_function, argv, exception_callback){
Dajaxice.call('{{function.get_callable_path}}', callback_function, argv, exception_callback);
}{% if not forloop.last %},{% endif %}
{% endfor %}
{% for sub_module in module.sub_modules %}
{% with "dajaxice/dajaxice_core_loop.js" as filename %}
{% with sub_module as module %}
{% include filename %}
{% endwith %}
{% endwith %}
{% endfor %}
}{% if not forloop.last %},{% endif %}

View file

@ -1,5 +1,5 @@
{% for function_name, function in module.functions.items %}
{{ function_name }}: function(callback_function, argv, custom_settings){
Dajaxice.call('{{ function.name }}', '{{ function.method }}', callback_function, argv, custom_settings);
}{% if not forloop.last or top %},{% endif %}
return Dajaxice.call('{{ function.name }}', '{{ function.method }}', callback_function, argv, custom_settings);
}{% if not forloop.last or top or module.submodules %},{% endif %}
{% endfor %}

View file

@ -1 +0,0 @@
<script src="/{{ DAJAXICE_MEDIA_PREFIX }}/dajaxice.core.js" type="text/javascript" charset="utf-8"></script>

View file

@ -1,8 +1,11 @@
{{ name }}: {
{% include "dajaxice/dajaxice_function_loop.js" %}
{% with parent_foorloop=forloop %}
{% for name, sub_module in module.submodules.items %}
{% with filename="dajaxice/dajaxice_module_loop.js" module=sub_module %}
{% include filename %}
{% endwith %}
{% if not forloop.last %},{% endif %}
{% endfor %}
}{% if not forloop.last %},{% endif %}
}
{% endwith %}

View file

@ -1,42 +1,35 @@
#----------------------------------------------------------------------
# Copyright (c) 2009-2011 Benito Jorge Bastida
# All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# o Redistributions of source code must retain the above copyright
# notice, this list of conditions, and the disclaimer that follows.
#
# o Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# o Neither the name of Digital Creations nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
# IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
# CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.
#----------------------------------------------------------------------
import logging
from django import template
from dajaxice.core import DajaxiceRequest
from django.middleware.csrf import get_token
from django.conf import settings
from django.core.files.storage import get_storage_class
staticfiles_storage = get_storage_class(settings.STATICFILES_STORAGE)()
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()}
@register.simple_tag(takes_context=True)
def dajaxice_js_import(context, csrf=True):
""" Return the js script tag for the dajaxice.core.js file
If the csrf argument is present and it's ``nocsrf`` dajaxice will not
try to mark the request as if it need the csrf token. By default use
the dajaxice_js_import template tag will make django set the csrftoken
cookie on the current request."""
csrf = csrf != 'nocsrf'
request = context.get('request')
if request and csrf:
get_token(request)
elif csrf:
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.")
url = staticfiles_storage.url('dajaxice/dajaxice.core.js')
return '<script src="%s" type="text/javascript" charset="utf-8"></script>' % url

View file

@ -1,46 +1,114 @@
#----------------------------------------------------------------------
# Copyright (c) 2009-2011 Benito Jorge Bastida
# All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# o Redistributions of source code must retain the above copyright
# notice, this list of conditions, and the disclaimer that follows.
#
# o Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# o Neither the name of Digital Creations nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
# IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
# CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.
#----------------------------------------------------------------------
import os
import unittest
from django.test import TestCase
from django.conf import settings
from dajaxice.exceptions import FunctionNotCallableError, DajaxiceImportError
from dajaxice.core import DajaxiceRequest
from dajaxice.core.Dajaxice import Dajaxice, DajaxiceModule, DajaxiceFunction
from dajaxice.core import dajaxice_functions
from dajaxice.core import DajaxiceConfig
from dajaxice.core.Dajaxice import DajaxiceModule, DajaxiceFunction, Dajaxice
from dajaxice.exceptions import FunctionNotCallableError
class DajaxiceModuleTest(TestCase):
def setUp(self):
self.module = DajaxiceModule()
def test_constructor(self):
self.assertEqual(self.module.functions, {})
self.assertEqual(self.module.submodules, {})
def test_add_function(self):
function = lambda x: x
self.module.add('test', function)
self.assertEqual(self.module.functions, {'test': function})
self.assertEqual(self.module.submodules, {})
self.module.add('foo.bar', function)
self.assertEqual(self.module.functions, {'test': function})
self.assertEqual(self.module.submodules.keys(), ['foo'])
self.assertEqual(self.module.submodules['foo'].functions, {'bar': function})
class DajaxiceFunctionTest(TestCase):
def test_constructor(self):
class CalledEception(Exception):
pass
def callback():
raise CalledEception
function = DajaxiceFunction(callback, 'foo', 'POST')
self.assertEqual(function.function, callback)
self.assertEqual(function.name, 'foo')
self.assertEqual(function.method, 'POST')
self.assertRaises(CalledEception, function.call)
class DajaxiceTest(TestCase):
def setUp(self):
self.dajaxice = Dajaxice()
self.function = lambda x: x
def test_constructor(self):
self.assertEqual(self.dajaxice._registry, {})
def test_register(self):
self.dajaxice.register(self.function, 'foo')
self.assertTrue('foo' in self.dajaxice._registry)
self.assertEqual(type(self.dajaxice._registry['foo']), DajaxiceFunction)
def bar_function():
return
self.dajaxice.register(bar_function)
self.assertTrue('dajaxice.tests.bar_function' in self.dajaxice._registry)
self.assertEqual(type(self.dajaxice._registry['dajaxice.tests.bar_function']), DajaxiceFunction)
def test__is_callable(self):
self.dajaxice.register(self.function, 'foo')
self.dajaxice.register(self.function, 'bar', method='GET')
self.assertTrue(self.dajaxice.is_callable('foo', 'POST'))
self.assertTrue(self.dajaxice.is_callable('bar', 'GET'))
self.assertFalse(self.dajaxice.is_callable('foo', 'GET'))
self.assertFalse(self.dajaxice.is_callable('bar', 'POST'))
self.assertFalse(self.dajaxice.is_callable('test', 'POST'))
self.assertFalse(self.dajaxice.is_callable('test', 'GET'))
def test_clean_method(self):
self.assertEqual(self.dajaxice.clean_method('post'), 'POST')
self.assertEqual(self.dajaxice.clean_method('get'), 'GET')
self.assertEqual(self.dajaxice.clean_method('POST'), 'POST')
self.assertEqual(self.dajaxice.clean_method('GET'), 'GET')
self.assertEqual(self.dajaxice.clean_method('other'), 'POST')
def test_modules(self):
self.dajaxice.register(self.function, 'foo')
self.dajaxice.register(self.function, 'bar')
self.assertEqual(type(self.dajaxice.modules), DajaxiceModule)
self.assertEqual(self.dajaxice.modules.functions.keys(), ['foo', 'bar'])
class DajaxiceConfigTest(TestCase):
def setUp(self):
self.config = DajaxiceConfig()
def test_defaults(self):
self.assertTrue(self.config.DAJAXICE_XMLHTTPREQUEST_JS_IMPORT)
self.assertTrue(self.config.DAJAXICE_JSON2_JS_IMPORT)
self.assertEqual(self.config.DAJAXICE_EXCEPTION, 'DAJAXICE_EXCEPTION')
self.assertEqual(self.config.DAJAXICE_MEDIA_PREFIX, 'dajaxice')
dajaxice_url = r'^%s/' % self.config.DAJAXICE_MEDIA_PREFIX
self.assertEqual(self.config.dajaxice_url, dajaxice_url)
self.assertEqual(type(self.config.modules), DajaxiceModule)
class DjangoIntegrationTest(TestCase):
@ -48,127 +116,50 @@ class DjangoIntegrationTest(TestCase):
urls = 'dajaxice.tests.urls'
def setUp(self):
settings.DAJAXICE_MEDIA_PREFIX = "dajaxice"
settings.DAJAXICE_DEBUG = False
settings.INSTALLED_APPS += ('dajaxice.tests', 'dajaxice.tests.submodules',)
os.environ['DJANGO_SETTINGS_MODULE'] = 'dajaxice'
settings.INSTALLED_APPS += ('dajaxice.tests',)
def test_calling_not_registered_function(self):
self.failUnlessRaises(FunctionNotCallableError, self.client.post, '/dajaxice/dajaxice.tests.this_function_not_exist/', {'callback': 'my_callback'})
self.failUnlessRaises(FunctionNotCallableError, self.client.post, '/dajaxice/dajaxice.tests.this_function_not_exist/')
def test_calling_registered_function(self):
response = self.client.post('/dajaxice/dajaxice.tests.test_foo/', {'callback': 'my_callback'})
response = self.client.post('/dajaxice/dajaxice.tests.test_foo/')
self.failUnlessEqual(response.status_code, 200)
self.failUnlessEqual(response.content, 'my_callback()')
self.failUnlessEqual(response.content, '{"foo": "bar"}')
def test_calling_registered_function_with_params(self):
response = self.client.post('/dajaxice/dajaxice.tests.test_foo_with_params/', {'callback': 'my_callback', 'argv': '{"param1":"value1"}'})
response = self.client.post('/dajaxice/dajaxice.tests.test_foo_with_params/', {'argv': '{"param1":"value1"}'})
self.failUnlessEqual(response.status_code, 200)
self.failUnlessEqual(response.content, 'my_callback("value1")')
self.failUnlessEqual(response.content, '{"param1": "value1"}')
def test_bad_function(self):
response = self.client.post('/dajaxice/dajaxice.tests.test_ajax_exception/', {'callback': 'my_callback'})
response = self.client.post('/dajaxice/dajaxice.tests.test_ajax_exception/')
self.failUnlessEqual(response.status_code, 200)
self.failUnlessEqual(response.content, "my_callback('DAJAXICE_EXCEPTION')")
self.failUnlessEqual(response.content, "DAJAXICE_EXCEPTION")
def test_is_callable(self):
def test_get_register(self):
dr = DajaxiceRequest(None, 'dajaxice.tests.test_registered_function')
self.failUnless(dr._is_callable())
response = self.client.get('/dajaxice/dajaxice.tests.test_get_register/')
dr = DajaxiceRequest(None, 'dajaxice.tests.test_ajax_not_registered')
self.failIf(dr._is_callable())
self.failUnlessEqual(response.status_code, 200)
self.failUnlessEqual(response.content, '{"foo": "user"}')
def test_get_js_functions(self):
def test_get_custom_name_register(self):
js_functions = DajaxiceRequest.get_js_functions()
response = self.client.get('/dajaxice/get_user_data/')
functions = [DajaxiceFunction('test_registered_function', 'dajaxice.tests.ajax.test_registered_function'),
DajaxiceFunction('test_string', 'dajaxice.tests.ajax.test_string'),
DajaxiceFunction('test_ajax_exception', 'dajaxice.tests.ajax.test_ajax_exception'),
DajaxiceFunction('test_foo', 'dajaxice.tests.ajax.test_foo'),
DajaxiceFunction('test_foo_with_params', 'dajaxice.tests.ajax.test_foo_with_params'),
DajaxiceFunction('test_submodule_registered_function', 'dajaxice.tests.submodules.ajax.test_submodule_registered_function')]
self.failUnlessEqual(response.status_code, 200)
self.failUnlessEqual(response.content, '{"bar": "user"}')
callables = [f.path for f in functions]
def test_multi_register(self):
self.failUnlessEqual(len(js_functions), 1)
self.failUnlessEqual(dajaxice_functions._callable, callables)
response = self.client.get('/dajaxice/get_multi/')
self.failUnlessEqual(response.status_code, 200)
self.failUnlessEqual(response.content, '{"foo": "multi"}')
sub = js_functions[0]
self.failUnlessEqual(len(sub.sub_modules), 1)
self.failUnlessEqual(len(sub.functions), 0)
self.failUnlessEqual(sub.name, 'dajaxice')
sub = js_functions[0].sub_modules[0]
self.failUnlessEqual(len(sub.sub_modules), 1)
self.failUnlessEqual(len(sub.functions), 5)
self.failUnlessEqual(sub.functions, functions[:-1])
self.failUnlessEqual(sub.name, 'tests')
sub = js_functions[0].sub_modules[0].sub_modules[0]
self.failUnlessEqual(len(sub.sub_modules), 0)
self.failUnlessEqual(len(sub.functions), 1)
self.failUnlessEqual(sub.functions, functions[-1:])
self.failUnlessEqual(sub.name, 'submodules')
def test_get_ajax_function(self):
# Test modern Import with a real ajax function
dr = DajaxiceRequest(None, 'dajaxice.tests.test_foo')
function = dr._modern_get_ajax_function()
self.failUnless(hasattr(function, '__call__'))
# Test modern Import without a real ajax function
dr = DajaxiceRequest(None, 'dajaxice.tests.test_foo2')
self.failUnlessRaises(DajaxiceImportError, dr._modern_get_ajax_function)
class DajaxiceFunctionTest(unittest.TestCase):
def setUp(self):
self.function = DajaxiceFunction('my_function', 'module.submodule.foo.ajax')
def test_constructor(self):
self.failUnlessEqual(self.function.name, 'my_function')
self.failUnlessEqual(self.function.path, 'module.submodule.foo.ajax')
def test_get_callable_path(self):
self.failUnlessEqual(self.function.get_callable_path(), 'module.submodule.foo.my_function')
class DajaxiceModuleTest(unittest.TestCase):
def setUp(self):
self.module = DajaxiceModule('module.submodule.foo.ajax'.split('.'))
def test_constructor(self):
self.failUnlessEqual(self.module.functions, [])
self.failUnlessEqual(self.module.name, 'module')
self.failUnlessEqual(len(self.module.sub_modules), 1)
def test_add_function(self):
function = DajaxiceFunction('my_function', 'module.submodule.foo.ajax')
self.failUnlessEqual(len(self.module.functions), 0)
self.module.add_function(function)
self.failUnlessEqual(len(self.module.functions), 1)
def test_has_sub_modules(self):
self.failUnlessEqual(self.module.has_sub_modules(), True)
def test_exist_submodule(self):
self.failUnlessEqual(self.module.exist_submodule('submodule'), 0)
self.assertFalse(self.module.exist_submodule('other'))
self.module.add_submodule('other.foo'.split('.'))
self.failUnlessEqual(self.module.exist_submodule('other'), 1)
def test_add_submodule(self):
self.failUnlessEqual(len(self.module.sub_modules), 1)
self.module.add_submodule('other.foo'.split('.'))
self.failUnlessEqual(len(self.module.sub_modules), 2)
self.assertTrue(type(self.module.sub_modules[1]), DajaxiceModule)
response = self.client.post('/dajaxice/post_multi/')
self.failUnlessEqual(response.status_code, 200)
self.failUnlessEqual(response.content, '{"foo": "multi"}')

View file

@ -1,61 +1,43 @@
#----------------------------------------------------------------------
# Copyright (c) 2009-2011 Benito Jorge Bastida
# All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# o Redistributions of source code must retain the above copyright
# notice, this list of conditions, and the disclaimer that follows.
#
# o Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# o Neither the name of Digital Creations nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
# IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
# CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.
#----------------------------------------------------------------------
from django.utils import simplejson
from dajaxice.core import dajaxice_functions
import json
from dajaxice.decorators import dajaxice_register
@dajaxice_register
def test_registered_function(request):
return ""
dajaxice_functions.register(test_registered_function)
@dajaxice_register
def test_string(request):
return simplejson.dumps({'string': 'hello world'})
dajaxice_functions.register(test_string)
return json.dumps({'string': 'hello world'})
@dajaxice_register
def test_ajax_exception(request):
raise Exception()
return
dajaxice_functions.register(test_ajax_exception)
@dajaxice_register
def test_foo(request):
return ""
dajaxice_functions.register(test_foo)
return json.dumps({'foo': 'bar'})
@dajaxice_register
def test_foo_with_params(request, param1):
return simplejson.dumps(param1)
dajaxice_functions.register(test_foo_with_params)
return json.dumps({'param1': param1})
@dajaxice_register(method='GET')
def test_get_register(request):
return json.dumps({'foo': 'user'})
@dajaxice_register(method='GET', name="get_user_data")
def test_get_with_name_register(request):
return json.dumps({'bar': 'user'})
@dajaxice_register(method='GET', name="get_multi")
@dajaxice_register(name="post_multi")
def test_multi_register(request):
return json.dumps({'foo': 'multi'})

View file

@ -1,40 +0,0 @@
#----------------------------------------------------------------------
# Copyright (c) 2009-2011 Benito Jorge Bastida
# All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# o Redistributions of source code must retain the above copyright
# notice, this list of conditions, and the disclaimer that follows.
#
# o Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# o Neither the name of Digital Creations nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
# IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
# CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.
#----------------------------------------------------------------------
from dajaxice.core import dajaxice_functions
def test_submodule_registered_function(request):
return ""
dajaxice_functions.register(test_submodule_registered_function)

View file

@ -1,44 +1,10 @@
#----------------------------------------------------------------------
# Copyright (c) 2009-2011 Benito Jorge Bastida
# All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# o Redistributions of source code must retain the above copyright
# notice, this list of conditions, and the disclaimer that follows.
#
# o Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# o Neither the name of Digital Creations nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
# IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
# CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.
#----------------------------------------------------------------------
from django.conf.urls import *
from django.conf import settings
from dajaxice.core import dajaxice_autodiscover
from django.conf.urls.defaults import *
from dajaxice.core import dajaxice_autodiscover, dajaxice_config
dajaxice_autodiscover()
urlpatterns = patterns('',
#Dajaxice URLS
(r'^%s/' % settings.DAJAXICE_MEDIA_PREFIX, include('dajaxice.urls')),
url(dajaxice_config.dajaxice_url, include('dajaxice.urls')),
)

View file

@ -1,39 +1,7 @@
#----------------------------------------------------------------------
# Copyright (c) 2009-2011 Benito Jorge Bastida
# All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# o Redistributions of source code must retain the above copyright
# notice, this list of conditions, and the disclaimer that follows.
#
# o Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# o Neither the name of Digital Creations nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
# IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
# CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.
#----------------------------------------------------------------------
from django.conf.urls import *
from .views import DajaxiceRequest
urlpatterns = patterns('',
url(r'^dajaxice.core.js$', 'dajaxice.views.js_core'),
url(r'^(.*)/$', 'dajaxice.views.dajaxice_request'),)
urlpatterns = patterns('dajaxice.views',
url(r'^(.+)/$', DajaxiceRequest.as_view(), name='dajaxice-call-endpoint'),
url(r'', DajaxiceRequest.as_view(), name='dajaxice-endpoint'),
)

View file

@ -1,50 +1,8 @@
#----------------------------------------------------------------------
# Copyright (c) 2009-2011 Benito Jorge Bastida
# All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# o Redistributions of source code must retain the above copyright
# notice, this list of conditions, and the disclaimer that follows.
#
# o Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# o Neither the name of Digital Creations nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
# IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
# CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.
#----------------------------------------------------------------------
from django.http import QueryDict
def deserialize_form(data):
"""
Create a new QueryDict from a serialized form.
"""
from django.http import QueryDict
data = QueryDict(query_string=unicode(data).encode('utf-8'))
return data
def simple_import_module(name):
"""
Reduced version of import_module
"""
import sys
__import__(name)
return sys.modules[name]
return QueryDict(query_string=unicode(data).encode('utf-8'))

View file

@ -1,62 +1,59 @@
#----------------------------------------------------------------------
# Copyright (c) 2009-2011 Benito Jorge Bastida
# All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# o Redistributions of source code must retain the above copyright
# notice, this list of conditions, and the disclaimer that follows.
#
# o Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# o Neither the name of Digital Creations nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
# IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
# CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.
#----------------------------------------------------------------------
import logging, json
from django.shortcuts import render_to_response
from django.views.decorators.cache import cache_control
from django.conf import settings
from django.views.generic.base import View
from django.http import HttpResponse, Http404
from dajaxice.core import DajaxiceRequest
from dajaxice.exceptions import FunctionNotCallableError
from dajaxice.core import dajaxice_functions, dajaxice_config
log = logging.getLogger('dajaxice')
def dajaxice_request(request, call):
def safe_dict(d):
"""
dajaxice_request
Uses DajaxRequest to handle dajax request.
Return the apropiate json according app_name and method.
Recursively clone json structure with UTF-8 dictionary keys
http://www.gossamer-threads.com/lists/python/bugs/684379
"""
return DajaxiceRequest(request, call).process()
if isinstance(d, dict):
return dict([(k.encode('utf-8'), safe_dict(v)) for k, v in d.iteritems()])
elif isinstance(d, list):
return [safe_dict(x) for x in d]
else:
return d
@cache_control(max_age=DajaxiceRequest.get_cache_control())
def js_core(request):
"""
Return the dajax JS code according settings.DAJAXICE_FUNCTIONS
registered functions.
"""
data = {'dajaxice_js_functions': DajaxiceRequest.get_js_functions(),
'DAJAXICE_URL_PREFIX': DajaxiceRequest.get_media_prefix(),
'DAJAXICE_XMLHTTPREQUEST_JS_IMPORT': DajaxiceRequest.get_xmlhttprequest_js_import(),
'DAJAXICE_JSON2_JS_IMPORT': DajaxiceRequest.get_json2_js_import(),
'DAJAXICE_EXCEPTION': DajaxiceRequest.get_exception_message(),
'DAJAXICE_JS_DOCSTRINGS': DajaxiceRequest.get_js_docstrings()}
class DajaxiceRequest(View):
""" Handle all the dajaxice xhr requests. """
return render_to_response('dajaxice/dajaxice.core.js', data, mimetype="text/javascript")
def dispatch(self, request, name=None):
if not name:
raise Http404
# Check if the function is callable
if dajaxice_functions.is_callable(name, request.method):
function = dajaxice_functions.get(name)
data = getattr(request, function.method).get('argv', '')
# Clean the argv
if data != 'undefined':
try:
data = safe_dict(json.loads(data))
except Exception:
data = {}
else:
data = {}
# Call the function. If something goes wrong, handle the Exception
try:
response = function.call(request, **data)
except Exception:
if settings.DEBUG:
raise
response = dajaxice_config.DAJAXICE_EXCEPTION
return HttpResponse(response, mimetype="application/x-json")
else:
raise FunctionNotCallableError(name)

View file

@ -14,6 +14,12 @@ from ietf.meeting.models import TimeSlot, Session, Schedule, Room, Constraint
import debug
def dajaxice_core_js(request):
# this is a slightly weird hack to get, we seem to need this because
# we're not using the built-in static files support
from dajaxice.finders import DajaxiceStorage
return HttpResponse(DajaxiceStorage().dajaxice_core_js(), content_type="application/javascript")
@dajaxice_register
def readonly(request, meeting_num, schedule_id):
meeting = get_meeting(meeting_num)

View file

@ -63,6 +63,7 @@ urlpatterns = patterns('',
# Google webmaster tools verification url
(r'^googlea30ad1dacffb5e5b.html', TemplateView.as_view(template_name='googlea30ad1dacffb5e5b.html')),
(r'^%s/dajaxice.core.js' % settings.DAJAXICE_MEDIA_PREFIX, 'ietf.meeting.ajax.dajaxice_core_js'),
(r'^%s/' % settings.DAJAXICE_MEDIA_PREFIX, include('dajaxice.urls')),
)