1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-17 07:41:26 +00:00

add djangorestframework

This commit is contained in:
poet
2012-07-14 14:25:17 +08:00
parent 823b437091
commit f29db5b649
56 changed files with 8249 additions and 0 deletions

View File

@@ -0,0 +1,175 @@
from django.utils.encoding import smart_unicode
from django.utils.xmlutils import SimplerXMLGenerator
from django.core.urlresolvers import resolve
from django.conf import settings
from djangorestframework.compat import StringIO
import re
import xml.etree.ElementTree as ET
#def admin_media_prefix(request):
# """Adds the ADMIN_MEDIA_PREFIX to the request context."""
# return {'ADMIN_MEDIA_PREFIX': settings.ADMIN_MEDIA_PREFIX}
from mediatypes import media_type_matches, is_form_media_type
from mediatypes import add_media_type_param, get_media_type_params, order_by_precedence
MSIE_USER_AGENT_REGEX = re.compile(r'^Mozilla/[0-9]+\.[0-9]+ \([^)]*; MSIE [0-9]+\.[0-9]+[a-z]?;[^)]*\)(?!.* Opera )')
def as_tuple(obj):
"""
Given an object which may be a list/tuple, another object, or None,
return that object in list form.
IE:
If the object is already a list/tuple just return it.
If the object is not None, return it in a list with a single element.
If the object is None return an empty list.
"""
if obj is None:
return ()
elif isinstance(obj, list):
return tuple(obj)
elif isinstance(obj, tuple):
return obj
return (obj,)
def url_resolves(url):
"""
Return True if the given URL is mapped to a view in the urlconf, False otherwise.
"""
try:
resolve(url)
except Exception:
return False
return True
# From http://www.koders.com/python/fidB6E125C586A6F49EAC38992CF3AFDAAE35651975.aspx?s=mdef:xml
#class object_dict(dict):
# """object view of dict, you can
# >>> a = object_dict()
# >>> a.fish = 'fish'
# >>> a['fish']
# 'fish'
# >>> a['water'] = 'water'
# >>> a.water
# 'water'
# >>> a.test = {'value': 1}
# >>> a.test2 = object_dict({'name': 'test2', 'value': 2})
# >>> a.test, a.test2.name, a.test2.value
# (1, 'test2', 2)
# """
# def __init__(self, initd=None):
# if initd is None:
# initd = {}
# dict.__init__(self, initd)
#
# def __getattr__(self, item):
# d = self.__getitem__(item)
# # if value is the only key in object, you can omit it
# if isinstance(d, dict) and 'value' in d and len(d) == 1:
# return d['value']
# else:
# return d
#
# def __setattr__(self, item, value):
# self.__setitem__(item, value)
# From xml2dict
class XML2Dict(object):
def __init__(self):
pass
def _parse_node(self, node):
node_tree = {}
# Save attrs and text, hope there will not be a child with same name
if node.text:
node_tree = node.text
for (k,v) in node.attrib.items():
k,v = self._namespace_split(k, v)
node_tree[k] = v
#Save childrens
for child in node.getchildren():
tag, tree = self._namespace_split(child.tag, self._parse_node(child))
if tag not in node_tree: # the first time, so store it in dict
node_tree[tag] = tree
continue
old = node_tree[tag]
if not isinstance(old, list):
node_tree.pop(tag)
node_tree[tag] = [old] # multi times, so change old dict to a list
node_tree[tag].append(tree) # add the new one
return node_tree
def _namespace_split(self, tag, value):
"""
Split the tag '{http://cs.sfsu.edu/csc867/myscheduler}patients'
ns = http://cs.sfsu.edu/csc867/myscheduler
name = patients
"""
result = re.compile("\{(.*)\}(.*)").search(tag)
if result:
value.namespace, tag = result.groups()
return (tag, value)
def parse(self, file):
"""parse a xml file to a dict"""
f = open(file, 'r')
return self.fromstring(f.read())
def fromstring(self, s):
"""parse a string"""
t = ET.fromstring(s)
unused_root_tag, root_tree = self._namespace_split(t.tag, self._parse_node(t))
return root_tree
def xml2dict(input):
return XML2Dict().fromstring(input)
# Piston:
class XMLRenderer():
def _to_xml(self, xml, data):
if isinstance(data, (list, tuple)):
for item in data:
xml.startElement("list-item", {})
self._to_xml(xml, item)
xml.endElement("list-item")
elif isinstance(data, dict):
for key, value in data.iteritems():
xml.startElement(key, {})
self._to_xml(xml, value)
xml.endElement(key)
elif data is None:
# Don't output any value
pass
else:
xml.characters(smart_unicode(data))
def dict2xml(self, data):
stream = StringIO.StringIO()
xml = SimplerXMLGenerator(stream, "utf-8")
xml.startDocument()
xml.startElement("root", {})
self._to_xml(xml, data)
xml.endElement("root")
xml.endDocument()
return stream.getvalue()
def dict2xml(input):
return XMLRenderer().dict2xml(input)

View File

@@ -0,0 +1,32 @@
from django.core.urlresolvers import resolve
def get_breadcrumbs(url):
"""Given a url returns a list of breadcrumbs, which are each a tuple of (name, url)."""
from djangorestframework.views import View
def breadcrumbs_recursive(url, breadcrumbs_list):
"""Add tuples of (name, url) to the breadcrumbs list, progressively chomping off parts of the url."""
try:
(view, unused_args, unused_kwargs) = resolve(url)
except Exception:
pass
else:
# Check if this is a REST framework view, and if so add it to the breadcrumbs
if isinstance(getattr(view, 'cls_instance', None), View):
breadcrumbs_list.insert(0, (view.cls_instance.get_name(), url))
if url == '':
# All done
return breadcrumbs_list
elif url.endswith('/'):
# Drop trailing slash off the end and continue to try to resolve more breadcrumbs
return breadcrumbs_recursive(url.rstrip('/'), breadcrumbs_list)
# Drop trailing non-slash off the end and continue to try to resolve more breadcrumbs
return breadcrumbs_recursive(url[:url.rfind('/') + 1], breadcrumbs_list)
return breadcrumbs_recursive(url, [])

View File

@@ -0,0 +1,113 @@
"""
Handling of media types, as found in HTTP Content-Type and Accept headers.
See http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7
"""
from django.http.multipartparser import parse_header
def media_type_matches(lhs, rhs):
"""
Returns ``True`` if the media type in the first argument <= the
media type in the second argument. The media types are strings
as described by the HTTP spec.
Valid media type strings include:
'application/json; indent=4'
'application/json'
'text/*'
'*/*'
"""
lhs = _MediaType(lhs)
rhs = _MediaType(rhs)
return lhs.match(rhs)
def is_form_media_type(media_type):
"""
Return True if the media type is a valid form media type as defined by the HTML4 spec.
(NB. HTML5 also adds text/plain to the list of valid form media types, but we don't support this here)
"""
media_type = _MediaType(media_type)
return media_type.full_type == 'application/x-www-form-urlencoded' or \
media_type.full_type == 'multipart/form-data'
def add_media_type_param(media_type, key, val):
"""
Add a key, value parameter to a media type string, and return the new media type string.
"""
media_type = _MediaType(media_type)
media_type.params[key] = val
return str(media_type)
def get_media_type_params(media_type):
"""
Return a dictionary of the parameters on the given media type.
"""
return _MediaType(media_type).params
def order_by_precedence(media_type_lst):
"""
Returns a list of lists of media type strings, ordered by precedence.
Precedence is determined by how specific a media type is:
3. 'type/subtype; param=val'
2. 'type/subtype'
1. 'type/*'
0. '*/*'
"""
ret = [[], [], [], []]
for media_type in media_type_lst:
precedence = _MediaType(media_type).precedence
ret[3 - precedence].append(media_type)
return ret
class _MediaType(object):
def __init__(self, media_type_str):
if media_type_str is None:
media_type_str = ''
self.orig = media_type_str
self.full_type, self.params = parse_header(media_type_str)
self.main_type, sep, self.sub_type = self.full_type.partition('/')
def match(self, other):
"""Return true if this MediaType satisfies the given MediaType."""
for key in self.params.keys():
if key != 'q' and other.params.get(key, None) != self.params.get(key, None):
return False
if self.sub_type != '*' and other.sub_type != '*' and other.sub_type != self.sub_type:
return False
if self.main_type != '*' and other.main_type != '*' and other.main_type != self.main_type:
return False
return True
@property
def precedence(self):
"""
Return a precedence level from 0-3 for the media type given how specific it is.
"""
if self.main_type == '*':
return 0
elif self.sub_type == '*':
return 1
elif not self.params or self.params.keys() == ['q']:
return 2
return 3
def __str__(self):
return unicode(self).encode('utf-8')
def __unicode__(self):
ret = "%s/%s" % (self.main_type, self.sub_type)
for key, val in self.params.items():
ret += "; %s=%s" % (key, val)
return ret

View File

@@ -0,0 +1,61 @@
from django.contrib.auth.views import *
from django.conf import settings
from django.http import HttpResponse
from django.shortcuts import render_to_response
from django.template import RequestContext
import base64
# BLERGH
# Replicate django.contrib.auth.views.login simply so we don't have get users to update TEMPLATE_CONTEXT_PROCESSORS
# to add ADMIN_MEDIA_PREFIX to the RequestContext. I don't like this but really really want users to not have to
# be making settings changes in order to accomodate django-rest-framework
@csrf_protect
@never_cache
def api_login(request, template_name='djangorestframework/login.html',
redirect_field_name=REDIRECT_FIELD_NAME,
authentication_form=AuthenticationForm):
"""Displays the login form and handles the login action."""
redirect_to = request.REQUEST.get(redirect_field_name, '')
if request.method == "POST":
form = authentication_form(data=request.POST)
if form.is_valid():
# Light security check -- make sure redirect_to isn't garbage.
if not redirect_to or ' ' in redirect_to:
redirect_to = settings.LOGIN_REDIRECT_URL
# Heavier security check -- redirects to http://example.com should
# not be allowed, but things like /view/?param=http://example.com
# should be allowed. This regex checks if there is a '//' *before* a
# question mark.
elif '//' in redirect_to and re.match(r'[^\?]*//', redirect_to):
redirect_to = settings.LOGIN_REDIRECT_URL
# Okay, security checks complete. Log the user in.
auth_login(request, form.get_user())
if request.session.test_cookie_worked():
request.session.delete_test_cookie()
return HttpResponseRedirect(redirect_to)
else:
form = authentication_form(request)
request.session.set_test_cookie()
#current_site = get_current_site(request)
return render_to_response(template_name, {
'form': form,
redirect_field_name: redirect_to,
#'site': current_site,
#'site_name': current_site.name,
'ADMIN_MEDIA_PREFIX': settings.ADMIN_MEDIA_PREFIX,
}, context_instance=RequestContext(request))
def api_logout(request, next_page=None, template_name='djangorestframework/login.html', redirect_field_name=REDIRECT_FIELD_NAME):
return logout(request, next_page, template_name, redirect_field_name)