diff options
| author | Tom Christie | 2013-04-30 19:32:34 +0100 | 
|---|---|---|
| committer | Tom Christie | 2013-04-30 19:32:34 +0100 | 
| commit | 22af28d146f2c4caccafafc78603ce20ffd76425 (patch) | |
| tree | 8dbf025ea1efaf257417b4a7c94263f0688c2786 | |
| parent | 7eba12fd28766971a25491a9360aaf0fda684a0f (diff) | |
| parent | 5d357a9b0807311b97de1e999be588f36fcd5b2f (diff) | |
| download | django-rest-framework-22af28d146f2c4caccafafc78603ce20ffd76425.tar.bz2 | |
Merge master
| -rw-r--r-- | docs/api-guide/permissions.md | 7 | ||||
| -rw-r--r-- | docs/topics/browsable-api.md | 11 | ||||
| -rw-r--r-- | docs/topics/credits.md | 4 | ||||
| -rw-r--r-- | docs/topics/release-notes.md | 4 | ||||
| -rw-r--r-- | rest_framework/serializers.py | 14 | ||||
| -rw-r--r-- | rest_framework/templates/rest_framework/login.html | 54 | ||||
| -rw-r--r-- | rest_framework/templates/rest_framework/login_base.html | 55 | ||||
| -rw-r--r-- | rest_framework/tests/serializer.py | 31 | 
8 files changed, 103 insertions, 77 deletions
diff --git a/docs/api-guide/permissions.md b/docs/api-guide/permissions.md index 5dbaf338..db0d4b26 100644 --- a/docs/api-guide/permissions.md +++ b/docs/api-guide/permissions.md @@ -21,7 +21,12 @@ If any permission check fails an `exceptions.PermissionDenied` exception will be  REST framework permissions also support object-level permissioning.  Object level permissions are used to determine if a user should be allowed to act on a particular object, which will typically be a model instance. -Object level permissions are run by REST framework's generic views when `.get_object()` is called.  As with view level permissions, an `exceptions.PermissionDenied` exception will be raised if the user is not allowed to act on the given object. +Object level permissions are run by REST framework's generic views when `.get_object()` is called. +As with view level permissions, an `exceptions.PermissionDenied` exception will be raised if the user is not allowed to act on the given object. + +If you're writing your own views and want to enforce object level permissions, +you'll need to explicitly call the `.check_object_permissions(request, obj)` method on the view at the point at which you've retrieved the object. +This will either raise a `PermissionDenied` or `NotAuthenticated` exception, or simply return if the view has the appropriate permissions.  ## Setting the permission policy diff --git a/docs/topics/browsable-api.md b/docs/topics/browsable-api.md index 5f80c4f9..8ee01824 100644 --- a/docs/topics/browsable-api.md +++ b/docs/topics/browsable-api.md @@ -60,6 +60,17 @@ All of the [Bootstrap components][bcomponents] are available.  The browsable API makes use of the Bootstrap tooltips component. Any element with the `js-tooltip` class and a `title` attribute has that title content displayed in a tooltip on hover after a 1000ms delay. +### Login Template + +To add branding and customize the look-and-feel of the auth login template, create a template called `login.html` and add it to your project, eg: `templates/rest_framework/login.html`, that extends the `rest_framework/base_login.html` template. + +You can add your site name or branding by including the branding block: + +    {% block branding %} +        <h3 style="margin: 0 0 20px;">My Site Name</h3> +    {% endblock %} +     +You can also customize the style by adding the `bootstrap_theme` or `style` block similar to `api.html`.  ### Advanced Customization diff --git a/docs/topics/credits.md b/docs/topics/credits.md index da49e521..7b8a428e 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -116,6 +116,8 @@ The following people have helped make REST framework great.  * Victor Shih - [vshih]  * Atle Frenvik Sveen - [atlefren]  * J. Paul Reed - [preed] +* Matt Majewski - [forgingdestiny] +* Jerome Chen - [chenjyw]  Many thanks to everyone who's contributed to the project. @@ -266,3 +268,5 @@ You can also contact [@_tomchristie][twitter] directly on twitter.  [vshih]: https://github.com/vshih  [atlefren]: https://github.com/atlefren  [preed]: https://github.com/preed +[forgingdestiny]: https://github.com/forgingdestiny +[chenjyw]: https://github.com/chenjyw diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 84d45a00..9b10a342 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -55,6 +55,10 @@ You can determine your currently installed version using `pip freeze`:  ## 2.2.x series +### Master + +* Made Login template more easy to restyle. +  ### 2.2.7  **Date**: 17th April 2013 diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 0f943d79..b589eca8 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -218,18 +218,6 @@ class BaseSerializer(WritableField):          return ret      ##### -    # Field methods - used when the serializer class is itself used as a field. - -    def initialize(self, parent, field_name): -        """ -        Same behaviour as usual Field, except that we need to keep track -        of state so that we can deal with handling maximum depth. -        """ -        super(BaseSerializer, self).initialize(parent, field_name) -        if parent.opts.depth: -            self.opts.depth = parent.opts.depth - 1 - -    #####      # Methods to convert or revert from objects <--> primitive representations.      def get_field_key(self, field_name): @@ -683,6 +671,8 @@ class ModelSerializer(Serializer):          class NestedModelSerializer(ModelSerializer):              class Meta:                  model = related_model +                depth = self.opts.depth - 1 +          return NestedModelSerializer(many=to_many)      def get_related_field(self, model_field, related_model, to_many): diff --git a/rest_framework/templates/rest_framework/login.html b/rest_framework/templates/rest_framework/login.html index e10ce20f..b7629327 100644 --- a/rest_framework/templates/rest_framework/login.html +++ b/rest_framework/templates/rest_framework/login.html @@ -1,53 +1,3 @@ -{% load url from future %} -{% load rest_framework %} -<html> +{% extends "rest_framework/login_base.html" %} -    <head> -        <link rel="stylesheet" type="text/css" href="{% static "rest_framework/css/bootstrap.min.css" %}"/> -        <link rel="stylesheet" type="text/css" href="{% static "rest_framework/css/bootstrap-tweaks.css" %}"/> -        <link rel="stylesheet" type="text/css" href="{% static "rest_framework/css/default.css" %}"/> -    </head> - -    <body class="container"> - -<div class="container-fluid" style="margin-top: 30px"> -        <div class="row-fluid"> -          -        <div class="well" style="width: 320px; margin-left: auto; margin-right: auto"> -            <div class="row-fluid"> -                <div> -                    <h3 style="margin: 0 0 20px;">Django REST framework</h3> -                </div> -            </div><!-- /row fluid --> - -            <div class="row-fluid"> -                <div> -                    <form action="{% url 'rest_framework:login' %}" class=" form-inline" method="post"> -                        {% csrf_token %} -                        <div id="div_id_username" class="clearfix control-group"> -                            <div class="controls"> -                                <Label class="span4">Username:</label> -                                <input style="height: 25px" type="text" name="username" maxlength="100" autocapitalize="off" autocorrect="off" class="textinput textInput" id="id_username"> -                            </div> -                        </div> -                        <div id="div_id_password" class="clearfix control-group"> -                            <div class="controls"> -                                <Label class="span4">Password:</label> -                                <input style="height: 25px" type="password" name="password" maxlength="100" autocapitalize="off" autocorrect="off" class="textinput textInput" id="id_password"> -                            </div> -                        </div> -                        <input type="hidden" name="next" value="{{ next }}" /> -                        <div class="form-actions-no-box"> -                            <input type="submit" name="submit" value="Log in" class="btn btn-primary" id="submit-id-submit"> -                        </div> -                    </form> -                </div> -            </div><!-- /row fluid --> -        </div><!--/span--> - -        </div><!-- /.row-fluid --> -    </div> - -        </div> -    </body> -</html> +{# Override this template in your own templates directory to customize #} diff --git a/rest_framework/templates/rest_framework/login_base.html b/rest_framework/templates/rest_framework/login_base.html new file mode 100644 index 00000000..380d5820 --- /dev/null +++ b/rest_framework/templates/rest_framework/login_base.html @@ -0,0 +1,55 @@ +{% load url from future %} +{% load rest_framework %} +<html> + +    <head> +        {% block style %} +        {% block bootstrap_theme %}<link rel="stylesheet" type="text/css" href="{% static "rest_framework/css/bootstrap.min.css" %}"/>{% endblock %} +        <link rel="stylesheet" type="text/css" href="{% static "rest_framework/css/bootstrap-tweaks.css" %}"/> +        <link rel="stylesheet" type="text/css" href="{% static "rest_framework/css/default.css" %}"/> +        {% endblock %} +    </head> + +    <body class="container"> + +<div class="container-fluid" style="margin-top: 30px"> +        <div class="row-fluid"> +          +        <div class="well" style="width: 320px; margin-left: auto; margin-right: auto"> +            <div class="row-fluid"> +                <div> +                    {% block branding %}<h3 style="margin: 0 0 20px;">Django REST framework</h3>{% endblock %} +                </div> +            </div><!-- /row fluid --> + +            <div class="row-fluid"> +                <div> +                    <form action="{% url 'rest_framework:login' %}" class=" form-inline" method="post"> +                        {% csrf_token %} +                        <div id="div_id_username" class="clearfix control-group"> +                            <div class="controls"> +                                <Label class="span4">Username:</label> +                                <input style="height: 25px" type="text" name="username" maxlength="100" autocapitalize="off" autocorrect="off" class="textinput textInput" id="id_username"> +                            </div> +                        </div> +                        <div id="div_id_password" class="clearfix control-group"> +                            <div class="controls"> +                                <Label class="span4">Password:</label> +                                <input style="height: 25px" type="password" name="password" maxlength="100" autocapitalize="off" autocorrect="off" class="textinput textInput" id="id_password"> +                            </div> +                        </div> +                        <input type="hidden" name="next" value="{{ next }}" /> +                        <div class="form-actions-no-box"> +                            <input type="submit" name="submit" value="Log in" class="btn btn-primary" id="submit-id-submit"> +                        </div> +                    </form> +                </div> +            </div><!-- /row fluid --> +        </div><!--/span--> + +        </div><!-- /.row-fluid --> +    </div> + +        </div> +    </body> +</html> diff --git a/rest_framework/tests/serializer.py b/rest_framework/tests/serializer.py index ae8d09dc..84e1ee4e 100644 --- a/rest_framework/tests/serializer.py +++ b/rest_framework/tests/serializer.py @@ -3,7 +3,7 @@ from django.utils.datastructures import MultiValueDict  from django.test import TestCase  from rest_framework import serializers  from rest_framework.tests.models import (HasPositiveIntegerAsChoice, Album, ActionItem, Anchor, BasicModel, -    BlankFieldModel, BlogPost, Book, CallableDefaultValueModel, DefaultValueModel, +    BlankFieldModel, BlogPost, BlogPostComment, Book, CallableDefaultValueModel, DefaultValueModel,      ManyToManyModel, Person, ReadOnlyManyToManyModel, Photo)  import datetime  import pickle @@ -803,8 +803,6 @@ class RelatedTraversalTest(TestCase):          post = BlogPost.objects.create(title="Test blog post", writer=user)          post.blogpostcomment_set.create(text="I love this blog post") -        from rest_framework.tests.models import BlogPostComment -          class PersonSerializer(serializers.ModelSerializer):              class Meta:                  model = Person @@ -1004,23 +1002,26 @@ class SerializerPickleTests(TestCase):  class DepthTest(TestCase):      def test_implicit_nesting(self): +          writer = Person.objects.create(name="django", age=1)          post = BlogPost.objects.create(title="Test blog post", writer=writer) +        comment = BlogPostComment.objects.create(text="Test blog post comment", blog_post=post) -        class BlogPostSerializer(serializers.ModelSerializer): +        class BlogPostCommentSerializer(serializers.ModelSerializer):              class Meta: -                model = BlogPost -                depth = 1 +                model = BlogPostComment +                depth = 2 -        serializer = BlogPostSerializer(instance=post) -        expected = {'id': 1, 'title': 'Test blog post', -                    'writer': {'id': 1, 'name': 'django', 'age': 1}} +        serializer = BlogPostCommentSerializer(instance=comment) +        expected = {'id': 1, 'text': 'Test blog post comment', 'blog_post': {'id': 1, 'title': 'Test blog post', +                    'writer': {'id': 1, 'name': 'django', 'age': 1}}}          self.assertEqual(serializer.data, expected)      def test_explicit_nesting(self):          writer = Person.objects.create(name="django", age=1)          post = BlogPost.objects.create(title="Test blog post", writer=writer) +        comment = BlogPostComment.objects.create(text="Test blog post comment", blog_post=post)          class PersonSerializer(serializers.ModelSerializer):              class Meta: @@ -1032,9 +1033,15 @@ class DepthTest(TestCase):              class Meta:                  model = BlogPost -        serializer = BlogPostSerializer(instance=post) -        expected = {'id': 1, 'title': 'Test blog post', -                    'writer': {'id': 1, 'name': 'django', 'age': 1}} +        class BlogPostCommentSerializer(serializers.ModelSerializer): +            blog_post = BlogPostSerializer() + +            class Meta: +                model = BlogPostComment + +        serializer = BlogPostCommentSerializer(instance=comment) +        expected = {'id': 1, 'text': 'Test blog post comment', 'blog_post': {'id': 1, 'title': 'Test blog post', +                    'writer': {'id': 1, 'name': 'django', 'age': 1}}}          self.assertEqual(serializer.data, expected)  | 
