Merge remote-tracking branch 'upstream/master'

This commit is contained in:
khamaileon 2014-08-10 19:33:42 +02:00
commit 8c1d93a166
80 changed files with 375 additions and 57 deletions

View File

@ -8,7 +8,7 @@ python:
- "3.4"
env:
- DJANGO="https://www.djangoproject.com/download/1.7.b4/tarball/"
- DJANGO="https://www.djangoproject.com/download/1.7c2/tarball/"
- DJANGO="django==1.6.5"
- DJANGO="django==1.5.8"
- DJANGO="django==1.4.13"
@ -16,15 +16,13 @@ env:
install:
- pip install $DJANGO
- pip install defusedxml==0.3 Pillow==2.3.0
- pip install defusedxml==0.3 Pillow==2.3.0 django-guardian==1.2.3
- "if [[ ${TRAVIS_PYTHON_VERSION::1} != '3' ]]; then pip install oauth2==1.5.211; fi"
- "if [[ ${TRAVIS_PYTHON_VERSION::1} != '3' ]]; then pip install django-oauth-plus==2.2.4; fi"
- "if [[ ${TRAVIS_PYTHON_VERSION::1} != '3' ]]; then pip install django-oauth2-provider==0.2.4; fi"
- "if [[ ${TRAVIS_PYTHON_VERSION::1} != '3' ]]; then pip install django-guardian==1.1.1; fi"
- "if [[ ${DJANGO::11} == 'django==1.3' ]]; then pip install django-filter==0.5.4; fi"
- "if [[ ${DJANGO::11} != 'django==1.3' ]]; then pip install django-filter==0.7; fi"
- "if [[ ${TRAVIS_PYTHON_VERSION::1} == '3' ]]; then pip install -e git+https://github.com/linovia/django-guardian.git@feature/django_1_7#egg=django-guardian-1.2.0; fi"
- "if [[ ${DJANGO} == 'https://www.djangoproject.com/download/1.7.b4/tarball/' ]]; then pip install -e git+https://github.com/linovia/django-guardian.git@feature/django_1_7#egg=django-guardian-1.2.0; fi"
- "if [[ ${DJANGO} == 'https://www.djangoproject.com/download/1.7c2/tarball/' ]]; then pip install -e git+https://github.com/linovia/django-guardian.git@feature/django_1_7#egg=django-guardian-1.2.0; fi"
- export PYTHONPATH=.
script:
@ -33,7 +31,7 @@ script:
matrix:
exclude:
- python: "2.6"
env: DJANGO="https://www.djangoproject.com/download/1.7.b4/tarball/"
env: DJANGO="https://www.djangoproject.com/download/1.7c2/tarball/"
- python: "3.2"
env: DJANGO="django==1.4.13"
- python: "3.2"

View File

@ -1,3 +1,13 @@
---
#### Django REST framework 3 - Kickstarter announcement!
We are currently running a Kickstarter campaign to help fund the development of Django REST framework 3.
If you want to help drive sustainable open-source development forward, then **please check out [the Kickstarter project](https://www.kickstarter.com/projects/tomchristie/django-rest-framework-3) and consider funding us.**
---
# Django REST framework
[![build-status-image]][travis]
@ -136,6 +146,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.
[build-status-image]: https://secure.travis-ci.org/tomchristie/django-rest-framework.png?branch=master
[travis]: http://travis-ci.org/tomchristie/django-rest-framework?branch=master
[twitter]: https://twitter.com/_tomchristie

View File

@ -347,7 +347,7 @@ As an example, let's create a field that can be used represent the class name of
"""
Serialize the object's class name.
"""
return obj.__class__
return obj.__class__.__name__
# Third party packages
@ -357,9 +357,20 @@ The following third party packages are also available.
The [drf-compound-fields][drf-compound-fields] package provides "compound" serializer fields, such as lists of simple values, which can be described by other fields rather than serializers with the `many=True` option. Also provided are fields for typed dictionaries and values that can be either a specific type or a list of items of that type.
## DRF Extra Fields
The [drf-extra-fields][drf-extra-fields] package provides extra serializer fields for REST framework, including `Base64ImageField` and `PointField` classes.
## django-rest-framework-gis
The [django-rest-framework-gis][django-rest-framework-gis] package provides geographic addons for django rest framework like a `GeometryField` field and a GeoJSON serializer.
[cite]: https://docs.djangoproject.com/en/dev/ref/forms/api/#django.forms.Form.cleaned_data
[FILE_UPLOAD_HANDLERS]: https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-FILE_UPLOAD_HANDLERS
[ecma262]: http://ecma-international.org/ecma-262/5.1/#sec-15.9.1.15
[strftime]: http://docs.python.org/2/library/datetime.html#strftime-and-strptime-behavior
[iso8601]: http://www.w3.org/TR/NOTE-datetime
[drf-compound-fields]: http://drf-compound-fields.readthedocs.org
[drf-extra-fields]: https://github.com/Hipo/drf-extra-fields
[django-rest-framework-gis]: https://github.com/djangonauts/django-rest-framework-gis

View File

@ -199,8 +199,7 @@ This enables us to make queries like:
http://example.com/api/products?manufacturer__name=foo
This is nice, but it shows underlying model structure in REST API, which may
be undesired, but you can use:
This is nice, but it exposes the Django's double underscore convention as part of the API. If you instead want to explicitly name the filter argument you can instead explicitly include it on the `FilterSet` class:
import django_filters
from myapp.models import Product
@ -208,7 +207,6 @@ be undesired, but you can use:
from rest_framework import generics
class ProductFilter(django_filters.FilterSet):
manufacturer = django_filters.CharFilter(name="manufacturer__name")
class Meta:

View File

@ -36,6 +36,12 @@ For example:
self.check_object_permissions(self.request, obj)
return obj
#### Limitations of object level permissions
For performance reasons the generic views will not automatically apply object level permissions to each instance in a queryset when returning a list of objects.
Often when you're using object level permissions you'll also want to [filter the queryset][filtering] appropriately, to ensure that users only have visibility onto instances that they are permitted to view.
## Setting the permission policy
The default permission policy may be set globally, using the `DEFAULT_PERMISSION_CLASSES` setting. For example.
@ -237,7 +243,8 @@ The [REST Condition][rest-condition] package is another extension for building c
[cite]: https://developer.apple.com/library/mac/#documentation/security/Conceptual/AuthenticationAndAuthorizationGuide/Authorization/Authorization.html
[authentication]: authentication.md
[throttling]: throttling.md
[contribauth]: https://docs.djangoproject.com/en/1.0/topics/auth/#permissions
[filtering]: filtering.md
[contribauth]: https://docs.djangoproject.com/en/dev/topics/auth/customizing/#custom-permissions
[objectpermissions]: https://docs.djangoproject.com/en/dev/topics/auth/customizing/#handling-object-permissions
[guardian]: https://github.com/lukaszb/django-guardian
[get_objects_for_user]: http://pythonhosted.org/django-guardian/api/guardian.shortcuts.html#get-objects-for-user

View File

@ -179,7 +179,16 @@ The [wq.db package][wq.db] provides an advanced [Router][wq.db-router] class (an
app.router.register_model(MyModel)
## DRF-extensions
The [`DRF-extensions` package][drf-extensions] provides [routers][drf-extensions-routers] for creating [nested viewsets][drf-extensions-nested-viewsets], [collection level controllers][drf-extensions-collection-level-controllers] with [customizable endpoint names][drf-extensions-customizable-endpoint-names].
[cite]: http://guides.rubyonrails.org/routing.html
[drf-nested-routers]: https://github.com/alanjds/drf-nested-routers
[wq.db]: http://wq.io/wq.db
[wq.db-router]: http://wq.io/docs/app.py
[drf-extensions]: http://chibisov.github.io/drf-extensions/docs/
[drf-extensions-routers]: http://chibisov.github.io/drf-extensions/docs/#routers
[drf-extensions-nested-viewsets]: http://chibisov.github.io/drf-extensions/docs/#nested-routes
[drf-extensions-collection-level-controllers]: http://chibisov.github.io/drf-extensions/docs/#collection-level-controllers
[drf-extensions-customizable-endpoint-names]: http://chibisov.github.io/drf-extensions/docs/#controller-endpoint-name

View File

@ -580,7 +580,21 @@ The following custom model serializer could be used as a base class for model se
def get_pk_field(self, model_field):
return None
---
# Third party packages
The following third party packages are also available.
## MongoengineModelSerializer
The [django-rest-framework-mongoengine][mongoengine] package provides a `MongoEngineModelSerializer` serializer class that supports using MongoDB as the storage layer for Django REST framework.
## GeoFeatureModelSerializer
The [django-rest-framework-gis][django-rest-framework-gis] package provides a `GeoFeatureModelSerializer` serializer class that supports GeoJSON both for read and write operations.
[cite]: https://groups.google.com/d/topic/django-users/sVFaOfQi4wY/discussion
[relations]: relations.md
[mongoengine]: https://github.com/umutbozkurt/django-rest-framework-mongoengine
[django-rest-framework-gis]: https://github.com/djangonauts/django-rest-framework-gis

View File

@ -58,7 +58,7 @@ using the `APIView` class based views.
Or, if you're using the `@api_view` decorator with function based views.
@api_view('GET')
@api_view(['GET'])
@throttle_classes([UserRateThrottle])
def example_view(request, format=None):
content = {

View File

@ -307,3 +307,76 @@ table {
.side-nav {
overflow-y: scroll;
}
ul.sponsor.diamond li a {
float: left;
width: 600px;
height: 20px;
text-align: center;
margin: 10px 70px;
padding: 300px 0 0 0;
background-position: 0 50%;
background-size: 600px auto;
background-repeat: no-repeat;
font-size: 200%;
}
@media (max-width: 1000px) {
ul.sponsor.diamond li a {
float: left;
width: 300px;
height: 20px;
text-align: center;
margin: 10px 40px;
padding: 300px 0 0 0;
background-position: 0 50%;
background-size: 280px auto;
background-repeat: no-repeat;
font-size: 150%;
}
}
ul.sponsor.platinum li a {
float: left;
width: 300px;
height: 20px;
text-align: center;
margin: 10px 40px;
padding: 300px 0 0 0;
background-position: 0 50%;
background-size: 280px auto;
background-repeat: no-repeat;
font-size: 150%;
}
ul.sponsor.gold li a {
float: left;
width: 130px;
height: 20px;
text-align: center;
margin: 10px 30px;
padding: 150px 0 0 0;
background-position: 0 50%;
background-size: 130px auto;
background-repeat: no-repeat;
font-size: 120%;
}
ul.sponsor.silver li a {
float: left;
width: 130px;
height: 20px;
text-align: center;
margin: 10px 30px;
padding: 150px 0 0 0;
background-position: 0 50%;
background-size: 130px auto;
background-repeat: no-repeat;
font-size: 120%;
}
ul.sponsor {
list-style: none;
display: block;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
docs/img/sponsors/2-sga.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

BIN
docs/img/sponsors/3-aba.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -9,6 +9,14 @@
---
#### Django REST framework 3 - Kickstarter announcement!
We are currently running a Kickstarter campaign to help fund the development of Django REST framework 3.
If you want to help drive sustainable open-source development **please [check out the Kickstarter project](https://www.kickstarter.com/projects/tomchristie/django-rest-framework-3) and consider funding us.**
---
<p>
<h1 style="position: absolute;
width: 1px;
@ -201,6 +209,7 @@ General guides to using REST framework.
* [2.0 Announcement][rest-framework-2-announcement]
* [2.2 Announcement][2.2-announcement]
* [2.3 Announcement][2.3-announcement]
* [Kickstarter Announcement][kickstarter-announcement]
* [Release Notes][release-notes]
* [Credits][credits]
@ -325,6 +334,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[rest-framework-2-announcement]: topics/rest-framework-2-announcement.md
[2.2-announcement]: topics/2.2-announcement.md
[2.3-announcement]: topics/2.3-announcement.md
[kickstarter-announcement]: topics/kickstarter-announcement.md
[release-notes]: topics/release-notes.md
[credits]: topics/credits.md

View File

@ -33,6 +33,21 @@
})();
</script>
<style>
span.fusion-wrap a {
display: block;
margin-top: 10px;
color: black;
}
a.fusion-poweredby {
display: block;
margin-top: 10px;
}
@media (max-width: 767px) {
div.promo {display: none;}
}
</style>
</head>
<body onload="prettyPrint()" class="{{ page_id }}-page">
@ -106,6 +121,7 @@
<li><a href="{{ base_url }}/topics/rest-framework-2-announcement{{ suffix }}">2.0 Announcement</a></li>
<li><a href="{{ base_url }}/topics/2.2-announcement{{ suffix }}">2.2 Announcement</a></li>
<li><a href="{{ base_url }}/topics/2.3-announcement{{ suffix }}">2.3 Announcement</a></li>
<li><a href="{{ base_url }}/topics/kickstarter-announcement{{ suffix }}">Kickstarter Announcement</a></li>
<li><a href="{{ base_url }}/topics/release-notes{{ suffix }}">Release Notes</a></li>
<li><a href="{{ base_url }}/topics/credits{{ suffix }}">Credits</a></li>
</ul>
@ -169,11 +185,9 @@
<div id="table-of-contents">
<ul class="nav nav-list side-nav well sidebar-nav-fixed">
{{ toc }}
<div>
{{ ad_block }}
</div>
<div class="promo">
{{ ad_block }}
</div>
</ul>
</div>
@ -199,6 +213,7 @@
<script src="{{ base_url }}/js/jquery-1.8.1-min.js"></script>
<script src="{{ base_url }}/js/prettify-1.0.js"></script>
<script src="{{ base_url }}/js/bootstrap-2.1.1-min.js"></script>
<script>
//$('.side-nav').scrollspy()
var shiftWindow = function() { scrollBy(0, -50) };

View File

@ -167,10 +167,10 @@ You can now add the `autocomplete_light.ChoiceWidget` widget to the serializer f
[bootstrap]: http://getbootstrap.com
[cerulean]: ../img/cerulean.png
[slate]: ../img/slate.png
[bcustomize]: http://twitter.github.com/bootstrap/customize.html#variables
[bcustomize]: http://getbootstrap.com/2.3.2/customize.html
[bswatch]: http://bootswatch.com/
[bcomponents]: http://twitter.github.com/bootstrap/components.html
[bcomponentsnav]: http://twitter.github.com/bootstrap/components.html#navbar
[bcomponents]: http://getbootstrap.com/2.3.2/components.html
[bcomponentsnav]: http://getbootstrap.com/2.3.2/components.html#navbar
[autocomplete-packages]: https://www.djangopackages.com/grids/g/auto-complete/
[django-autocomplete-light]: https://github.com/yourlabs/django-autocomplete-light
[django-autocomplete-light-install]: http://django-autocomplete-light.readthedocs.org/en/latest/#install

View File

@ -0,0 +1,143 @@
# Kickstarting Django REST framework 3
---
<iframe width="480" height="360" src="https://www.kickstarter.com/projects/tomchristie/django-rest-framework-3/widget/video.html" frameborder="0" scrolling="no"> </iframe>
---
In order to continue to drive the project forward, I'm launching a Kickstarter campaign to help fund the development of a major new release - Django REST framework 3.
## Project details
This new release will allow us to comprehensively address some of the shortcomings of the framework, and will aim to include the following:
* Faster, simpler and easier-to-use serializers.
* An alternative admin-style interface for the browsable API.
* Search and filtering controls made accessible in the browsable API.
* Alternative API pagination styles.
* Documentation around API versioning.
* Triage of outstanding tickets.
* Improving the ongoing quality and maintainability of the project.
Full details are available now on the [project page](https://www.kickstarter.com/projects/tomchristie/django-rest-framework-3).
If you're interested in helping make sustainable open source development a reality please [visit the Kickstarter page](https://www.kickstarter.com/projects/tomchristie/django-rest-framework-3) and consider funding the project.
I can't wait to see where this takes us!
Many thanks to everyone for your support so far,
Tom Christie :)
---
## Sponsors
We've now blazed way past all our goals, with a staggering £30,000 (~$50,000), meaning I'll be in a position to work on the project significantly beyond what we'd originally planned for. I owe a huge debt of gratitude to all the wonderful companies and individuals who have been backing the project so generously, and making this possible.
---
### Platinum sponsors
Our platinum sponsors have each made a hugely substantial contribution to the future development of Django REST framework, and I simply can't thank them enough.
<ul class="sponsor diamond">
<li><a href="https://www.eventbrite.com/" rel="nofollow" style="background-image:url(../img/sponsors/0-eventbrite.png);">Eventbrite</a></li>
</ul>
<ul class="sponsor platinum">
<li><a href="https://www.divio.ch/" rel="nofollow" style="background-image:url(../img/sponsors/1-divio.png);">Divio</a></li>
<li><a href="http://company.onlulu.com/en/" rel="nofollow" style="background-image:url(../img/sponsors/1-lulu.png);">Lulu</a></li>
<li><a href="https://p.ota.to/" rel="nofollow" style="background-image:url(../img/sponsors/1-potato.png);">Potato</a></li>
<li><a href="http://www.wiredrive.com/" rel="nofollow" style="background-image:url(../img/sponsors/1-wiredrive.png);">Wiredrive</a></li>
<li><a href="http://www.cyaninc.com/" rel="nofollow" style="background-image:url(../img/sponsors/1-cyan.png);">Cyan</a></li>
<li><a href="https://www.runscope.com/" rel="nofollow" style="background-image:url(../img/sponsors/1-runscope.png);">Runscope</a></li>
<li><a href="http://simpleenergy.com/" rel="nofollow" style="background-image:url(../img/sponsors/1-simple-energy.png);">Simple Energy</a></li>
<li><a href="http://vokalinteractive.com/" rel="nofollow" style="background-image:url(../img/sponsors/1-vokal_interactive.png);">VOKAL Interactive</a></li>
<li><a href="http://www.purplebit.com/" rel="nofollow" style="background-image:url(../img/sponsors/1-purplebit.png);">Purple Bit</a></li>
<li><a href="http://www.kuwaitnet.net/" rel="nofollow" style="background-image:url(../img/sponsors/1-kuwaitnet.png);">KuwaitNET</a></li>
</ul>
<div style="clear: both"></div>
---
### Gold sponsors
Our gold sponsors include companies large and small. Many thanks for their significant funding of the project and their commitment to sustainable open-source development.
<ul class="sponsor gold">
<li><a href="https://laterpay.net/" rel="nofollow" style="background-image:url(../img/sponsors/2-laterpay.png);">LaterPay</a></li>
<li><a href="https://www.schubergphilis.com/" rel="nofollow" style="background-image:url(../img/sponsors/2-schuberg_philis.png);">Schuberg Philis</a></li>
<li><a href="http://prorenata.se/" rel="nofollow" style="background-image:url(../img/sponsors/2-prorenata.png);">ProReNata AB</a></li>
<li><a href="https://www.sgawebsites.com/" rel="nofollow" style="background-image:url(../img/sponsors/2-sga.png);">SGA Websites</a></li>
<li><a href="http://www.sirono.com/" rel="nofollow" style="background-image:url(../img/sponsors/2-sirono.png);">Sirono</a></li>
<li><a href="http://www.vinta.com.br/" rel="nofollow" style="background-image:url(../img/sponsors/2-vinta.png);">Vinta Software Studio</a></li>
<li><a href="http://www.rapasso.nl/index.php/en" rel="nofollow" style="background-image:url(../img/sponsors/2-rapasso.png);">Rapasso</a></li>
<li><a href="https://mirusresearch.com/" rel="nofollow" style="background-image:url(../img/sponsors/2-mirus_research.png);">Mirus Research</a></li>
<li><a href="http://hipolabs.com" rel="nofollow" style="background-image:url(../img/sponsors/2-hipo.png);">Hipo</a></li>
<li><a href="http://www.byte.nl" rel="nofollow" style="background-image:url(../img/sponsors/2-byte.png);">Byte</a></li>
<li><a href="http://lightningkite.com/" rel="nofollow" style="background-image:url(../img/sponsors/2-lightning_kite.png);">Lightning Kite</a></li>
<li><a href="https://opbeat.com/" rel="nofollow" style="background-image:url(../img/sponsors/2-opbeat.png);">Opbeat</a></li>
<li><a href="https://koordinates.com" rel="nofollow" style="background-image:url(../img/sponsors/2-koordinates.png);">Koordinates</a></li>
<!--Xitij-->
<!--Howard-->
<li><a href="https://www.heroku.com/" rel="nofollow" style="background-image:url(../img/sponsors/2-heroku.png);">Heroku</a></li>
<li><a href="https://www.galileo-press.de/" rel="nofollow" style="background-image:url(../img/sponsors/2-galileo_press.png);">Galileo Press</a></li>
<li><a href="http://www.securitycompass.com/" rel="nofollow" style="background-image:url(../img/sponsors/2-security_compass.png);">Security Compass</a></li>
<li><a href="https://www.djangoproject.com/foundation/" rel="nofollow" style="background-image:url(../img/sponsors/2-django.png);">Django Software Foundation</a></li>
<li><a href="http://www.hipflaskapp.com" rel="nofollow" style="background-image:url(../img/sponsors/2-hipflask.png);">Hipflask</a></li>
<li><a href="http://www.crate.io/" rel="nofollow" style="background-image:url(../img/sponsors/2-crate.png);">Crate</a></li>
<li><a href="http://crypticocorp.com/" rel="nofollow" style="background-image:url(../img/sponsors/2-cryptico.png);">Cryptico Corp</a></li>
<li><a href="http://envisionlinux.org/blog" rel="nofollow">Envision Linux</a></li>
</ul>
<!--Name: Envision Linux text-->
<div style="clear: both;"></div>
---
### Silver sponsors
The serious financial contribution that our silver sponsors have made is very much appreciated. I'd like to say a particular thank&nbsp;you to individuals who have choosen to privately support the project at this level.
<ul class="sponsor silver">
<li><a href="http://www.imtapps.com/" rel="nofollow" style="background-image:url(../img/sponsors/3-imt_computer_services.png);">IMT Computer Services</a></li>
<li><a href="http://wildfish.com/" rel="nofollow" style="background-image:url(../img/sponsors/3-wildfish.png);">Wildfish</a></li>
<li><a href="http://www.thermondo.de/" rel="nofollow" style="background-image:url(../img/sponsors/3-thermondo-gmbh.png);">Thermondo GmbH</a></li>
<li><a href="http://providenz.fr/" rel="nofollow" style="background-image:url(../img/sponsors/3-providenz.png);">Providenz</a></li>
<li><a href="https://www.alwaysdata.com" rel="nofollow" style="background-image:url(../img/sponsors/3-alwaysdata.png);">alwaysdata.com</a></li>
<li><a href="http://www.triggeredmessaging.com/" rel="nofollow" style="background-image:url(../img/sponsors/3-triggered_messaging.png);">Triggered Messaging</a></li>
<!--Markus-->
<li><a href="https://garfo.io/" rel="nofollow" style="background-image:url(../img/sponsors/3-garfo.png);">Garfo</a></li>
<li><a href="https://goshippo.com/" rel="nofollow" style="background-image:url(../img/sponsors/3-shippo.png);">Shippo</a></li>
<!--Dylan-->
<li><a href="http://www.gizmag.com/" rel="nofollow" style="background-image:url(../img/sponsors/3-gizmag.png);">Gizmag</a></li>
<li><a href="http://www.tivix.com/" rel="nofollow" style="background-image:url(../img/sponsors/3-tivix.png);">Tivix</a></li>
<li><a href="http://www.safaribooksonline.com/" rel="nofollow" style="background-image:url(../img/sponsors/3-safari.png);">Safari</a></li>
<li><a href="http://brightloop.com/" rel="nofollow" style="background-image:url(../img/sponsors/3-brightloop.png);">Bright Loop</a></li>
<li><a href="http://www.aba-systems.com.au/" rel="nofollow" style="background-image:url(../img/sponsors/3-aba.png);">ABA Systems</a></li>
<li><a href="http://beefarm.ru/" rel="nofollow" style="background-image:url(../img/sponsors/3-beefarm.png);">beefarm.ru</a></li>
<li><a href="http://www.vzzual.com/" rel="nofollow" style="background-image:url(../img/sponsors/3-vzzual.png);">Vzzual.com</a></li>
<!--Vzzual-->
<!--Linovia-->
<li><a href="http://infinite-code.com/" rel="nofollow" style="background-image:url(../img/sponsors/3-infinite_code.png);">Infinite Code</a></li>
<!--Jon-->
<li><a href="https://www.pkgfarm.com/" rel="nofollow" style="background-image:url(../img/sponsors/3-pkgfarm.png);">PkgFarm</a></li>
<li><a href="http://life.tl/" rel="nofollow" style="background-image:url(../img/sponsors/3-life_the_game.png);">Life. The Game.</a></li>
<li><a href="http://blimp.io/" rel="nofollow" style="background-image:url(../img/sponsors/3-blimp.png);">Blimp</a></li>
<li><a href="http://pathwright.com" rel="nofollow" style="background-image:url(../img/sponsors/3-pathwright.png);">Pathwright</a></li>
<li><a href="http://fluxility.com/" rel="nofollow" style="background-image:url(../img/sponsors/3-fluxility.png);">Fluxility</a></li>
<li><a href="http://trackmaven.com/" rel="nofollow" style="background-image:url(../img/sponsors/3-trackmaven.png);">TrackMaven</a></li>
<li><a href="http://www.nephila.co.uk/" rel="nofollow" style="background-image:url(../img/sponsors/3-nephila.png);">Nephila</a></li>
<!--Haris-->
<li><a href="http://www.aditium.com/" rel="nofollow" style="background-image:url(../img/sponsors/3-aditium.png);">Aditium</a></li>
<!--Craig-->
</ul>
<div style="clear: both; padding-bottom: 20px;"></div>
**Individual contributions**: Paul Hallet, <a href="http://www.paulwhippconsulting.com/">Paul Whipp</a>, Jannis Leidel, <a href="http://spielmannsolutions.com/">Johannes Spielmann</a>, <a href="http://chrisheisel.com/">Chris Heisel</a>, Marwan Alsabbagh.

View File

@ -29,7 +29,7 @@ Unlike all our other API endpoints, we don't want to use JSON, but instead just
The other thing we need to consider when creating the code highlight view is that there's no existing concrete generic view that we can use. We're not returning an object instance, but instead a property of an object instance.
Instead of using a concrete generic view, we'll use the base class for representing instances, and create our own `.get()` method. In your snippets.views add:
Instead of using a concrete generic view, we'll use the base class for representing instances, and create our own `.get()` method. In your `snippets.views` add:
from rest_framework import renderers
from rest_framework.response import Response

View File

@ -162,8 +162,8 @@ for (dirpath, dirnames, filenames) in os.walk(docs_dir):
output = output.replace('{{ canonical_url }}', canonical_url)
if filename =='index.md':
output = output.replace('{{ ad_block }}', """<hr><p><strong>The team behind REST framework is launching a new API service.</strong></p>
<p>If you want to be first in line when we start issuing invitations, please <a href="http://brightapi.com">sign up here</a>.</p>""")
output = output.replace('{{ ad_block }}', """<hr/>
<script type="text/javascript" src="//cdn.fusionads.net/fusion.js?zoneid=1332&serve=C6SDP2Y&placement=djangorestframework" id="_fusionads_js"></script>""")
else:
output = output.replace('{{ ad_block }}', '')

View File

@ -310,6 +310,13 @@ class OAuth2Authentication(BaseAuthentication):
auth = get_authorization_header(request).split()
if len(auth) == 1:
msg = 'Invalid bearer header. No credentials provided.'
raise exceptions.AuthenticationFailed(msg)
elif len(auth) > 2:
msg = 'Invalid bearer header. Token string should not contain spaces.'
raise exceptions.AuthenticationFailed(msg)
if auth and auth[0].lower() == b'bearer':
access_token = auth[1]
elif 'access_token' in request.POST:
@ -319,13 +326,6 @@ class OAuth2Authentication(BaseAuthentication):
else:
return None
if len(auth) == 1:
msg = 'Invalid bearer header. No credentials provided.'
raise exceptions.AuthenticationFailed(msg)
elif len(auth) > 2:
msg = 'Invalid bearer header. Token string should not contain spaces.'
raise exceptions.AuthenticationFailed(msg)
return self.authenticate_credentials(request, access_token)
def authenticate_credentials(self, request, access_token):

View File

@ -48,12 +48,15 @@ try:
except ImportError:
django_filters = None
# guardian is optional
try:
# Django-guardian is optional. Import only if guardian is in INSTALLED_APPS
# Fixes (#1712). We keep the try/except for the test suite.
guardian = None
if 'guardian' in settings.INSTALLED_APPS:
try:
import guardian
import guardian.shortcuts # Fixes #1624
except ImportError:
guardian = None
except ImportError:
pass
# cStringIO only if it's available, otherwise StringIO

View File

@ -187,7 +187,7 @@ class Field(object):
def field_to_native(self, obj, field_name):
"""
Given and object and a field name, returns the value that should be
Given an object and a field name, returns the value that should be
serialized for that field.
"""
if obj is None:
@ -474,8 +474,12 @@ class CharField(WritableField):
self.validators.append(validators.MaxLengthValidator(max_length))
def from_native(self, value):
if isinstance(value, six.string_types) or value is None:
if isinstance(value, six.string_types):
return value
if value is None:
return ''
return smart_text(value)

View File

@ -116,6 +116,10 @@ class OrderingFilter(BaseFilterBackend):
def get_ordering(self, request):
"""
Ordering is set by a comma delimited ?ordering=... query parameter.
The `ordering` query parameter can be overridden by setting
the `ordering_param` value on the OrderingFilter or by
specifying an `ORDERING_PARAM` value in the API settings.
"""
params = request.QUERY_PARAMS.get(self.ordering_param)
if params:

View File

@ -5,6 +5,7 @@ it is initialized with unrendered data, instead of a pre-rendered string.
The appropriate renderer is called during Django's template response rendering.
"""
from __future__ import unicode_literals
import django
from django.core.handlers.wsgi import STATUS_CODE_TEXT
from django.template.response import SimpleTemplateResponse
from rest_framework.compat import six
@ -15,6 +16,9 @@ class Response(SimpleTemplateResponse):
An HttpResponse that allows its data to be rendered into
arbitrary media types.
"""
# TODO: remove that once Django 1.3 isn't supported
if django.VERSION >= (1, 4):
rendering_attrs = SimpleTemplateResponse.rendering_attrs + ['_closable_objects']
def __init__(self, data=None, status=200,
template_name=None, headers=None,

View File

@ -93,7 +93,7 @@
{% endif %}
{% if options_form %}
<form class="button-form" action="{{ request.get_full_path }}" method="POST" class="pull-right">
<form class="button-form" action="{{ request.get_full_path }}" method="POST">
{% csrf_token %}
<input type="hidden" name="{{ api_settings.FORM_METHOD_OVERRIDE }}" value="OPTIONS" />
<button class="btn btn-primary js-tooltip" title="Make an OPTIONS request on the {{ name }} resource">OPTIONS</button>
@ -101,7 +101,7 @@
{% endif %}
{% if delete_form %}
<form class="button-form" action="{{ request.get_full_path }}" method="POST" class="pull-right">
<form class="button-form" action="{{ request.get_full_path }}" method="POST">
{% csrf_token %}
<input type="hidden" name="{{ api_settings.FORM_METHOD_OVERRIDE }}" value="DELETE" />
<button class="btn btn-danger js-tooltip" title="Make a DELETE request on the {{ name }} resource">DELETE</button>

View File

@ -105,6 +105,7 @@ class Album(RESTFrameworkModel):
title = models.CharField(max_length=100, unique=True)
ref = models.CharField(max_length=10, unique=True, null=True, blank=True)
class Photo(RESTFrameworkModel):
description = models.TextField()
album = models.ForeignKey(Album)
@ -112,7 +113,8 @@ class Photo(RESTFrameworkModel):
# Model for issue #324
class BlankFieldModel(RESTFrameworkModel):
title = models.CharField(max_length=100, blank=True, null=False)
title = models.CharField(max_length=100, blank=True, null=False,
default="title")
# Model for issue #380

View File

@ -549,6 +549,15 @@ class OAuth2Tests(TestCase):
response = self.csrf_client.get('/oauth2-test/', HTTP_AUTHORIZATION=auth)
self.assertEqual(response.status_code, 401)
@unittest.skipUnless(oauth2_provider, 'django-oauth2-provider not installed')
def test_get_form_with_wrong_authorization_header_token_missing(self):
"""Ensure that a missing token lead to the correct HTTP error status code"""
auth = "Bearer"
response = self.csrf_client.get('/oauth2-test/', {}, HTTP_AUTHORIZATION=auth)
self.assertEqual(response.status_code, 401)
response = self.csrf_client.get('/oauth2-test/', HTTP_AUTHORIZATION=auth)
self.assertEqual(response.status_code, 401)
@unittest.skipUnless(oauth2_provider, 'django-oauth2-provider not installed')
def test_get_form_passing_auth(self):
"""Ensure GETing form over OAuth with correct client credentials succeed"""

View File

@ -1236,6 +1236,9 @@ class BlankFieldTests(TestCase):
def test_create_model_null_field(self):
serializer = self.model_serializer_class(data={'title': None})
self.assertEqual(serializer.is_valid(), True)
serializer.save()
self.assertIsNot(serializer.object.pk, None)
self.assertEqual(serializer.object.title, '')
def test_create_not_blank_field(self):
"""

32
tox.ini
View File

@ -12,34 +12,34 @@ commands = {envpython} rest_framework/runtests/runtests.py
[testenv:py3.4-django1.7]
basepython = python3.4
deps = https://www.djangoproject.com/download/1.7b2/tarball/
deps = https://www.djangoproject.com/download/1.7c2/tarball/
django-filter==0.7
defusedxml==0.3
Pillow==2.3.0
[testenv:py3.3-django1.7]
basepython = python3.3
deps = https://www.djangoproject.com/download/1.7b2/tarball/
deps = https://www.djangoproject.com/download/1.7c2/tarball/
django-filter==0.7
defusedxml==0.3
Pillow==2.3.0
[testenv:py3.2-django1.7]
basepython = python3.2
deps = https://www.djangoproject.com/download/1.7b2/tarball/
deps = https://www.djangoproject.com/download/1.7c2/tarball/
django-filter==0.7
defusedxml==0.3
Pillow==2.3.0
[testenv:py2.7-django1.7]
basepython = python2.7
deps = https://www.djangoproject.com/download/1.7b2/tarball/
deps = https://www.djangoproject.com/download/1.7c2/tarball/
django-filter==0.7
defusedxml==0.3
django-oauth-plus==2.2.1
oauth2==1.5.211
django-oauth2-provider==0.2.4
django-guardian==1.1.1
# django-oauth-plus==2.2.1
# oauth2==1.5.211
# django-oauth2-provider==0.2.4
django-guardian==1.2.3
Pillow==2.3.0
[testenv:py3.4-django1.6]
@ -71,7 +71,7 @@ deps = Django==1.6.3
django-oauth-plus==2.2.1
oauth2==1.5.211
django-oauth2-provider==0.2.4
django-guardian==1.1.1
django-guardian==1.2.3
Pillow==2.3.0
[testenv:py2.6-django1.6]
@ -82,7 +82,7 @@ deps = Django==1.6.3
django-oauth-plus==2.2.1
oauth2==1.5.211
django-oauth2-provider==0.2.4
django-guardian==1.1.1
django-guardian==1.2.3
Pillow==2.3.0
[testenv:py3.4-django1.5]
@ -114,7 +114,7 @@ deps = django==1.5.6
django-oauth-plus==2.2.1
oauth2==1.5.211
django-oauth2-provider==0.2.3
django-guardian==1.1.1
django-guardian==1.2.3
Pillow==2.3.0
[testenv:py2.6-django1.5]
@ -125,7 +125,7 @@ deps = django==1.5.6
django-oauth-plus==2.2.1
oauth2==1.5.211
django-oauth2-provider==0.2.3
django-guardian==1.1.1
django-guardian==1.2.3
Pillow==2.3.0
[testenv:py2.7-django1.4]
@ -136,7 +136,7 @@ deps = django==1.4.11
django-oauth-plus==2.2.1
oauth2==1.5.211
django-oauth2-provider==0.2.3
django-guardian==1.1.1
django-guardian==1.2.3
Pillow==2.3.0
[testenv:py2.6-django1.4]
@ -147,7 +147,7 @@ deps = django==1.4.11
django-oauth-plus==2.2.1
oauth2==1.5.211
django-oauth2-provider==0.2.3
django-guardian==1.1.1
django-guardian==1.2.3
Pillow==2.3.0
[testenv:py2.7-django1.3]
@ -158,7 +158,7 @@ deps = django==1.3.5
django-oauth-plus==2.2.1
oauth2==1.5.211
django-oauth2-provider==0.2.3
django-guardian==1.1.1
django-guardian==1.2.3
Pillow==2.3.0
[testenv:py2.6-django1.3]
@ -169,5 +169,5 @@ deps = django==1.3.5
django-oauth-plus==2.2.1
oauth2==1.5.211
django-oauth2-provider==0.2.3
django-guardian==1.1.1
django-guardian==1.2.3
Pillow==2.3.0