mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-23 01:57:00 +03:00
Merge 'tomchristie/restframework2' into 'browsable-bootstrap'
This commit is contained in:
commit
4500103337
|
@ -4,6 +4,8 @@
|
|||
|
||||
**Author:** Tom Christie. [Follow me on Twitter][twitter]
|
||||
|
||||
[![Build Status](https://secure.travis-ci.org/tomchristie/django-rest-framework.png?branch=restframework2)][travis]
|
||||
|
||||
# Overview
|
||||
|
||||
This branch is the redesign of Django REST framework. It is a work in progress.
|
||||
|
@ -79,7 +81,7 @@ 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.
|
||||
|
||||
|
||||
[travis]: http://travis-ci.org/tomchristie/django-rest-framework?branch=restframework2
|
||||
[twitter]: https://twitter.com/_tomchristie
|
||||
[docs]: http://tomchristie.github.com/django-rest-framework/
|
||||
[urlobject]: https://github.com/zacharyvoase/urlobject
|
||||
|
|
|
@ -103,4 +103,38 @@ class SessionAuthentication(BaseAuthentication):
|
|||
return (user, None)
|
||||
|
||||
|
||||
# TODO: TokenAuthentication, DigestAuthentication, OAuthAuthentication
|
||||
class TokenAuthentication(BaseAuthentication):
|
||||
"""
|
||||
Use a token model for authentication.
|
||||
|
||||
A custom token model may be used here, but must have the following minimum
|
||||
properties:
|
||||
|
||||
* key -- The string identifying the token
|
||||
* user -- The user to which the token belongs
|
||||
* revoked -- The status of the token
|
||||
|
||||
The token key should be passed in as a string to the "Authorization" HTTP
|
||||
header. For example:
|
||||
|
||||
Authorization: 0123456789abcdef0123456789abcdef
|
||||
|
||||
"""
|
||||
model = None
|
||||
|
||||
def authenticate(self, request):
|
||||
key = request.META.get('HTTP_AUTHORIZATION', '').strip()
|
||||
|
||||
if self.model is None:
|
||||
from djangorestframework.tokenauth.models import BasicToken
|
||||
self.model = BasicToken
|
||||
|
||||
try:
|
||||
token = self.model.objects.get(key=key)
|
||||
except self.model.DoesNotExist:
|
||||
return None
|
||||
|
||||
if token.user.is_active and not token.revoked:
|
||||
return (token.user, token)
|
||||
|
||||
# TODO: DigestAuthentication, OAuthAuthentication
|
||||
|
|
|
@ -366,6 +366,59 @@ else:
|
|||
|
||||
return self._accept(request)
|
||||
|
||||
# timezone support is new in Django 1.4
|
||||
try:
|
||||
from django.utils import timezone
|
||||
except ImportError:
|
||||
timezone = None
|
||||
|
||||
# dateparse is ALSO new in Django 1.4
|
||||
try:
|
||||
from django.utils.dateparse import parse_date, parse_datetime
|
||||
except ImportError:
|
||||
import datetime
|
||||
import re
|
||||
|
||||
date_re = re.compile(
|
||||
r'(?P<year>\d{4})-(?P<month>\d{1,2})-(?P<day>\d{1,2})$'
|
||||
)
|
||||
|
||||
datetime_re = re.compile(
|
||||
r'(?P<year>\d{4})-(?P<month>\d{1,2})-(?P<day>\d{1,2})'
|
||||
r'[T ](?P<hour>\d{1,2}):(?P<minute>\d{1,2})'
|
||||
r'(?::(?P<second>\d{1,2})(?:\.(?P<microsecond>\d{1,6})\d{0,6})?)?'
|
||||
r'(?P<tzinfo>Z|[+-]\d{1,2}:\d{1,2})?$'
|
||||
)
|
||||
|
||||
time_re = re.compile(
|
||||
r'(?P<hour>\d{1,2}):(?P<minute>\d{1,2})'
|
||||
r'(?::(?P<second>\d{1,2})(?:\.(?P<microsecond>\d{1,6})\d{0,6})?)?'
|
||||
)
|
||||
|
||||
def parse_date(value):
|
||||
match = date_re.match(value)
|
||||
if match:
|
||||
kw = dict((k, int(v)) for k, v in match.groupdict().iteritems())
|
||||
return datetime.date(**kw)
|
||||
|
||||
def parse_time(value):
|
||||
match = time_re.match(value)
|
||||
if match:
|
||||
kw = match.groupdict()
|
||||
if kw['microsecond']:
|
||||
kw['microsecond'] = kw['microsecond'].ljust(6, '0')
|
||||
kw = dict((k, int(v)) for k, v in kw.iteritems() if v is not None)
|
||||
return datetime.time(**kw)
|
||||
|
||||
def parse_datetime(value):
|
||||
"""Parse datetime, but w/o the timezone awareness in 1.4"""
|
||||
match = datetime_re.match(value)
|
||||
if match:
|
||||
kw = match.groupdict()
|
||||
if kw['microsecond']:
|
||||
kw['microsecond'] = kw['microsecond'].ljust(6, '0')
|
||||
kw = dict((k, int(v)) for k, v in kw.iteritems() if v is not None)
|
||||
return datetime.datetime(**kw)
|
||||
|
||||
# Markdown is optional
|
||||
try:
|
||||
|
|
|
@ -8,10 +8,10 @@ from django.core.exceptions import ValidationError
|
|||
from django.conf import settings
|
||||
from django.db import DEFAULT_DB_ALIAS
|
||||
from django.db.models.related import RelatedObject
|
||||
from django.utils import timezone
|
||||
from django.utils.dateparse import parse_date, parse_datetime
|
||||
from django.utils.encoding import is_protected_type, smart_unicode
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from djangorestframework.compat import parse_date, parse_datetime
|
||||
from djangorestframework.compat import timezone
|
||||
|
||||
|
||||
def is_simple_callable(obj):
|
||||
|
@ -317,7 +317,7 @@ class DateField(Field):
|
|||
if value is None:
|
||||
return value
|
||||
if isinstance(value, datetime.datetime):
|
||||
if settings.USE_TZ and timezone.is_aware(value):
|
||||
if timezone and settings.USE_TZ and timezone.is_aware(value):
|
||||
# Convert aware datetimes to the default time zone
|
||||
# before casting them to dates (#17742).
|
||||
default_timezone = timezone.get_default_timezone()
|
||||
|
|
|
@ -22,7 +22,7 @@ class CreateModelMixin(object):
|
|||
self.object = serializer.object
|
||||
self.object.save()
|
||||
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
||||
return Response(serializer.error_data, status=status.HTTP_400_BAD_REQUEST)
|
||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
|
||||
class ListModelMixin(object):
|
||||
|
|
|
@ -16,6 +16,7 @@ from djangorestframework.utils import encoders
|
|||
from djangorestframework.utils.breadcrumbs import get_breadcrumbs
|
||||
from djangorestframework.utils.mediatypes import get_media_type_params, add_media_type_param, media_type_matches
|
||||
from djangorestframework import VERSION
|
||||
from djangorestframework.fields import FloatField, IntegerField, DateTimeField, DateField, EmailField, CharField, BooleanField
|
||||
|
||||
import string
|
||||
|
||||
|
@ -233,33 +234,31 @@ class DocumentingTemplateRenderer(BaseRenderer):
|
|||
In the absence on of the Resource having an associated form then
|
||||
provide a form that can be used to submit arbitrary content.
|
||||
"""
|
||||
if not hasattr(self.view, 'get_serializer'): # No serializer, no form.
|
||||
return
|
||||
# We need to map our Fields to Django's Fields.
|
||||
field_mapping = dict([
|
||||
[FloatField.__name__, forms.FloatField],
|
||||
[IntegerField.__name__, forms.IntegerField],
|
||||
[DateTimeField.__name__, forms.DateTimeField],
|
||||
[DateField.__name__, forms.DateField],
|
||||
[EmailField.__name__, forms.EmailField],
|
||||
[CharField.__name__, forms.CharField],
|
||||
[BooleanField.__name__, forms.BooleanField]
|
||||
])
|
||||
|
||||
# Get the form instance if we have one bound to the input
|
||||
form_instance = None
|
||||
if method == getattr(view, 'method', view.request.method).lower():
|
||||
form_instance = getattr(view, 'bound_form_instance', None)
|
||||
|
||||
if not form_instance and hasattr(view, 'get_bound_form'):
|
||||
# Otherwise if we have a response that is valid against the form then use that
|
||||
if view.response.has_content_body:
|
||||
try:
|
||||
form_instance = view.get_bound_form(view.response.cleaned_content, method=method)
|
||||
if form_instance and not form_instance.is_valid():
|
||||
form_instance = None
|
||||
except Exception:
|
||||
form_instance = None
|
||||
|
||||
# If we still don't have a form instance then try to get an unbound form
|
||||
if not form_instance:
|
||||
try:
|
||||
form_instance = view.get_bound_form(method=method)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# If we still don't have a form instance then try to get an unbound form which can tunnel arbitrary content types
|
||||
if not form_instance:
|
||||
form_instance = self._get_generic_content_form(view)
|
||||
|
||||
# Creating an on the fly form see: http://stackoverflow.com/questions/3915024/dynamically-creating-classes-python
|
||||
fields = {}
|
||||
object, data = None, None
|
||||
if hasattr(self.view, 'object'):
|
||||
object = self.view.object
|
||||
serializer = self.view.get_serializer(instance=object)
|
||||
for k, v in serializer.fields.items():
|
||||
fields[k] = field_mapping[v.__class__.__name__]()
|
||||
OnTheFlyForm = type("OnTheFlyForm", (forms.Form,), fields)
|
||||
if object and not self.view.request.method == 'DELETE': # Don't fill in the form when the object is deleted
|
||||
data = serializer.data
|
||||
form_instance = OnTheFlyForm(data)
|
||||
return form_instance
|
||||
|
||||
def _get_generic_content_form(self, view):
|
||||
|
|
|
@ -90,6 +90,7 @@ INSTALLED_APPS = (
|
|||
# Uncomment the next line to enable admin documentation:
|
||||
# 'django.contrib.admindocs',
|
||||
'djangorestframework',
|
||||
'djangorestframework.tokenauth',
|
||||
)
|
||||
|
||||
STATIC_URL = '/static/'
|
||||
|
|
|
@ -88,7 +88,10 @@ def import_from_string(val, setting):
|
|||
module_path, class_name = '.'.join(parts[:-1]), parts[-1]
|
||||
module = importlib.import_module(module_path)
|
||||
return getattr(module, class_name)
|
||||
except:
|
||||
except Exception, e:
|
||||
import traceback
|
||||
tb = traceback.format_exc()
|
||||
import pdb; pdb.set_trace()
|
||||
msg = "Could not import '%s' for API setting '%s'" % (val, setting)
|
||||
raise ImportError(msg)
|
||||
|
||||
|
|
|
@ -8,6 +8,9 @@ from django.http import HttpResponse
|
|||
from djangorestframework.views import APIView
|
||||
from djangorestframework import permissions
|
||||
|
||||
from djangorestframework.tokenauth.models import BasicToken
|
||||
from djangorestframework.authentication import TokenAuthentication
|
||||
|
||||
import base64
|
||||
|
||||
|
||||
|
@ -20,6 +23,8 @@ class MockView(APIView):
|
|||
def put(self, request):
|
||||
return HttpResponse({'a': 1, 'b': 2, 'c': 3})
|
||||
|
||||
MockView.authentication += (TokenAuthentication,)
|
||||
|
||||
urlpatterns = patterns('',
|
||||
(r'^$', MockView.as_view()),
|
||||
)
|
||||
|
@ -104,3 +109,45 @@ class SessionAuthTests(TestCase):
|
|||
"""
|
||||
response = self.csrf_client.post('/', {'example': 'example'})
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
|
||||
class TokenAuthTests(TestCase):
|
||||
"""Token authentication"""
|
||||
urls = 'djangorestframework.tests.authentication'
|
||||
|
||||
def setUp(self):
|
||||
self.csrf_client = Client(enforce_csrf_checks=True)
|
||||
self.username = 'john'
|
||||
self.email = 'lennon@thebeatles.com'
|
||||
self.password = 'password'
|
||||
self.user = User.objects.create_user(self.username, self.email, self.password)
|
||||
|
||||
self.key = 'abcd1234'
|
||||
self.token = BasicToken.objects.create(key=self.key, user=self.user)
|
||||
|
||||
def test_post_form_passing_token_auth(self):
|
||||
"""Ensure POSTing json over token auth with correct credentials passes and does not require CSRF"""
|
||||
auth = self.key
|
||||
response = self.csrf_client.post('/', {'example': 'example'}, HTTP_AUTHORIZATION=auth)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_post_json_passing_token_auth(self):
|
||||
"""Ensure POSTing form over token auth with correct credentials passes and does not require CSRF"""
|
||||
auth = self.key
|
||||
response = self.csrf_client.post('/', json.dumps({'example': 'example'}), 'application/json', HTTP_AUTHORIZATION=auth)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_post_form_failing_token_auth(self):
|
||||
"""Ensure POSTing form over token auth without correct credentials fails"""
|
||||
response = self.csrf_client.post('/', {'example': 'example'})
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_post_json_failing_token_auth(self):
|
||||
"""Ensure POSTing json over token auth without correct credentials fails"""
|
||||
response = self.csrf_client.post('/', json.dumps({'example': 'example'}), 'application/json')
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_token_has_auto_assigned_key_if_none_provided(self):
|
||||
"""Ensure creating a token with no key will auto-assign a key"""
|
||||
token = BasicToken.objects.create(user=self.user)
|
||||
self.assertEqual(len(token.key), 32)
|
||||
|
|
|
@ -55,27 +55,27 @@ class MockView(APIView):
|
|||
|
||||
def get(self, request, **kwargs):
|
||||
response = Response(DUMMYCONTENT, status=DUMMYSTATUS)
|
||||
return self.render(response)
|
||||
return response
|
||||
|
||||
|
||||
class MockGETView(APIView):
|
||||
|
||||
def get(self, request, **kwargs):
|
||||
return {'foo': ['bar', 'baz']}
|
||||
return Response({'foo': ['bar', 'baz']})
|
||||
|
||||
|
||||
class HTMLView(APIView):
|
||||
renderers = (DocumentingHTMLRenderer, )
|
||||
|
||||
def get(self, request, **kwargs):
|
||||
return 'text'
|
||||
return Response('text')
|
||||
|
||||
|
||||
class HTMLView1(APIView):
|
||||
renderers = (DocumentingHTMLRenderer, JSONRenderer)
|
||||
|
||||
def get(self, request, **kwargs):
|
||||
return 'text'
|
||||
return Response('text')
|
||||
|
||||
urlpatterns = patterns('',
|
||||
url(r'^.*\.(?P<format>.+)$', MockView.as_view(renderers=[RendererA, RendererB])),
|
||||
|
@ -88,7 +88,7 @@ urlpatterns = patterns('',
|
|||
)
|
||||
|
||||
|
||||
class RendererIntegrationTests(TestCase):
|
||||
class RendererEndToEndTests(TestCase):
|
||||
"""
|
||||
End-to-end testing of renderers using an RendererMixin on a generic view.
|
||||
"""
|
||||
|
@ -216,18 +216,6 @@ class JSONRendererTests(TestCase):
|
|||
self.assertEquals(strip_trailing_whitespace(content), _indented_repr)
|
||||
|
||||
|
||||
class MockGETView(APIView):
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
return Response({'foo': ['bar', 'baz']})
|
||||
|
||||
|
||||
urlpatterns = patterns('',
|
||||
url(r'^jsonp/jsonrenderer$', MockGETView.as_view(renderers=[JSONRenderer, JSONPRenderer])),
|
||||
url(r'^jsonp/nojsonrenderer$', MockGETView.as_view(renderers=[JSONPRenderer])),
|
||||
)
|
||||
|
||||
|
||||
class JSONPRendererTests(TestCase):
|
||||
"""
|
||||
Tests specific to the JSONP Renderer
|
||||
|
|
|
@ -94,7 +94,16 @@ class TestContentParsing(TestCase):
|
|||
"""
|
||||
data = {'qwerty': 'uiop'}
|
||||
parsers = (FormParser, MultiPartParser)
|
||||
request = factory.put('/', data, parsers=parsers)
|
||||
|
||||
from django import VERSION
|
||||
|
||||
if VERSION >= (1, 5):
|
||||
from django.test.client import MULTIPART_CONTENT, BOUNDARY, encode_multipart
|
||||
request = factory.put('/', encode_multipart(BOUNDARY, data), parsers=parsers,
|
||||
content_type=MULTIPART_CONTENT)
|
||||
else:
|
||||
request = factory.put('/', data, parsers=parsers)
|
||||
|
||||
self.assertEqual(request.DATA.items(), data.items())
|
||||
|
||||
def test_standard_behaviour_determines_non_form_content_PUT(self):
|
||||
|
|
0
djangorestframework/tokenauth/__init__.py
Normal file
0
djangorestframework/tokenauth/__init__.py
Normal file
15
djangorestframework/tokenauth/models.py
Normal file
15
djangorestframework/tokenauth/models.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
import uuid
|
||||
from django.db import models
|
||||
|
||||
class BasicToken(models.Model):
|
||||
"""
|
||||
The default authorization token model class.
|
||||
"""
|
||||
key = models.CharField(max_length=32, primary_key=True, blank=True)
|
||||
user = models.ForeignKey('auth.User')
|
||||
revoked = models.BooleanField(default=False)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.key:
|
||||
self.key = uuid.uuid4().hex
|
||||
return super(BasicToken, self).save(*args, **kwargs)
|
0
djangorestframework/tokenauth/views.py
Normal file
0
djangorestframework/tokenauth/views.py
Normal file
|
@ -3,8 +3,8 @@ Helper classes for parsers.
|
|||
"""
|
||||
import datetime
|
||||
import decimal
|
||||
from django.utils import timezone
|
||||
from django.utils import simplejson as json
|
||||
from djangorestframework.compat import timezone
|
||||
|
||||
|
||||
class JSONEncoder(json.JSONEncoder):
|
||||
|
@ -25,7 +25,7 @@ class JSONEncoder(json.JSONEncoder):
|
|||
elif isinstance(o, datetime.date):
|
||||
return o.isoformat()
|
||||
elif isinstance(o, datetime.time):
|
||||
if timezone.is_aware(o):
|
||||
if timezone and timezone.is_aware(o):
|
||||
raise ValueError("JSON can't represent timezone-aware times.")
|
||||
r = o.isoformat()
|
||||
if o.microsecond:
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
<a class="github" href="authentication.py"></a>
|
||||
|
||||
# Authentication
|
||||
|
||||
Authentication is the mechanism of associating an incoming request with a set of identifying credentials, such as the user the request came from, or the token that it was signed with. The [permission] and [throttling] policies can then use those credentials to determine if the request should be permitted.
|
||||
|
@ -8,7 +10,7 @@ Authentication will run the first time either the `request.user` or `request.aut
|
|||
|
||||
The `request.user` property will typically be set to an instance of the `contrib.auth` package's `User` class.
|
||||
|
||||
The `request.auth` property is used for any additional authentication information, for example, it may be used to represent an authentication token that the request was signed with.
|
||||
The `request.auth` property is used for any additional authentication information, for example, it may be used to represent an authentication token that the request was signed with.
|
||||
|
||||
## How authentication is determined
|
||||
|
||||
|
@ -36,7 +38,7 @@ You can also set the authentication policy on a per-view basis, using the `APIVi
|
|||
|
||||
def get(self, request, format=None):
|
||||
content = {
|
||||
'user': unicode(request.user), # `django.contrib.auth.User` instance.
|
||||
'user': unicode(request.user), # `django.contrib.auth.User` instance.
|
||||
'auth': unicode(request.auth), # None
|
||||
}
|
||||
return Response(content)
|
||||
|
@ -49,7 +51,7 @@ Or, if you're using the `@api_view` decorator with function based views.
|
|||
)
|
||||
def example_view(request, format=None):
|
||||
content = {
|
||||
'user': unicode(request.user), # `django.contrib.auth.User` instance.
|
||||
'user': unicode(request.user), # `django.contrib.auth.User` instance.
|
||||
'auth': unicode(request.auth), # None
|
||||
}
|
||||
return Response(content)
|
||||
|
@ -65,16 +67,20 @@ If successfully authenticated, `UserBasicAuthentication` provides the following
|
|||
* `request.user` will be a `django.contrib.auth.models.User` instance.
|
||||
* `request.auth` will be `None`.
|
||||
|
||||
## TokenBasicAuthentication
|
||||
## TokenAuthentication
|
||||
|
||||
This policy uses [HTTP Basic Authentication][basicauth], signed against a token key and secret. Token basic authentication is appropriate for client-server setups, such as native desktop and mobile clients.
|
||||
This policy uses [HTTP Authentication][basicauth] with no authentication scheme. Token basic authentication is appropriate for client-server setups, such as native desktop and mobile clients. The token key should be passed in as a string to the "Authorization" HTTP header. For example:
|
||||
|
||||
**Note:** If you run `TokenBasicAuthentication` in production your API must be `https` only, or it will be completely insecure.
|
||||
curl http://my.api.org/ -X POST -H "Authorization: 0123456789abcdef0123456789abcdef"
|
||||
|
||||
If successfully authenticated, `TokenBasicAuthentication` provides the following credentials.
|
||||
**Note:** If you run `TokenAuthentication` in production your API must be `https` only, or it will be completely insecure.
|
||||
|
||||
If successfully authenticated, `TokenAuthentication` provides the following credentials.
|
||||
|
||||
* `request.user` will be a `django.contrib.auth.models.User` instance.
|
||||
* `request.auth` will be a `djangorestframework.models.BasicToken` instance.
|
||||
* `request.auth` will be a `djangorestframework.tokenauth.models.BasicToken` instance.
|
||||
|
||||
To use the `TokenAuthentication` policy, you must have a token model. Django REST Framework comes with a minimal default token model. To use it, include `djangorestframework.tokenauth` in your installed applications and sync your database. To use your own token model, subclass the `djangorestframework.tokenauth.TokenAuthentication` class and specify a `model` attribute that references your custom token model. The token model must provide `user`, `key`, and `revoked` attributes. Refer to the `djangorestframework.tokenauth.models.BasicToken` model as an example.
|
||||
|
||||
## OAuthAuthentication
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
<a class="github" href="exceptions.py"></a>
|
||||
|
||||
# Exceptions
|
||||
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
<a class="github" href="parsers.py"></a>
|
||||
|
||||
# Parsers
|
||||
|
||||
## .parse(request)
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
<a class="github" href="permissions.py"></a>
|
||||
|
||||
# Permissions
|
|
@ -1,3 +1,5 @@
|
|||
<a class="github" href="renderers.py"></a>
|
||||
|
||||
# Renderers
|
||||
|
||||
## .render(response)
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
<a class="github" href="request.py"></a>
|
||||
|
||||
# Requests
|
||||
|
||||
> If you're doing REST-based web service stuff ... you should ignore request.POST.
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
<a class="github" href="response.py"></a>
|
||||
|
||||
# Responses
|
||||
|
||||
> Unlike basic HttpResponse objects, TemplateResponse objects retain the details of the context that was provided by the view to compute the response. The final output of the response is not computed until it is needed, later in the response process.
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
<a class="github" href="reverse.py"></a>
|
||||
|
||||
# Returning URIs from your Web APIs
|
||||
|
||||
> The central feature that distinguishes the REST architectural style from other network-based styles is its emphasis on a uniform interface between components.
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
<a class="github" href="serializers.py"></a>
|
||||
|
||||
# Serializers
|
||||
|
||||
> Expanding the usefulness of the serializers is something that we would
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
<a class="github" href="settings.py"></a>
|
||||
|
||||
# Settings
|
||||
|
||||
Configuration for REST framework is all namespaced inside the `API_SETTINGS` setting.
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
<a class="github" href="status.py"></a>
|
||||
|
||||
# Status Codes
|
||||
|
||||
> 418 I'm a teapot - Any attempt to brew coffee with a teapot should result in the error code "418 I'm a teapot". The resulting entity body MAY be short and stout.
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
<a class="github" href="throttling.py"></a>
|
||||
|
||||
# Throttling
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
<a class="github" href="views.py"></a>
|
||||
|
||||
# Views
|
||||
|
||||
> Django's class based views are a welcome departure from the old-style views.
|
||||
>
|
||||
> — [Reinout van Rees][cite]
|
||||
|
||||
# Views
|
||||
|
||||
REST framework provides a simple `APIView` class, built on Django's `django.generics.views.View`. The `APIView` class ensures five main things:
|
||||
|
||||
1. Any requests inside the view will become `Request` instances.
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
<iframe src="http://ghbtns.com/github-btn.html?user=tomchristie&repo=django-rest-framework&type=watch&count=true" allowtransparency="true" frameborder="0" scrolling="0" width="110px" height="20px"></iframe>
|
||||
[![Build Status](https://secure.travis-ci.org/tomchristie/django-rest-framework.png?branch=restframework2)][travis]
|
||||
|
||||
# Django REST framework
|
||||
|
||||
**A toolkit for building well-connected, self-describing Web APIs.**
|
||||
|
@ -131,6 +134,7 @@ 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.
|
||||
|
||||
[travis]: http://travis-ci.org/tomchristie/django-rest-framework?branch=restframework2
|
||||
[urlobject]: https://github.com/zacharyvoase/urlobject
|
||||
[markdown]: http://pypi.python.org/pypi/Markdown/
|
||||
[yaml]: http://pypi.python.org/pypi/PyYAML
|
||||
|
|
30
docs/static/css/bootstrap-responsive.css
vendored
30
docs/static/css/bootstrap-responsive.css
vendored
|
@ -1,5 +1,5 @@
|
|||
/*!
|
||||
* Bootstrap Responsive v2.1.0
|
||||
* Bootstrap Responsive v2.1.1
|
||||
*
|
||||
* Copyright 2012 Twitter, Inc
|
||||
* Licensed under the Apache License v2.0
|
||||
|
@ -107,6 +107,7 @@
|
|||
}
|
||||
[class*="span"] {
|
||||
float: left;
|
||||
min-height: 1px;
|
||||
margin-left: 30px;
|
||||
}
|
||||
.container,
|
||||
|
@ -453,6 +454,7 @@
|
|||
}
|
||||
[class*="span"] {
|
||||
float: left;
|
||||
min-height: 1px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
.container,
|
||||
|
@ -780,7 +782,8 @@
|
|||
padding-left: 20px;
|
||||
}
|
||||
.navbar-fixed-top,
|
||||
.navbar-fixed-bottom {
|
||||
.navbar-fixed-bottom,
|
||||
.navbar-static-top {
|
||||
margin-right: -20px;
|
||||
margin-left: -20px;
|
||||
}
|
||||
|
@ -814,8 +817,11 @@
|
|||
.row-fluid [class*="span"] {
|
||||
display: block;
|
||||
float: none;
|
||||
width: auto;
|
||||
width: 100%;
|
||||
margin-left: 0;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.span12,
|
||||
.row-fluid .span12 {
|
||||
|
@ -845,6 +851,9 @@
|
|||
display: inline-block;
|
||||
width: auto;
|
||||
}
|
||||
.controls-row [class*="span"] + [class*="span"] {
|
||||
margin-left: 0;
|
||||
}
|
||||
.modal {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
|
@ -870,7 +879,7 @@
|
|||
input[type="radio"] {
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
.form-horizontal .control-group > label {
|
||||
.form-horizontal .control-label {
|
||||
float: none;
|
||||
width: auto;
|
||||
padding-top: 0;
|
||||
|
@ -944,14 +953,14 @@
|
|||
display: none;
|
||||
}
|
||||
.nav-collapse .nav .nav-header {
|
||||
color: #555555;
|
||||
color: #777777;
|
||||
text-shadow: none;
|
||||
}
|
||||
.nav-collapse .nav > li > a,
|
||||
.nav-collapse .dropdown-menu a {
|
||||
padding: 9px 15px;
|
||||
font-weight: bold;
|
||||
color: #555555;
|
||||
color: #777777;
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
|
@ -1003,6 +1012,10 @@
|
|||
.nav-collapse .dropdown-menu .divider {
|
||||
display: none;
|
||||
}
|
||||
.nav-collapse .nav > li > .dropdown-menu:before,
|
||||
.nav-collapse .nav > li > .dropdown-menu:after {
|
||||
display: none;
|
||||
}
|
||||
.nav-collapse .navbar-form,
|
||||
.nav-collapse .navbar-search {
|
||||
float: none;
|
||||
|
@ -1014,6 +1027,11 @@
|
|||
-moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
.navbar-inverse .nav-collapse .navbar-form,
|
||||
.navbar-inverse .nav-collapse .navbar-search {
|
||||
border-top-color: #111111;
|
||||
border-bottom-color: #111111;
|
||||
}
|
||||
.navbar .nav-collapse .nav.pull-right {
|
||||
float: none;
|
||||
margin-left: 0;
|
||||
|
|
318
docs/static/css/bootstrap.css
vendored
318
docs/static/css/bootstrap.css
vendored
|
@ -1,5 +1,5 @@
|
|||
/*!
|
||||
* Bootstrap v2.1.0
|
||||
* Bootstrap v2.1.1
|
||||
*
|
||||
* Copyright 2012 Twitter, Inc
|
||||
* Licensed under the Apache License v2.0
|
||||
|
@ -67,6 +67,7 @@ sub {
|
|||
}
|
||||
|
||||
img {
|
||||
width: auto\9;
|
||||
height: auto;
|
||||
max-width: 100%;
|
||||
vertical-align: middle;
|
||||
|
@ -215,6 +216,7 @@ a:hover {
|
|||
|
||||
[class*="span"] {
|
||||
float: left;
|
||||
min-height: 1px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
|
@ -583,7 +585,7 @@ p {
|
|||
|
||||
.lead {
|
||||
margin-bottom: 20px;
|
||||
font-size: 20px;
|
||||
font-size: 21px;
|
||||
font-weight: 200;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
@ -608,6 +610,22 @@ cite {
|
|||
color: #999999;
|
||||
}
|
||||
|
||||
.text-warning {
|
||||
color: #c09853;
|
||||
}
|
||||
|
||||
.text-error {
|
||||
color: #b94a48;
|
||||
}
|
||||
|
||||
.text-info {
|
||||
color: #3a87ad;
|
||||
}
|
||||
|
||||
.text-success {
|
||||
color: #468847;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
|
@ -725,9 +743,24 @@ dd {
|
|||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.dl-horizontal {
|
||||
*zoom: 1;
|
||||
}
|
||||
|
||||
.dl-horizontal:before,
|
||||
.dl-horizontal:after {
|
||||
display: table;
|
||||
line-height: 0;
|
||||
content: "";
|
||||
}
|
||||
|
||||
.dl-horizontal:after {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.dl-horizontal dt {
|
||||
float: left;
|
||||
width: 120px;
|
||||
width: 160px;
|
||||
overflow: hidden;
|
||||
clear: left;
|
||||
text-align: right;
|
||||
|
@ -736,7 +769,7 @@ dd {
|
|||
}
|
||||
|
||||
.dl-horizontal dd {
|
||||
margin-left: 130px;
|
||||
margin-left: 180px;
|
||||
}
|
||||
|
||||
hr {
|
||||
|
@ -945,8 +978,9 @@ input[type="color"],
|
|||
}
|
||||
|
||||
input,
|
||||
textarea {
|
||||
width: 210px;
|
||||
textarea,
|
||||
.uneditable-input {
|
||||
width: 206px;
|
||||
}
|
||||
|
||||
textarea {
|
||||
|
@ -1039,7 +1073,7 @@ input[type="file"] {
|
|||
select {
|
||||
width: 220px;
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #bbb;
|
||||
border: 1px solid #cccccc;
|
||||
}
|
||||
|
||||
select[multiple],
|
||||
|
@ -1301,14 +1335,17 @@ input[type="checkbox"][readonly] {
|
|||
.control-group.warning select,
|
||||
.control-group.warning textarea {
|
||||
color: #c09853;
|
||||
}
|
||||
|
||||
.control-group.warning input,
|
||||
.control-group.warning select,
|
||||
.control-group.warning textarea {
|
||||
border-color: #c09853;
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
|
||||
.control-group.warning .checkbox:focus,
|
||||
.control-group.warning .radio:focus,
|
||||
.control-group.warning input:focus,
|
||||
.control-group.warning select:focus,
|
||||
.control-group.warning textarea:focus {
|
||||
|
@ -1337,14 +1374,17 @@ input[type="checkbox"][readonly] {
|
|||
.control-group.error select,
|
||||
.control-group.error textarea {
|
||||
color: #b94a48;
|
||||
}
|
||||
|
||||
.control-group.error input,
|
||||
.control-group.error select,
|
||||
.control-group.error textarea {
|
||||
border-color: #b94a48;
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
|
||||
.control-group.error .checkbox:focus,
|
||||
.control-group.error .radio:focus,
|
||||
.control-group.error input:focus,
|
||||
.control-group.error select:focus,
|
||||
.control-group.error textarea:focus {
|
||||
|
@ -1373,14 +1413,17 @@ input[type="checkbox"][readonly] {
|
|||
.control-group.success select,
|
||||
.control-group.success textarea {
|
||||
color: #468847;
|
||||
}
|
||||
|
||||
.control-group.success input,
|
||||
.control-group.success select,
|
||||
.control-group.success textarea {
|
||||
border-color: #468847;
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
|
||||
.control-group.success .checkbox:focus,
|
||||
.control-group.success .radio:focus,
|
||||
.control-group.success input:focus,
|
||||
.control-group.success select:focus,
|
||||
.control-group.success textarea:focus {
|
||||
|
@ -1397,6 +1440,45 @@ input[type="checkbox"][readonly] {
|
|||
border-color: #468847;
|
||||
}
|
||||
|
||||
.control-group.info > label,
|
||||
.control-group.info .help-block,
|
||||
.control-group.info .help-inline {
|
||||
color: #3a87ad;
|
||||
}
|
||||
|
||||
.control-group.info .checkbox,
|
||||
.control-group.info .radio,
|
||||
.control-group.info input,
|
||||
.control-group.info select,
|
||||
.control-group.info textarea {
|
||||
color: #3a87ad;
|
||||
}
|
||||
|
||||
.control-group.info input,
|
||||
.control-group.info select,
|
||||
.control-group.info textarea {
|
||||
border-color: #3a87ad;
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
|
||||
.control-group.info input:focus,
|
||||
.control-group.info select:focus,
|
||||
.control-group.info textarea:focus {
|
||||
border-color: #2d6987;
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;
|
||||
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;
|
||||
}
|
||||
|
||||
.control-group.info .input-prepend .add-on,
|
||||
.control-group.info .input-append .add-on {
|
||||
color: #3a87ad;
|
||||
background-color: #d9edf7;
|
||||
border-color: #3a87ad;
|
||||
}
|
||||
|
||||
input:focus:required:invalid,
|
||||
textarea:focus:required:invalid,
|
||||
select:focus:required:invalid {
|
||||
|
@ -1503,7 +1585,6 @@ select:focus:required:invalid:focus {
|
|||
.input-prepend .add-on,
|
||||
.input-append .btn,
|
||||
.input-prepend .btn {
|
||||
margin-left: -1px;
|
||||
vertical-align: top;
|
||||
-webkit-border-radius: 0;
|
||||
-moz-border-radius: 0;
|
||||
|
@ -1536,6 +1617,11 @@ select:focus:required:invalid:focus {
|
|||
border-radius: 3px 0 0 3px;
|
||||
}
|
||||
|
||||
.input-append .add-on,
|
||||
.input-append .btn {
|
||||
margin-left: -1px;
|
||||
}
|
||||
|
||||
.input-append .add-on:last-child,
|
||||
.input-append .btn:last-child {
|
||||
-webkit-border-radius: 0 3px 3px 0;
|
||||
|
@ -1706,7 +1792,7 @@ legend + .control-group {
|
|||
|
||||
.form-horizontal .control-label {
|
||||
float: left;
|
||||
width: 140px;
|
||||
width: 160px;
|
||||
padding-top: 5px;
|
||||
text-align: right;
|
||||
}
|
||||
|
@ -1714,21 +1800,26 @@ legend + .control-group {
|
|||
.form-horizontal .controls {
|
||||
*display: inline-block;
|
||||
*padding-left: 20px;
|
||||
margin-left: 160px;
|
||||
margin-left: 180px;
|
||||
*margin-left: 0;
|
||||
}
|
||||
|
||||
.form-horizontal .controls:first-child {
|
||||
*padding-left: 160px;
|
||||
*padding-left: 180px;
|
||||
}
|
||||
|
||||
.form-horizontal .help-block {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.form-horizontal input + .help-block,
|
||||
.form-horizontal select + .help-block,
|
||||
.form-horizontal textarea + .help-block {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.form-horizontal .form-actions {
|
||||
padding-left: 160px;
|
||||
padding-left: 180px;
|
||||
}
|
||||
|
||||
table {
|
||||
|
@ -1853,7 +1944,7 @@ table {
|
|||
.table-bordered colgroup + tbody tr:first-child td:last-child {
|
||||
-webkit-border-top-right-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
-moz-border-right-topleft: 4px;
|
||||
-moz-border-radius-topleft: 4px;
|
||||
}
|
||||
|
||||
.table-striped tbody tr:nth-child(odd) td,
|
||||
|
@ -1873,145 +1964,145 @@ table [class*=span],
|
|||
margin-left: 0;
|
||||
}
|
||||
|
||||
table .span1 {
|
||||
.table .span1 {
|
||||
float: none;
|
||||
width: 44px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
table .span2 {
|
||||
.table .span2 {
|
||||
float: none;
|
||||
width: 124px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
table .span3 {
|
||||
.table .span3 {
|
||||
float: none;
|
||||
width: 204px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
table .span4 {
|
||||
.table .span4 {
|
||||
float: none;
|
||||
width: 284px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
table .span5 {
|
||||
.table .span5 {
|
||||
float: none;
|
||||
width: 364px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
table .span6 {
|
||||
.table .span6 {
|
||||
float: none;
|
||||
width: 444px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
table .span7 {
|
||||
.table .span7 {
|
||||
float: none;
|
||||
width: 524px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
table .span8 {
|
||||
.table .span8 {
|
||||
float: none;
|
||||
width: 604px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
table .span9 {
|
||||
.table .span9 {
|
||||
float: none;
|
||||
width: 684px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
table .span10 {
|
||||
.table .span10 {
|
||||
float: none;
|
||||
width: 764px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
table .span11 {
|
||||
.table .span11 {
|
||||
float: none;
|
||||
width: 844px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
table .span12 {
|
||||
.table .span12 {
|
||||
float: none;
|
||||
width: 924px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
table .span13 {
|
||||
.table .span13 {
|
||||
float: none;
|
||||
width: 1004px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
table .span14 {
|
||||
.table .span14 {
|
||||
float: none;
|
||||
width: 1084px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
table .span15 {
|
||||
.table .span15 {
|
||||
float: none;
|
||||
width: 1164px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
table .span16 {
|
||||
.table .span16 {
|
||||
float: none;
|
||||
width: 1244px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
table .span17 {
|
||||
.table .span17 {
|
||||
float: none;
|
||||
width: 1324px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
table .span18 {
|
||||
.table .span18 {
|
||||
float: none;
|
||||
width: 1404px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
table .span19 {
|
||||
.table .span19 {
|
||||
float: none;
|
||||
width: 1484px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
table .span20 {
|
||||
.table .span20 {
|
||||
float: none;
|
||||
width: 1564px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
table .span21 {
|
||||
.table .span21 {
|
||||
float: none;
|
||||
width: 1644px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
table .span22 {
|
||||
.table .span22 {
|
||||
float: none;
|
||||
width: 1724px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
table .span23 {
|
||||
.table .span23 {
|
||||
float: none;
|
||||
width: 1804px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
table .span24 {
|
||||
.table .span24 {
|
||||
float: none;
|
||||
width: 1884px;
|
||||
margin-left: 0;
|
||||
|
@ -2025,10 +2116,30 @@ table .span24 {
|
|||
background-color: #f2dede;
|
||||
}
|
||||
|
||||
.table tbody tr.warning td {
|
||||
background-color: #fcf8e3;
|
||||
}
|
||||
|
||||
.table tbody tr.info td {
|
||||
background-color: #d9edf7;
|
||||
}
|
||||
|
||||
.table-hover tbody tr.success:hover td {
|
||||
background-color: #d0e9c6;
|
||||
}
|
||||
|
||||
.table-hover tbody tr.error:hover td {
|
||||
background-color: #ebcccc;
|
||||
}
|
||||
|
||||
.table-hover tbody tr.warning:hover td {
|
||||
background-color: #faf2cc;
|
||||
}
|
||||
|
||||
.table-hover tbody tr.info:hover td {
|
||||
background-color: #c4e3f3;
|
||||
}
|
||||
|
||||
[class^="icon-"],
|
||||
[class*=" icon-"] {
|
||||
display: inline-block;
|
||||
|
@ -2046,8 +2157,14 @@ table .span24 {
|
|||
/* White icons with optional class, or on hover/active states of certain elements */
|
||||
|
||||
.icon-white,
|
||||
.nav > .active > a > [class^="icon-"],
|
||||
.nav > .active > a > [class*=" icon-"],
|
||||
.nav-tabs > .active > a > [class^="icon-"],
|
||||
.nav-tabs > .active > a > [class*=" icon-"],
|
||||
.nav-pills > .active > a > [class^="icon-"],
|
||||
.nav-pills > .active > a > [class*=" icon-"],
|
||||
.nav-list > .active > a > [class^="icon-"],
|
||||
.nav-list > .active > a > [class*=" icon-"],
|
||||
.navbar-inverse .nav > .active > a > [class^="icon-"],
|
||||
.navbar-inverse .nav > .active > a > [class*=" icon-"],
|
||||
.dropdown-menu > li > a:hover > [class^="icon-"],
|
||||
.dropdown-menu > li > a:hover > [class*=" icon-"],
|
||||
.dropdown-menu > .active > a > [class^="icon-"],
|
||||
|
@ -2759,7 +2876,7 @@ table .span24 {
|
|||
.navbar-fixed-bottom .dropdown .caret {
|
||||
border-top: 0;
|
||||
border-bottom: 4px solid #000000;
|
||||
content: "\2191";
|
||||
content: "";
|
||||
}
|
||||
|
||||
.dropup .dropdown-menu,
|
||||
|
@ -2783,7 +2900,7 @@ table .span24 {
|
|||
border-radius: 0 6px 6px 6px;
|
||||
}
|
||||
|
||||
.dropdown-submenu:hover .dropdown-menu {
|
||||
.dropdown-submenu:hover > .dropdown-menu {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
@ -2866,7 +2983,6 @@ table .span24 {
|
|||
position: relative;
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
overflow: visible \9;
|
||||
-webkit-transition: height 0.35s ease;
|
||||
-moz-transition: height 0.35s ease;
|
||||
-o-transition: height 0.35s ease;
|
||||
|
@ -3030,7 +3146,7 @@ button.close {
|
|||
.btn-mini {
|
||||
padding: 2px 6px;
|
||||
font-size: 11px;
|
||||
line-height: 16px;
|
||||
line-height: 17px;
|
||||
}
|
||||
|
||||
.btn-block {
|
||||
|
@ -3047,6 +3163,12 @@ button.close {
|
|||
margin-top: 5px;
|
||||
}
|
||||
|
||||
input[type="submit"].btn-block,
|
||||
input[type="reset"].btn-block,
|
||||
input[type="button"].btn-block {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.btn-primary.active,
|
||||
.btn-warning.active,
|
||||
.btn-danger.active,
|
||||
|
@ -3284,7 +3406,8 @@ input[type="submit"].btn.btn-mini {
|
|||
}
|
||||
|
||||
.btn-link,
|
||||
.btn-link:active {
|
||||
.btn-link:active,
|
||||
.btn-link[disabled] {
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
-webkit-box-shadow: none;
|
||||
|
@ -3307,11 +3430,17 @@ input[type="submit"].btn.btn-mini {
|
|||
background-color: transparent;
|
||||
}
|
||||
|
||||
.btn-link[disabled]:hover {
|
||||
color: #333333;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
position: relative;
|
||||
*margin-left: .3em;
|
||||
font-size: 0;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.btn-group:first-child {
|
||||
|
@ -4018,7 +4147,7 @@ input[type="submit"].btn.btn-mini {
|
|||
*z-index: 2;
|
||||
margin-bottom: 20px;
|
||||
overflow: visible;
|
||||
color: #555555;
|
||||
color: #777777;
|
||||
}
|
||||
|
||||
.navbar-inner {
|
||||
|
@ -4037,11 +4166,23 @@ input[type="submit"].btn.btn-mini {
|
|||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);
|
||||
*zoom: 1;
|
||||
-webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
|
||||
-moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
|
||||
}
|
||||
|
||||
.navbar-inner:before,
|
||||
.navbar-inner:after {
|
||||
display: table;
|
||||
line-height: 0;
|
||||
content: "";
|
||||
}
|
||||
|
||||
.navbar-inner:after {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.navbar .container {
|
||||
width: auto;
|
||||
}
|
||||
|
@ -4057,7 +4198,7 @@ input[type="submit"].btn.btn-mini {
|
|||
margin-left: -20px;
|
||||
font-size: 20px;
|
||||
font-weight: 200;
|
||||
color: #555555;
|
||||
color: #777777;
|
||||
text-shadow: 0 1px 0 #ffffff;
|
||||
}
|
||||
|
||||
|
@ -4071,7 +4212,7 @@ input[type="submit"].btn.btn-mini {
|
|||
}
|
||||
|
||||
.navbar-link {
|
||||
color: #555555;
|
||||
color: #777777;
|
||||
}
|
||||
|
||||
.navbar-link:hover {
|
||||
|
@ -4087,11 +4228,13 @@ input[type="submit"].btn.btn-mini {
|
|||
|
||||
.navbar .btn,
|
||||
.navbar .btn-group {
|
||||
margin-top: 6px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.navbar .btn-group .btn {
|
||||
margin: 0;
|
||||
.navbar .btn-group .btn,
|
||||
.navbar .input-prepend .btn,
|
||||
.navbar .input-append .btn {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.navbar-form {
|
||||
|
@ -4182,9 +4325,12 @@ input[type="submit"].btn.btn-mini {
|
|||
}
|
||||
|
||||
.navbar-fixed-top .navbar-inner,
|
||||
.navbar-fixed-bottom .navbar-inner,
|
||||
.navbar-static-top .navbar-inner {
|
||||
border: 0;
|
||||
border-width: 0 0 1px;
|
||||
}
|
||||
|
||||
.navbar-fixed-bottom .navbar-inner {
|
||||
border-width: 1px 0 0;
|
||||
}
|
||||
|
||||
.navbar-fixed-top .navbar-inner,
|
||||
|
@ -4233,6 +4379,7 @@ input[type="submit"].btn.btn-mini {
|
|||
|
||||
.navbar .nav.pull-right {
|
||||
float: right;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.navbar .nav > li {
|
||||
|
@ -4242,7 +4389,7 @@ input[type="submit"].btn.btn-mini {
|
|||
.navbar .nav > li > a {
|
||||
float: none;
|
||||
padding: 10px 15px 10px;
|
||||
color: #555555;
|
||||
color: #777777;
|
||||
text-decoration: none;
|
||||
text-shadow: 0 1px 0 #ffffff;
|
||||
}
|
||||
|
@ -4372,8 +4519,8 @@ input[type="submit"].btn.btn-mini {
|
|||
}
|
||||
|
||||
.navbar .nav li.dropdown > .dropdown-toggle .caret {
|
||||
border-top-color: #555555;
|
||||
border-bottom-color: #555555;
|
||||
border-top-color: #777777;
|
||||
border-bottom-color: #777777;
|
||||
}
|
||||
|
||||
.navbar .nav li.dropdown.open > .dropdown-toggle .caret,
|
||||
|
@ -4599,12 +4746,12 @@ input[type="submit"].btn.btn-mini {
|
|||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.pagination li {
|
||||
.pagination ul > li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.pagination a,
|
||||
.pagination span {
|
||||
.pagination ul > li > a,
|
||||
.pagination ul > li > span {
|
||||
float: left;
|
||||
padding: 0 14px;
|
||||
line-height: 38px;
|
||||
|
@ -4614,36 +4761,36 @@ input[type="submit"].btn.btn-mini {
|
|||
border-left-width: 0;
|
||||
}
|
||||
|
||||
.pagination a:hover,
|
||||
.pagination .active a,
|
||||
.pagination .active span {
|
||||
.pagination ul > li > a:hover,
|
||||
.pagination ul > .active > a,
|
||||
.pagination ul > .active > span {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.pagination .active a,
|
||||
.pagination .active span {
|
||||
.pagination ul > .active > a,
|
||||
.pagination ul > .active > span {
|
||||
color: #999999;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.pagination .disabled span,
|
||||
.pagination .disabled a,
|
||||
.pagination .disabled a:hover {
|
||||
.pagination ul > .disabled > span,
|
||||
.pagination ul > .disabled > a,
|
||||
.pagination ul > .disabled > a:hover {
|
||||
color: #999999;
|
||||
cursor: default;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.pagination li:first-child a,
|
||||
.pagination li:first-child span {
|
||||
.pagination ul > li:first-child > a,
|
||||
.pagination ul > li:first-child > span {
|
||||
border-left-width: 1px;
|
||||
-webkit-border-radius: 3px 0 0 3px;
|
||||
-moz-border-radius: 3px 0 0 3px;
|
||||
border-radius: 3px 0 0 3px;
|
||||
}
|
||||
|
||||
.pagination li:last-child a,
|
||||
.pagination li:last-child span {
|
||||
.pagination ul > li:last-child > a,
|
||||
.pagination ul > li:last-child > span {
|
||||
-webkit-border-radius: 0 3px 3px 0;
|
||||
-moz-border-radius: 0 3px 3px 0;
|
||||
border-radius: 0 3px 3px 0;
|
||||
|
@ -4679,7 +4826,8 @@ input[type="submit"].btn.btn-mini {
|
|||
display: inline;
|
||||
}
|
||||
|
||||
.pager a {
|
||||
.pager a,
|
||||
.pager span {
|
||||
display: inline-block;
|
||||
padding: 5px 14px;
|
||||
background-color: #fff;
|
||||
|
@ -4694,7 +4842,8 @@ input[type="submit"].btn.btn-mini {
|
|||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.pager .next a {
|
||||
.pager .next a,
|
||||
.pager .next span {
|
||||
float: right;
|
||||
}
|
||||
|
||||
|
@ -4703,25 +4852,26 @@ input[type="submit"].btn.btn-mini {
|
|||
}
|
||||
|
||||
.pager .disabled a,
|
||||
.pager .disabled a:hover {
|
||||
.pager .disabled a:hover,
|
||||
.pager .disabled span {
|
||||
color: #999999;
|
||||
cursor: default;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.modal-open .dropdown-menu {
|
||||
.modal-open .modal .dropdown-menu {
|
||||
z-index: 2050;
|
||||
}
|
||||
|
||||
.modal-open .dropdown.open {
|
||||
.modal-open .modal .dropdown.open {
|
||||
*z-index: 2050;
|
||||
}
|
||||
|
||||
.modal-open .popover {
|
||||
.modal-open .modal .popover {
|
||||
z-index: 2060;
|
||||
}
|
||||
|
||||
.modal-open .tooltip {
|
||||
.modal-open .modal .tooltip {
|
||||
z-index: 2080;
|
||||
}
|
||||
|
||||
|
|
126
docs/static/css/drf-styles.css
vendored
Normal file
126
docs/static/css/drf-styles.css
vendored
Normal file
|
@ -0,0 +1,126 @@
|
|||
/* Set the body padding-top when above 980px to push the content down from
|
||||
below the navbar, which is fixed at >980px screen widths. */
|
||||
@media (min-width: 980px) {
|
||||
body {
|
||||
padding-top: 71px;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
pre {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
a.github {
|
||||
float: right;
|
||||
margin-top: -12px;
|
||||
}
|
||||
|
||||
a.github:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.dropdown .dropdown-menu {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.dropdown.open .dropdown-menu {
|
||||
display: block;
|
||||
}
|
||||
|
||||
body.index #main-content iframe {
|
||||
float: right;
|
||||
}
|
||||
|
||||
body.index #main-content iframe {
|
||||
float: right;
|
||||
margin-right: -15px;
|
||||
}
|
||||
|
||||
body.index #main-content p:first-of-type {
|
||||
float: right;
|
||||
margin-right: 8px;
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
#table-of-contents {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
pre {
|
||||
overflow: auto;
|
||||
word-wrap: normal;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
/* Preserve the spacing of the navbar across different screen sizes. */
|
||||
.navbar-inner {
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
@media (max-width: 979px) {
|
||||
.navbar .brand {
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
.navbar-inner .container-fluid {
|
||||
padding-left: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.nav-list li.main {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Set the table of contents to static so it flows back into the content when
|
||||
viewed on tablets and smaller. */
|
||||
@media (max-width: 767px) {
|
||||
#table-of-contents {
|
||||
position: static;
|
||||
}
|
||||
}
|
||||
|
||||
/* When the page is in two-column layout, give the main content some room
|
||||
to breath on the left. */
|
||||
@media (min-width: 768px) {
|
||||
#main-content {
|
||||
padding-left: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
blockquote {
|
||||
font-family: Georgia, serif;
|
||||
font-size: 18px;
|
||||
font-style: italic;
|
||||
margin: 0.25em 0;
|
||||
padding: 0.25em 40px;
|
||||
line-height: 1.45;
|
||||
position: relative;
|
||||
color: #383838;
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
blockquote:before {
|
||||
display: block;
|
||||
content: "\201C";
|
||||
font-size: 80px;
|
||||
position: absolute;
|
||||
left: -10px;
|
||||
top: -20px;
|
||||
color: #7a7a7a;
|
||||
}
|
||||
|
||||
blockquote p:last-child {
|
||||
color: #999999;
|
||||
font-size: 14px;
|
||||
display: block;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
30
docs/static/css/prettify.css
vendored
Normal file
30
docs/static/css/prettify.css
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
.com { color: #93a1a1; }
|
||||
.lit { color: #195f91; }
|
||||
.pun, .opn, .clo { color: #93a1a1; }
|
||||
.fun { color: #dc322f; }
|
||||
.str, .atv { color: #D14; }
|
||||
.kwd, .prettyprint .tag { color: #1e347b; }
|
||||
.typ, .atn, .dec, .var { color: teal; }
|
||||
.pln { color: #48484c; }
|
||||
|
||||
.prettyprint {
|
||||
padding: 8px;
|
||||
background-color: #f7f7f9;
|
||||
border: 1px solid #e1e1e8;
|
||||
}
|
||||
.prettyprint.linenums {
|
||||
-webkit-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0;
|
||||
-moz-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0;
|
||||
box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0;
|
||||
}
|
||||
|
||||
/* Specify class=linenums on a pre to get line numbering */
|
||||
ol.linenums {
|
||||
margin: 0 0 0 33px; /* IE indents via margin-left */
|
||||
}
|
||||
ol.linenums li {
|
||||
padding-left: 12px;
|
||||
color: #bebec5;
|
||||
line-height: 20px;
|
||||
text-shadow: 0 1px 0 #fff;
|
||||
}
|
BIN
docs/static/img/glyphicons-halflings-white.png
vendored
Normal file
BIN
docs/static/img/glyphicons-halflings-white.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.6 KiB |
BIN
docs/static/img/glyphicons-halflings.png
vendored
Normal file
BIN
docs/static/img/glyphicons-halflings.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
104
docs/static/js/bootstrap-affix.js
vendored
Executable file
104
docs/static/js/bootstrap-affix.js
vendored
Executable file
|
@ -0,0 +1,104 @@
|
|||
/* ==========================================================
|
||||
* bootstrap-affix.js v2.1.1
|
||||
* http://twitter.github.com/bootstrap/javascript.html#affix
|
||||
* ==========================================================
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ========================================================== */
|
||||
|
||||
|
||||
!function ($) {
|
||||
|
||||
"use strict"; // jshint ;_;
|
||||
|
||||
|
||||
/* AFFIX CLASS DEFINITION
|
||||
* ====================== */
|
||||
|
||||
var Affix = function (element, options) {
|
||||
this.options = $.extend({}, $.fn.affix.defaults, options)
|
||||
this.$window = $(window).on('scroll.affix.data-api', $.proxy(this.checkPosition, this))
|
||||
this.$element = $(element)
|
||||
this.checkPosition()
|
||||
}
|
||||
|
||||
Affix.prototype.checkPosition = function () {
|
||||
if (!this.$element.is(':visible')) return
|
||||
|
||||
var scrollHeight = $(document).height()
|
||||
, scrollTop = this.$window.scrollTop()
|
||||
, position = this.$element.offset()
|
||||
, offset = this.options.offset
|
||||
, offsetBottom = offset.bottom
|
||||
, offsetTop = offset.top
|
||||
, reset = 'affix affix-top affix-bottom'
|
||||
, affix
|
||||
|
||||
if (typeof offset != 'object') offsetBottom = offsetTop = offset
|
||||
if (typeof offsetTop == 'function') offsetTop = offset.top()
|
||||
if (typeof offsetBottom == 'function') offsetBottom = offset.bottom()
|
||||
|
||||
affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ?
|
||||
false : offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ?
|
||||
'bottom' : offsetTop != null && scrollTop <= offsetTop ?
|
||||
'top' : false
|
||||
|
||||
if (this.affixed === affix) return
|
||||
|
||||
this.affixed = affix
|
||||
this.unpin = affix == 'bottom' ? position.top - scrollTop : null
|
||||
|
||||
this.$element.removeClass(reset).addClass('affix' + (affix ? '-' + affix : ''))
|
||||
}
|
||||
|
||||
|
||||
/* AFFIX PLUGIN DEFINITION
|
||||
* ======================= */
|
||||
|
||||
$.fn.affix = function (option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
, data = $this.data('affix')
|
||||
, options = typeof option == 'object' && option
|
||||
if (!data) $this.data('affix', (data = new Affix(this, options)))
|
||||
if (typeof option == 'string') data[option]()
|
||||
})
|
||||
}
|
||||
|
||||
$.fn.affix.Constructor = Affix
|
||||
|
||||
$.fn.affix.defaults = {
|
||||
offset: 0
|
||||
}
|
||||
|
||||
|
||||
/* AFFIX DATA-API
|
||||
* ============== */
|
||||
|
||||
$(window).on('load', function () {
|
||||
$('[data-spy="affix"]').each(function () {
|
||||
var $spy = $(this)
|
||||
, data = $spy.data()
|
||||
|
||||
data.offset = data.offset || {}
|
||||
|
||||
data.offsetBottom && (data.offset.bottom = data.offsetBottom)
|
||||
data.offsetTop && (data.offset.top = data.offsetTop)
|
||||
|
||||
$spy.affix(data)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
}(window.jQuery);
|
2
docs/static/js/bootstrap-alert.js
vendored
Normal file → Executable file
2
docs/static/js/bootstrap-alert.js
vendored
Normal file → Executable file
|
@ -1,5 +1,5 @@
|
|||
/* ==========================================================
|
||||
* bootstrap-alert.js v2.1.0
|
||||
* bootstrap-alert.js v2.1.1
|
||||
* http://twitter.github.com/bootstrap/javascript.html#alerts
|
||||
* ==========================================================
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
|
|
4
docs/static/js/bootstrap-button.js
vendored
Normal file → Executable file
4
docs/static/js/bootstrap-button.js
vendored
Normal file → Executable file
|
@ -1,5 +1,5 @@
|
|||
/* ============================================================
|
||||
* bootstrap-button.js v2.1.0
|
||||
* bootstrap-button.js v2.1.1
|
||||
* http://twitter.github.com/bootstrap/javascript.html#buttons
|
||||
* ============================================================
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
|
@ -51,7 +51,7 @@
|
|||
}
|
||||
|
||||
Button.prototype.toggle = function () {
|
||||
var $parent = this.$element.parent('[data-toggle="buttons-radio"]')
|
||||
var $parent = this.$element.closest('[data-toggle="buttons-radio"]')
|
||||
|
||||
$parent && $parent
|
||||
.find('.active')
|
||||
|
|
2
docs/static/js/bootstrap-carousel.js
vendored
Normal file → Executable file
2
docs/static/js/bootstrap-carousel.js
vendored
Normal file → Executable file
|
@ -1,5 +1,5 @@
|
|||
/* ==========================================================
|
||||
* bootstrap-carousel.js v2.1.0
|
||||
* bootstrap-carousel.js v2.1.1
|
||||
* http://twitter.github.com/bootstrap/javascript.html#carousel
|
||||
* ==========================================================
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
|
|
2
docs/static/js/bootstrap-collapse.js
vendored
Normal file → Executable file
2
docs/static/js/bootstrap-collapse.js
vendored
Normal file → Executable file
|
@ -1,5 +1,5 @@
|
|||
/* =============================================================
|
||||
* bootstrap-collapse.js v2.1.0
|
||||
* bootstrap-collapse.js v2.1.1
|
||||
* http://twitter.github.com/bootstrap/javascript.html#collapse
|
||||
* =============================================================
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
|
|
6
docs/static/js/bootstrap-dropdown.js
vendored
Normal file → Executable file
6
docs/static/js/bootstrap-dropdown.js
vendored
Normal file → Executable file
|
@ -1,5 +1,5 @@
|
|||
/* ============================================================
|
||||
* bootstrap-dropdown.js v2.1.0
|
||||
* bootstrap-dropdown.js v2.1.1
|
||||
* http://twitter.github.com/bootstrap/javascript.html#dropdowns
|
||||
* ============================================================
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
|
@ -110,7 +110,7 @@
|
|||
|
||||
if (!selector) {
|
||||
selector = $this.attr('href')
|
||||
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
|
||||
selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
|
||||
}
|
||||
|
||||
$parent = $(selector)
|
||||
|
@ -142,7 +142,7 @@
|
|||
$('html')
|
||||
.on('click.dropdown.data-api touchstart.dropdown.data-api', clearMenus)
|
||||
$('body')
|
||||
.on('click.dropdown touchstart.dropdown.data-api', '.dropdown', function (e) { e.stopPropagation() })
|
||||
.on('click.dropdown touchstart.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
|
||||
.on('click.dropdown.data-api touchstart.dropdown.data-api' , toggle, Dropdown.prototype.toggle)
|
||||
.on('keydown.dropdown.data-api touchstart.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
|
||||
})
|
||||
|
|
2
docs/static/js/bootstrap-modal.js
vendored
Normal file → Executable file
2
docs/static/js/bootstrap-modal.js
vendored
Normal file → Executable file
|
@ -1,5 +1,5 @@
|
|||
/* =========================================================
|
||||
* bootstrap-modal.js v2.1.0
|
||||
* bootstrap-modal.js v2.1.1
|
||||
* http://twitter.github.com/bootstrap/javascript.html#modals
|
||||
* =========================================================
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
|
|
2
docs/static/js/bootstrap-popover.js
vendored
Normal file → Executable file
2
docs/static/js/bootstrap-popover.js
vendored
Normal file → Executable file
|
@ -1,5 +1,5 @@
|
|||
/* ===========================================================
|
||||
* bootstrap-popover.js v2.1.0
|
||||
* bootstrap-popover.js v2.1.1
|
||||
* http://twitter.github.com/bootstrap/javascript.html#popovers
|
||||
* ===========================================================
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
|
|
2
docs/static/js/bootstrap-scrollspy.js
vendored
Normal file → Executable file
2
docs/static/js/bootstrap-scrollspy.js
vendored
Normal file → Executable file
|
@ -1,5 +1,5 @@
|
|||
/* =============================================================
|
||||
* bootstrap-scrollspy.js v2.1.0
|
||||
* bootstrap-scrollspy.js v2.1.1
|
||||
* http://twitter.github.com/bootstrap/javascript.html#scrollspy
|
||||
* =============================================================
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
|
|
2
docs/static/js/bootstrap-tab.js
vendored
Normal file → Executable file
2
docs/static/js/bootstrap-tab.js
vendored
Normal file → Executable file
|
@ -1,5 +1,5 @@
|
|||
/* ========================================================
|
||||
* bootstrap-tab.js v2.1.0
|
||||
* bootstrap-tab.js v2.1.1
|
||||
* http://twitter.github.com/bootstrap/javascript.html#tabs
|
||||
* ========================================================
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
|
|
2
docs/static/js/bootstrap-tooltip.js
vendored
Normal file → Executable file
2
docs/static/js/bootstrap-tooltip.js
vendored
Normal file → Executable file
|
@ -1,5 +1,5 @@
|
|||
/* ===========================================================
|
||||
* bootstrap-tooltip.js v2.1.0
|
||||
* bootstrap-tooltip.js v2.1.1
|
||||
* http://twitter.github.com/bootstrap/javascript.html#tooltips
|
||||
* Inspired by the original jQuery.tipsy by Jason Frame
|
||||
* ===========================================================
|
||||
|
|
2
docs/static/js/bootstrap-transition.js
vendored
Normal file → Executable file
2
docs/static/js/bootstrap-transition.js
vendored
Normal file → Executable file
|
@ -1,5 +1,5 @@
|
|||
/* ===================================================
|
||||
* bootstrap-transition.js v2.1.0
|
||||
* bootstrap-transition.js v2.1.1
|
||||
* http://twitter.github.com/bootstrap/javascript.html#transitions
|
||||
* ===================================================
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
|
|
4
docs/static/js/bootstrap-typeahead.js
vendored
Normal file → Executable file
4
docs/static/js/bootstrap-typeahead.js
vendored
Normal file → Executable file
|
@ -1,5 +1,5 @@
|
|||
/* =============================================================
|
||||
* bootstrap-typeahead.js v2.1.0
|
||||
* bootstrap-typeahead.js v2.1.1
|
||||
* http://twitter.github.com/bootstrap/javascript.html#typeahead
|
||||
* =============================================================
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
|
@ -174,7 +174,7 @@
|
|||
.on('keypress', $.proxy(this.keypress, this))
|
||||
.on('keyup', $.proxy(this.keyup, this))
|
||||
|
||||
if ($.browser.webkit || $.browser.msie) {
|
||||
if ($.browser.chrome || $.browser.webkit || $.browser.msie) {
|
||||
this.$element.on('keydown', $.proxy(this.keydown, this))
|
||||
}
|
||||
|
||||
|
|
2
docs/static/js/jquery-1.8.1-min.js
vendored
Normal file
2
docs/static/js/jquery-1.8.1-min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
4
docs/static/js/jquery.js
vendored
4
docs/static/js/jquery.js
vendored
File diff suppressed because one or more lines are too long
28
docs/static/js/prettify.js
vendored
Normal file
28
docs/static/js/prettify.js
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;
|
||||
(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a=
|
||||
[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c<i;++c){var j=f[c];if(/\\[bdsw]/i.test(j))a.push(j);else{var j=m(j),d;c+2<i&&"-"===f[c+1]?(d=m(f[c+2]),c+=2):d=j;b.push([j,d]);d<65||j>122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;c<b.length;++c)i=b[c],i[0]<=j[1]+1?j[1]=Math.max(j[1],i[1]):f.push(j=i);b=["["];o&&b.push("^");b.push.apply(b,a);for(c=0;c<
|
||||
f.length;++c)i=f[c],b.push(e(i[0])),i[1]>i[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c<b;++c){var j=f[c];j==="("?++i:"\\"===j.charAt(0)&&(j=+j.substring(1))&&j<=i&&(d[j]=-1)}for(c=1;c<d.length;++c)-1===d[c]&&(d[c]=++t);for(i=c=0;c<b;++c)j=f[c],j==="("?(++i,d[i]===void 0&&(f[c]="(?:")):"\\"===j.charAt(0)&&
|
||||
(j=+j.substring(1))&&j<=i&&(f[c]="\\"+d[i]);for(i=c=0;c<b;++c)"^"===f[c]&&"^"!==f[c+1]&&(f[c]="");if(a.ignoreCase&&s)for(c=0;c<b;++c)j=f[c],a=j.charAt(0),j.length>=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p<d;++p){var g=a[p];if(g.ignoreCase)l=!0;else if(/[a-z]/i.test(g.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){s=!0;l=!1;break}}for(var r=
|
||||
{b:8,t:9,n:10,v:11,f:12,r:13},n=[],p=0,d=a.length;p<d;++p){g=a[p];if(g.global||g.multiline)throw Error(""+g);n.push("(?:"+y(g)+")")}return RegExp(n.join("|"),l?"gi":"g")}function M(a){function m(a){switch(a.nodeType){case 1:if(e.test(a.className))break;for(var g=a.firstChild;g;g=g.nextSibling)m(g);g=a.nodeName;if("BR"===g||"LI"===g)h[s]="\n",t[s<<1]=y++,t[s++<<1|1]=a;break;case 3:case 4:g=a.nodeValue,g.length&&(g=p?g.replace(/\r\n?/g,"\n"):g.replace(/[\t\n\r ]+/g," "),h[s]=g,t[s<<1]=y,y+=g.length,
|
||||
t[s++<<1|1]=a)}}var e=/(?:^|\s)nocode(?:\s|$)/,h=[],y=0,t=[],s=0,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=document.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);m(a);return{a:h.join("").replace(/\n$/,""),c:t}}function B(a,m,e,h){m&&(a={a:m,d:a},e(a),h.push.apply(h,a.e))}function x(a,m){function e(a){for(var l=a.d,p=[l,"pln"],d=0,g=a.a.match(y)||[],r={},n=0,z=g.length;n<z;++n){var f=g[n],b=r[f],o=void 0,c;if(typeof b===
|
||||
"string")c=!1;else{var i=h[f.charAt(0)];if(i)o=f.match(i[1]),b=i[0];else{for(c=0;c<t;++c)if(i=m[c],o=f.match(i[1])){b=i[0];break}o||(b="pln")}if((c=b.length>=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m),
|
||||
l=[],p={},d=0,g=e.length;d<g;++d){var r=e[d],n=r[3];if(n)for(var k=n.length;--k>=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,
|
||||
q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/,
|
||||
q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g,
|
||||
"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a),
|
||||
a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e}
|
||||
for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g<d.length;++g)e(d[g]);m===(m|0)&&d[0].setAttribute("value",
|
||||
m);var r=s.createElement("OL");r.className="linenums";for(var n=Math.max(0,m-1|0)||0,g=0,z=d.length;g<z;++g)l=d[g],l.className="L"+(g+n)%10,l.firstChild||l.appendChild(s.createTextNode("\xa0")),r.appendChild(l);a.appendChild(r)}function k(a,m){for(var e=m.length;--e>=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*</.test(m)?"default-markup":"default-code";return A[a]}function E(a){var m=
|
||||
a.g;try{var e=M(a.h),h=e.a;a.a=h;a.c=e.c;a.d=0;C(m,h)(a);var k=/\bMSIE\b/.test(navigator.userAgent),m=/\n/g,t=a.a,s=t.length,e=0,l=a.c,p=l.length,h=0,d=a.e,g=d.length,a=0;d[g]=s;var r,n;for(n=r=0;n<g;)d[n]!==d[n+2]?(d[r++]=d[n++],d[r++]=d[n++]):n+=2;g=r;for(n=r=0;n<g;){for(var z=d[n],f=d[n+1],b=n+2;b+2<=g&&d[b+1]===f;)b+=2;d[r++]=z;d[r++]=f;n=b}for(d.length=r;h<p;){var o=l[h+2]||s,c=d[a+2]||s,b=Math.min(o,c),i=l[h+1],j;if(i.nodeType!==1&&(j=t.substring(e,b))){k&&(j=j.replace(m,"\r"));i.nodeValue=
|
||||
j;var u=i.ownerDocument,v=u.createElement("SPAN");v.className=d[a+1];var x=i.parentNode;x.replaceChild(v,i);v.appendChild(i);e<o&&(l[h+1]=i=u.createTextNode(t.substring(b,o)),x.insertBefore(i,v.nextSibling))}e=b;e>=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],
|
||||
"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"],
|
||||
H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],
|
||||
J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+
|
||||
I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),
|
||||
["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",
|
||||
/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),
|
||||
["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes",
|
||||
hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p<h.length&&l.now()<e;p++){var n=h[p],k=n.className;if(k.indexOf("prettyprint")>=0){var k=k.match(g),f,b;if(b=
|
||||
!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p<h.length?setTimeout(m,
|
||||
250):a&&a()}for(var e=[document.getElementsByTagName("pre"),document.getElementsByTagName("code"),document.getElementsByTagName("xmp")],h=[],k=0;k<e.length;++k)for(var t=0,s=e[k].length;t<s;++t)h.push(e[k][t]);var e=q,l=Date;l.now||(l={now:function(){return+new Date}});var p=0,d,g=/\blang(?:uage)?-([\w.]+)(?!\S)/;m()};window.PR={createSimpleLexer:x,registerLangHandler:k,sourceDecorator:u,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",
|
||||
PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ"}})();
|
|
@ -7,54 +7,16 @@
|
|||
<meta name="author" content="">
|
||||
|
||||
<!-- Le styles -->
|
||||
<link href="{{ base_url }}/css/prettify.css" rel="stylesheet">
|
||||
<link href="{{ base_url }}/css/bootstrap.css" rel="stylesheet">
|
||||
<style type="text/css">
|
||||
body {
|
||||
padding-top: 60px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
.sidebar-nav {
|
||||
padding: 9px 0;
|
||||
}
|
||||
.nav-list li.main {
|
||||
font-weight: bold;
|
||||
}
|
||||
blockquote {
|
||||
font-family: Georgia, serif;
|
||||
font-size: 18px;
|
||||
font-style: italic;
|
||||
margin: 0.25em 0;
|
||||
padding: 0.25em 40px;
|
||||
line-height: 1.45;
|
||||
position: relative;
|
||||
color: #383838;
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
blockquote:before {
|
||||
display: block;
|
||||
content: "\201C";
|
||||
font-size: 80px;
|
||||
position: absolute;
|
||||
left: -10px;
|
||||
top: -20px;
|
||||
color: #7a7a7a;
|
||||
}
|
||||
|
||||
blockquote p:last-child {
|
||||
color: #999999;
|
||||
font-size: 14px;
|
||||
display: block;
|
||||
margin-top: 5px;
|
||||
}
|
||||
</style>
|
||||
<link href="{{ base_url }}/css/bootstrap-responsive.css" rel="stylesheet">
|
||||
<link href="{{ base_url }}/css/drf-styles.css" rel="stylesheet">
|
||||
|
||||
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<body>
|
||||
<body onload="prettyPrint()" class="{{ page_id }}">
|
||||
|
||||
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="navbar-inner">
|
||||
|
@ -108,14 +70,14 @@ margin-top: 5px;
|
|||
</li>
|
||||
</ul>
|
||||
<ul class="nav pull-right">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="#">Trunk</a></li>
|
||||
<li><a href="#">2.0.0</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="#">Trunk</a></li>
|
||||
<li><a href="#">2.0.0</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div>
|
||||
</div>
|
||||
|
@ -123,16 +85,16 @@ margin-top: 5px;
|
|||
|
||||
<div class="container-fluid">
|
||||
<div class="row-fluid">
|
||||
<div class="span3">
|
||||
<div class="well affix span3">
|
||||
<ul class="nav nav-list side-nav">
|
||||
{{ toc }}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="span3">
|
||||
<div id="table-of-contents" class="well affix span3">
|
||||
<ul class="nav nav-list side-nav">
|
||||
{{ toc }}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="span9">
|
||||
{{ content }}
|
||||
<div id="main-content" class="span9">
|
||||
{{ content }}
|
||||
</div><!--/span-->
|
||||
</div><!--/row-->
|
||||
</div><!--/.fluid-container-->
|
||||
|
@ -140,13 +102,15 @@ margin-top: 5px;
|
|||
<!-- Le javascript
|
||||
================================================== -->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
<script src="{{ base_url }}/js/jquery.js"></script>
|
||||
<script src="{{ base_url }}/js/jquery-1.8.1-min.js"></script>
|
||||
<script src="{{ base_url }}/js/prettify.js"></script>
|
||||
<script src="{{ base_url }}/js/bootstrap-dropdown.js"></script>
|
||||
<script src="{{ base_url }}/js/bootstrap-scrollspy.js"></script>
|
||||
<script src="{{ base_url }}/js/bootstrap-collapse.js"></script>
|
||||
<script>
|
||||
//$('.side-nav').scrollspy()
|
||||
var shiftWindow = function() { scrollBy(0, -50) };
|
||||
if (location.hash) shiftWindow();
|
||||
window.addEventListener("hashchange", shiftWindow);
|
||||
//$('.side-nav').scrollspy()
|
||||
var shiftWindow = function() { scrollBy(0, -50) };
|
||||
if (location.hash) shiftWindow();
|
||||
window.addEventListener("hashchange", shiftWindow);
|
||||
</script>
|
||||
</body></html>
|
|
@ -2,43 +2,44 @@
|
|||
|
||||
The following people have helped make REST framework great.
|
||||
|
||||
* Tom Christie <tomchristie>
|
||||
* Marko Tibold <markotibold>
|
||||
* Paul Bagwell <pbgwl>
|
||||
* Sébastien Piquemal <sebpiq>
|
||||
* Carmen Wick <cwick>
|
||||
* Alex Ehlke <aehlke>
|
||||
* Alen Mujezinovic <flashingpumpkin>
|
||||
* Carles Barrobés <txels>
|
||||
* Michael Fötsch <mfoetsch>
|
||||
* David Larlet <david>
|
||||
* Andrew Straw <astraw>
|
||||
* Zeth <zeth>
|
||||
* Fernando Zunino <fzunino>
|
||||
* Jens Alm <ulmus>
|
||||
* Craig Blaszczyk <jakul>
|
||||
* Garcia Solero <garciasolero>
|
||||
* Tom Drummond <devioustree>
|
||||
* Danilo Bargen <gwrtheyrn>
|
||||
* Andrew McCloud <amccloud>
|
||||
* Thomas Steinacher <thomasst>
|
||||
* Meurig Freeman <meurig>
|
||||
* Anthony Nemitz <anemitz>
|
||||
* Ewoud Kohl van Wijngaarden <ekohl>
|
||||
* Michael Ding <yandy>
|
||||
* Mjumbe Poe <mjumbewu>
|
||||
* Natim <natim>
|
||||
* Sebastian Żurek <sebzur>
|
||||
* Benoit C <dzen>
|
||||
* Chris Pickett <bunchesofdonald>
|
||||
* Ben Timby <btimby>
|
||||
* Michele Lazzeri <michelelazzeri-nextage>
|
||||
* Camille Harang <mammique>
|
||||
* Paul Oswald <poswald>
|
||||
* Sean C. Farley <scfarley>
|
||||
* Daniel Izquierdo <izquierdo>
|
||||
* Can Yavuz <tschan>
|
||||
* Shawn Lewis <shawnlewis>
|
||||
* Tom Christie - [tomchristie]
|
||||
* Marko Tibold - [markotibold]
|
||||
* Paul Bagwell - [pbgwl]
|
||||
* Sébastien Piquemal - [sebpiq]
|
||||
* Carmen Wick - [cwick]
|
||||
* Alex Ehlke - [aehlke]
|
||||
* Alen Mujezinovic - [flashingpumpkin]
|
||||
* Carles Barrobés - [txels]
|
||||
* Michael Fötsch - [mfoetsch]
|
||||
* David Larlet - [david]
|
||||
* Andrew Straw - [astraw]
|
||||
* Zeth - [zeth]
|
||||
* Fernando Zunino - [fzunino]
|
||||
* Jens Alm - [ulmus]
|
||||
* Craig Blaszczyk - [jakul]
|
||||
* Garcia Solero - [garciasolero]
|
||||
* Tom Drummond - [devioustree]
|
||||
* Danilo Bargen - [gwrtheyrn]
|
||||
* Andrew McCloud - [amccloud]
|
||||
* Thomas Steinacher - [thomasst]
|
||||
* Meurig Freeman - [meurig]
|
||||
* Anthony Nemitz - [anemitz]
|
||||
* Ewoud Kohl van Wijngaarden - [ekohl]
|
||||
* Michael Ding - [yandy]
|
||||
* Mjumbe Poe - [mjumbewu]
|
||||
* Natim - [natim]
|
||||
* Sebastian Żurek - [sebzur]
|
||||
* Benoit C - [dzen]
|
||||
* Chris Pickett - [bunchesofdonald]
|
||||
* Ben Timby - [btimby]
|
||||
* Michele Lazzeri - [michelelazzeri-nextage]
|
||||
* Camille Harang - [mammique]
|
||||
* Paul Oswald - [poswald]
|
||||
* Sean C. Farley - [scfarley]
|
||||
* Daniel Izquierdo - [izquierdo]
|
||||
* Can Yavuz - [tschan]
|
||||
* Shawn Lewis - [shawnlewis]
|
||||
* Alec Perkins - [alecperkins]
|
||||
|
||||
Many thanks to everyone who's contributed to the project.
|
||||
|
||||
|
@ -55,11 +56,49 @@ Continuous integration testing is managed with [Travis CI][travis-ci].
|
|||
To contact the author directly:
|
||||
|
||||
* twitter: [@_tomchristie][twitter]
|
||||
* mail: [tom@tomchristie.com][email]
|
||||
* email: [tom@tomchristie.com][email]
|
||||
|
||||
[email]: mailto:tom@tomchristie.com
|
||||
[twitter]: http://twitter.com/_tomchristie
|
||||
[bootstrap]: http://twitter.github.com/bootstrap/
|
||||
[markdown]: http://daringfireball.net/projects/markdown/
|
||||
[github]: github.com/tomchristie/django-rest-framework
|
||||
[travis-ci]: https://secure.travis-ci.org/tomchristie/django-rest-framework
|
||||
[travis-ci]: https://secure.travis-ci.org/tomchristie/django-rest-framework
|
||||
[tomchristie]: https://github.com/tomchristie
|
||||
[markotibold]: https://github.com/markotibold
|
||||
[pbgwl]: https://github.com/pbgwl
|
||||
[sebpiq]: https://github.com/sebpiq
|
||||
[cwick]: https://github.com/cwick
|
||||
[aehlke]: https://github.com/aehlke
|
||||
[flashingpumpkin]: https://github.com/flashingpumpkin
|
||||
[txels]: https://github.com/txels
|
||||
[mfoetsch]: https://github.com/mfoetsch
|
||||
[david]: https://github.com/david
|
||||
[astraw]: https://github.com/astraw
|
||||
[zeth]: https://github.com/zeth
|
||||
[fzunino]: https://github.com/fzunino
|
||||
[ulmus]: https://github.com/ulmus
|
||||
[jakul]: https://github.com/jakul
|
||||
[garciasolero]: https://github.com/garciasolero
|
||||
[devioustree]: https://github.com/devioustree
|
||||
[gwrtheyrn]: https://github.com/gwrtheyrn
|
||||
[amccloud]: https://github.com/amccloud
|
||||
[thomasst]: https://github.com/thomasst
|
||||
[meurig]: https://github.com/meurig
|
||||
[anemitz]: https://github.com/anemitz
|
||||
[ekohl]: https://github.com/ekohl
|
||||
[yandy]: https://github.com/yandy
|
||||
[mjumbewu]: https://github.com/mjumbewu
|
||||
[natim]: https://github.com/natim
|
||||
[sebzur]: https://github.com/sebzur
|
||||
[dzen]: https://github.com/dzen
|
||||
[bunchesofdonald]: https://github.com/bunchesofdonald
|
||||
[btimby]: https://github.com/btimby
|
||||
[michelelazzeri-nextage]: https://github.com/michelelazzeri-nextage
|
||||
[mammique]: https://github.com/mammique
|
||||
[poswald]: https://github.com/poswald
|
||||
[scfarley]: https://github.com/scfarley
|
||||
[izquierdo]: https://github.com/izquierdo
|
||||
[tschan]: https://github.com/tschan
|
||||
[shawnlewis]: https://github.com/shawnlewis
|
||||
[alecperkins]: https://github.com/alecperkins
|
||||
|
|
|
@ -8,6 +8,7 @@ This tutorial will walk you through the building blocks that make up REST framew
|
|||
|
||||
Before we do anything else we'll create a new virtual environment, using [virtualenv]. This will make sure our package configuration is keep nicely isolated from any other projects we're working on.
|
||||
|
||||
:::bash
|
||||
mkdir ~/env
|
||||
virtualenv --no-site-packages ~/env/tutorial
|
||||
source ~/env/tutorial/bin/activate
|
||||
|
|
|
@ -7,30 +7,31 @@ We can also write our API views using class based views, rather than function ba
|
|||
We'll start by rewriting the root view as a class based view. All this involves is a little bit of refactoring.
|
||||
|
||||
from blog.models import Comment
|
||||
from blog.serializers import ComentSerializer
|
||||
from blog.serializers import CommentSerializer
|
||||
from django.http import Http404
|
||||
from djangorestframework.views import APIView
|
||||
from djangorestframework.response import Response
|
||||
from djangorestframework.status import status
|
||||
from djangorestframework import status
|
||||
|
||||
|
||||
class CommentRoot(APIView):
|
||||
"""
|
||||
List all comments, or create a new comment.
|
||||
"""
|
||||
"""
|
||||
def get(self, request, format=None):
|
||||
comments = Comment.objects.all()
|
||||
serializer = ComentSerializer(instance=comments)
|
||||
serializer = CommentSerializer(instance=comments)
|
||||
return Response(serializer.data)
|
||||
|
||||
def post(self, request, format=None)
|
||||
serializer = ComentSerializer(request.DATA)
|
||||
def post(self, request, format=None):
|
||||
serializer = CommentSerializer(request.DATA)
|
||||
if serializer.is_valid():
|
||||
comment = serializer.object
|
||||
comment.save()
|
||||
return Response(serializer.serialized, status=HTTP_201_CREATED)
|
||||
return Response(serializer.serialized_errors, status=HTTP_400_BAD_REQUEST)
|
||||
return Response(serializer.serialized, status=status.HTTP_201_CREATED)
|
||||
return Response(serializer.serialized_errors, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
comment_root = CommentRoot.as_view()
|
||||
comment_root = CommentRoot.as_view()
|
||||
|
||||
So far, so good. It looks pretty similar to the previous case, but we've got better seperation between the different HTTP methods. We'll also need to update the instance view.
|
||||
|
||||
|
@ -38,18 +39,18 @@ So far, so good. It looks pretty similar to the previous case, but we've got be
|
|||
"""
|
||||
Retrieve, update or delete a comment instance.
|
||||
"""
|
||||
|
||||
|
||||
def get_object(self, pk):
|
||||
try:
|
||||
return Comment.objects.get(pk=pk)
|
||||
except Comment.DoesNotExist:
|
||||
raise Http404
|
||||
|
||||
|
||||
def get(self, request, pk, format=None):
|
||||
comment = self.get_object(pk)
|
||||
serializer = CommentSerializer(instance=comment)
|
||||
return Response(serializer.data)
|
||||
|
||||
|
||||
def put(self, request, pk, format=None):
|
||||
comment = self.get_object(pk)
|
||||
serializer = CommentSerializer(request.DATA, instance=comment)
|
||||
|
@ -64,7 +65,7 @@ So far, so good. It looks pretty similar to the previous case, but we've got be
|
|||
comment.delete()
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
comment_instance = CommentInstance.as_view()
|
||||
comment_instance = CommentInstance.as_view()
|
||||
|
||||
That's looking good. Again, it's still pretty similar to the function based view right now.
|
||||
Okay, we're done. If you run the development server everything should be working just as before.
|
||||
|
|
|
@ -44,6 +44,6 @@ We've reached the end of our tutorial. If you want to get more involved in the
|
|||
|
||||
* Contribute on GitHub by reviewing issues, and submitting issues or pull requests.
|
||||
* Join the REST framework group, and help build the community.
|
||||
* Follow me on Twitter and say hi.
|
||||
* Follow me [on Twitter](https://twitter.com/_tomchristie) and say hi.
|
||||
|
||||
Now go build something great.
|
|
@ -24,11 +24,12 @@ else:
|
|||
|
||||
main_header = '<li class="main"><a href="#{{ anchor }}">{{ title }}</a></li>'
|
||||
sub_header = '<li><a href="#{{ anchor }}">{{ title }}</a></li>'
|
||||
code_label = r'<a class="github" href="https://github.com/tomchristie/django-rest-framework/blob/restframework2/djangorestframework/\1"><span class="label label-info">\1</span></a>'
|
||||
|
||||
page = open(os.path.join(docs_dir, 'template.html'), 'r').read()
|
||||
|
||||
# Copy static files
|
||||
for static in ['css', 'js']:
|
||||
for static in ['css', 'js', 'img']:
|
||||
source = os.path.join(docs_dir, 'static', static)
|
||||
target = os.path.join(html_dir, static)
|
||||
if os.path.exists(target):
|
||||
|
@ -65,5 +66,9 @@ for (dirpath, dirnames, filenames) in os.walk(docs_dir):
|
|||
if not os.path.exists(build_dir):
|
||||
os.makedirs(build_dir)
|
||||
output = page.replace('{{ content }}', content).replace('{{ toc }}', toc).replace('{{ base_url }}', base_url).replace('{{ suffix }}', suffix).replace('{{ index }}', index)
|
||||
output = output.replace('{{ page_id }}', filename[:-3])
|
||||
output = re.sub(r'a href="([^"]*)\.md"', r'a href="\1%s"' % suffix, output)
|
||||
output = re.sub(r'<pre><code>:::bash', r'<pre class="prettyprint lang-bsh">', output)
|
||||
output = re.sub(r'<pre>', r'<pre class="prettyprint lang-py">', output)
|
||||
output = re.sub(r'<a class="github" href="([^"]*)"></a>', code_label, output)
|
||||
open(build_file, 'w').write(output.encode('utf-8'))
|
||||
|
|
Loading…
Reference in New Issue
Block a user