# -*- coding: utf-8 -*- # vi:si:et:sw=4:sts=4:ts=4 from __future__ import division import os.path from os.path import join import re from datetime import datetime from urllib2 import unquote import mimetypes from django import forms from django.core.paginator import Paginator from django.contrib.auth.decorators import login_required from django.contrib.auth.models import User from django.db.models import Q, Avg, Count, Sum from django.http import HttpResponse, Http404 from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404, redirect from django.template import RequestContext from django.conf import settings from django.contrib.comments.forms import CommentForm from django.contrib.comments.models import Comment from django.contrib.comments.signals import comment_will_be_posted, comment_was_posted from django.contrib.contenttypes.models import ContentType from ox.utils import json from ox.django.decorators import login_required_json from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response from ox.django.http import HttpFileResponse import ox from actions import actions from user.models import get_user_json from django.views.decorators.csrf import csrf_exempt @csrf_exempt def api(request): if request.META['REQUEST_METHOD'] == "OPTIONS": response = render_to_json_response({'status': {'code': 200, 'text': 'use POST'}}) response['Access-Control-Allow-Origin'] = '*' return response if not 'action' in request.POST: methods = actions.keys() api = [] for f in sorted(methods): api.append({'name': f, 'doc': actions.doc(f).replace('\n', '
\n')}) context = RequestContext(request, {'api': api, 'sitename': settings.SITENAME}) return render_to_response('api.html', context) function = request.POST['action'] #FIXME: possible to do this in f #data = json.loads(request.POST['data']) f = actions.get(function, None) if f: response = f(request) else: response = render_to_json_response(json_response(status=400, text='Unknown function %s' % function)) response['Access-Control-Allow-Origin'] = '*' return response #def api_api(request): # ''' # returns list of all known api action # return {'status': {'code': int, 'text': string}, # 'data': {actions: ['api', 'hello', ...]}} # ''' # actions = globals().keys() # actions = map(lambda a: a[4:], filter(lambda a: a.startswith('api_'), actions)) # actions.sort() # ret = {} # #FIXME: set cache to False for login, logout, etc. # for a in actions: # ret[a] = { # 'cache': True # } # return render_to_json_response(json_response({'actions': ret})) #def api_apidoc(request): # ''' # returns array of actions with documentation # ''' # actions = globals().keys() # actions = map(lambda a: a[4:], filter(lambda a: a.startswith('api_'), actions)) # actions.sort() # docs = {} # for f in actions: # docs[f] = get_api_doc(f) # return render_to_json_response(json_response({'actions': docs})) def init(request): ''' return {'status': {'code': int, 'text': string}, 'data': {user: object}} ''' #data = json.loads(request.POST['data']) response = json_response({}) if request.user.is_authenticated(): response['data']['user'] = get_user_json(request.user) else: response['data']['user'] = {'name': 'Guest', 'group': 'guest', 'level': 'guest', 'preferences': {}} #FIXME: Get config definition out of here. response['data']['config'] = { 'site': { 'name': 'India Theatre Forum' } } return render_to_json_response(response) actions.register(init) def error(request): ''' trows 503 error ''' success = error_is_success return render_to_json_response({}) actions.register(error) def find(request): data = json.loads(request.POST['data']) # print json.dumps(data) model = getModel(data) response = json_response({}) l = model.get_list(data) if data.has_key('ids'): ids = data['ids'] else: ids = [] if data.has_key('range'): response['data']['items'] = l else: response['data']['items'] = len(l) response['data']['positions'] = _get_positions(ids, l) response['status'] = {'code': 200} return render_to_json_response(response) actions.register(find) def _get_positions(ids, l): ret = {} i = 0 for id in ids: for obj in l: if obj['id'] == id: ret[id] = i break i += 1 return ret def preview(request): data = json.loads(request.POST['data']) if not data.has_key('id'): return render_to_json_response({'status': {'code': 404}}) id = int(data['id']) model = getModel(data) response = json_response({}) response['status'] = {'code': 200} obj = get_object_or_404(model, pk=id) response['data'] = obj.preview_dict() response['template'] = getTemplate(data, "preview") return render_to_json_response(response) actions.register(preview) #FIXME: Generalize based on these two functions being the same. def info(request): ''' id: object id model: string, name of model module: string, name of module ''' data = json.loads(request.POST['data']) id = int(data['id']) model = getModel(data) response = json_response({}) response['status'] = {'code': 200} obj = get_object_or_404(model, pk=id) if model.hasComments: response['commentForm'] = _get_comment_form_initial(request, obj) response['comments'] = _get_comments(obj) response['data'] = obj.info_dict() response['template'] = getTemplate(data, "info") return render_to_json_response(response) actions.register(info) #obj: Django model instance - object for which to get comment form for. #Returns dict with content_type, object_id, security_hash, etc. #FIXME: put comments stuff somewhere def _get_comment_form_initial(request, obj): c = CommentForm(obj) return c.initial def _get_comments(obj): ret = [] content_type = ContentType.objects.get_for_model(obj) object_id = obj.id qset = Comment.objects.filter(content_type=content_type, object_pk=object_id) for q in qset: ret.append({ 'name': q.name, # 'date': q.submit_date, 'comment': q.comment }) return ret @login_required_json def addComment(request): ''' id module model comment content_type email name object_pk security_hash timestamp ''' data = json.loads(request.POST['data']) data.update({ 'name': request.user.username, 'email': request.user.email }) id = int(data['object_pk']) model = getModel(data) obj = get_object_or_404_json(model, pk=id) cf = CommentForm(obj, data=data) ret = json_response({}) if cf.is_valid(): comment = cf.get_comment_object() comment.user = request.user # Signal that the comment is about to be saved responses = comment_will_be_posted.send( sender = comment.__class__, comment = comment, request = request ) for (receiver, response) in responses: if response == False: return CommentPostBadRequest( "comment_will_be_posted receiver %r killed the comment" % receiver.__name__) # Save the comment and signal that it was saved comment.save() comment_was_posted.send( sender = comment.__class__, comment = comment, request = request ) ret['data'] = { id: comment.id } ret['status'] = {'code': 200} else: ret['status'] = {'code': 200} ret['errors'] = cf.errors return render_to_json_response(ret) actions.register(addComment) widgetMap = { 'TextInput': 'text', 'Textarea': 'textarea', 'Select': 'select' } def getAddItemForm(request): response = json_response({}) data = json.loads(request.POST['data']) model = getModel(data) # import pdb; pdb.set_trace() form = getForm(data) form_fields = [] for field in form.base_fields: name = field this = form.base_fields[field] widget = this.widget widgetClassName = type(widget).__name__ if hasattr(widget, "choices"): choices = [] for c in widget.choices: if c[0] == '': id = 0 else: id = c[0] choices.append({ 'id': id, 'title': c[1] }) else: choices = False js_widget = widgetMap.get(widgetClassName, "text") form_fields.append({ 'name': name, 'widget': js_widget, 'label': this.label, 'choices': choices }) response['data']['form'] = form_fields return render_to_json_response(response) actions.register(getAddItemForm) @login_required_json def addItem(request): response = json_response({}) data = json.loads(request.POST['data']) model = getModel(data) form = getForm(data) if form.is_valid(): m = model() for field in form.base_fields: m.__setattr__(field, form.cleaned_data[field]) m.save() response['data'] = {'id': m.id} else: response['errors'] = form.errors return render_to_json_response(response) actions.register(addItem) def getTemplate(data, tmpl_name): path = join(settings.PROJECT_PATH, "templates", data['module'], data['model'], tmpl_name + ".html") return open(path).read().strip() def getModel(data): module = __import__(data['module']) return module.models.__getattribute__(data['model']) #FIXME: BAAD Hack def getForm(data): module = __import__(data['module'] + ".forms") model = getModel(data) formStr = model.add_form return module.forms.__getattribute__(formStr) def get_api_doc(f): f = 'api_' + f import sys def trim(docstring): if not docstring: return '' # Convert tabs to spaces (following the normal Python rules) # and split into a list of lines: lines = docstring.expandtabs().splitlines() # Determine minimum indentation (first line doesn't count): indent = sys.maxint for line in lines[1:]: stripped = line.lstrip() if stripped: indent = min(indent, len(line) - len(stripped)) # Remove indentation (first line is special): trimmed = [lines[0].strip()] if indent < sys.maxint: for line in lines[1:]: trimmed.append(line[indent:].rstrip()) # Strip off trailing and leading blank lines: while trimmed and not trimmed[-1]: trimmed.pop() while trimmed and not trimmed[0]: trimmed.pop(0) # Return a single string: return '\n'.join(trimmed) return trim(globals()[f].__doc__) def apidoc(request): ''' this is used for online documentation at http://127.0.0.1:8000/api/ ''' functions = filter(lambda x: x.startswith('api_'), globals().keys()) api = [] for f in sorted(functions): api.append({ 'name': f[4:], 'doc': get_api_doc(f[4:]).replace('\n', '
\n') }) context = RequestContext(request, {'api': api, 'sitename': settings.SITENAME,}) return render_to_response('api.html', context) def jsdoc(request): ''' Used to document OxUI JS Widgets ''' context = RequestContext(request, {}) return render_to_response("jsdoc.html", context) ''' ajax html snapshots http://code.google.com/web/ajaxcrawling/docs/html-snapshot.html ''' def html_snapshot(request): fragment = unquote(request.GET['_escaped_fragment_']) url = request.build_absolute_uri('/ra') url = 'http://'+settings.URL response = HttpResponse('sorry, server side rendering for %s!#%s not yet implemented'%(url, fragment)) return response