mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-01-23 15:54:16 +03:00
Merge master
This commit is contained in:
commit
22af28d146
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -217,18 +217,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.
|
||||
|
||||
|
@ -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):
|
||||
|
|
|
@ -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 #}
|
||||
|
|
55
rest_framework/templates/rest_framework/login_base.html
Normal file
55
rest_framework/templates/rest_framework/login_base.html
Normal file
|
@ -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>
|
|
@ -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)
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user