Merge branch 'master' into localizedfloatfield

This commit is contained in:
kgeorgy 2017-03-14 15:32:15 +01:00 committed by GitHub
commit 7daa6880a3
19 changed files with 128 additions and 56 deletions

View File

@ -67,8 +67,7 @@ REST framework is a *collaboratively funded project*. If you use
REST framework commercially we strongly encourage you to invest in its
continued development by **[signing up for a paid plan][funding]**.
The initial aim is to provide a single full-time position on REST framework.
*Every single sign-up makes a significant impact towards making that possible.*
*Every single sign-up helps us make REST framework long-term financially sustainable.*
<ul class="premium-promo promo">
<li><a href="http://jobs.rover.com/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/rover_130x130.png)">Rover.com</a></li>

View File

@ -97,10 +97,6 @@ form.signup {
# Funding
> As a direct result of [a successful Mozilla grant application](mozilla-grant.md), I will be leaving my current role at [DabApps](http://www.dabapps.com), and attempting to secure a sustainable business model for REST framework development. I need your help in order to make this work.
>
> &mdash; Tom Christie
If you use REST framework commercially we strongly encourage you to invest in its continued development by signing up for a paid plan.
**We believe that collaboratively funded software can offer outstanding returns on investment, by encouraging our users to collectively share the cost of development.**
@ -115,36 +111,51 @@ REST framework continues to be open-source and permissively licensed, but we fir
---
## Making the business case
## What funding has enabled so far
Our [successful Kickstarter campaign](https://www.kickstarter.com/projects/tomchristie/django-rest-framework-3) demonstrates the impressive cost-reward ratio of shared funding of open-source software.
* The [3.4](http://www.django-rest-framework.org/topics/3.4-announcement/) and [3.5](http://www.django-rest-framework.org/topics/3.5-announcement/) releases, including schema generation for both Swagger and RAML, a Python client library, a Command Line client, and addressing of a large number of outstanding issues.
* The [3.6](http://www.django-rest-framework.org/topics/3.6-announcement/) release, including JavaScript client library, and API documentation, complete with auto-generated code samples.
* Tom Christie, the creator of Django REST framework, working on the project full-time.
* Around 80-90 issues and pull requests closed per month since Tom Christie started working on the project full-time.
* A community & operations manager position part-time for 4 months, helping mature the business and grow sponsorship.
* Contracting development time for the work on the JavaScript client library and API documentation tooling.
With *typical corporate fundings of just £100-£1000 per organization* we successfully delivered:
---
* The comprehensive serializer redesign, and **version 3.0 release**.
* Ongoing triage and community support, **closing over 1600 tickets**.
* Substantial improvements to the Browsable API.
* The admin interface.
* A new pagination API including offset/limit and cursor pagination implementations, plus on-page controls.
* A versioning API, including URL-based and header-based versioning schemes.
* Support for customizable exception handling.
* Support for Django's PostgreSQL HStoreField, ArrayField and JSONField.
* Templated HTML form support, including HTML forms with nested list and objects.
* Internationalization support for API responses, currently with 27 languages.
* The metadata APIs for handling `OPTIONS` requests and schema endpoints.
* Numerous minor improvements and better quality throughout the codebase.
## What future funding will enable
This incredible level of return on investment is *only possible through collaboratively funded models*, which is why we believe that supporting our paid plans is in everyone's best interest.
* Realtime API support, using WebSockets. This will consist of documentation and support for using REST framework together with Django Channels, plus integrating WebSocket support into the client libraries.
* Better authentication defaults, possibly bringing JWT & CORs support into the core package.
* Securing the community & operations manager position long-term.
* Opening up and securing a part-time position to focus on ticket triage and resolution.
* Paying for development time on building API client libraries in a range of programming languages. These would be integrated directly into the upcoming API documentation.
Sign up for a paid plan today, and help ensure that REST framework becomes a sustainable, full-time funded project.
---
## Freelancer plan
## What our sponsors and users say
This subscription is recommended for freelancers and other individuals with an interest in seeing REST framework continue to&nbsp;improve.
> As a developer, Django REST framework feels like an obvious and natural extension to all the great things that make up Django and it's community. Getting started is easy while providing simple abstractions which makes it flexible and customizable. Contributing and supporting Django REST framework helps ensure its future and one way or another it also helps Django, and the Python ecosystem.
>
> &mdash; José Padilla, Django REST framework contributor
If you are using REST framework as an full-time employee, consider recommending that your company takes out a [corporate&nbsp;plan](#corporate-plans).
> The number one feature of the Python programming language is its community. Such a community is only possible because of the Open Source nature of the language and all the culture that comes from it. Building great Open Source projects require great minds. Given that, we at Vinta are not only proud to sponsor the team behind DRF but we also recognize the ROI that comes from it.
>
> &mdash; Filipe Ximenes, Vinta Software
> It's really awesome that this project continues to endure. The code base is top notch and the maintainers are committed to the highest level of quality.
DRF is one of the core reasons why Django is top choice among web frameworks today. In my opinion, it sets the standard for rest frameworks for the development community at large.
>
> &mdash; agconti, Django REST framework user
---
## Individual plan
This subscription is recommended for individuals with an interest in seeing REST framework continue to&nbsp;improve.
If you are using REST framework as a full-time employee, consider recommending that your company takes out a [corporate&nbsp;plan](#corporate-plans).
<div class="pricing">
<div class="span4">
@ -154,7 +165,7 @@ If you are using REST framework as an full-time employee, consider recommending
<span class="price">{{ rates.personal1 }}</span>
<span class="period">/month{% if vat %} +VAT{% endif %}</span>
</div>
<div class="plan-name">Freelancer</div>
<div class="plan-name">Individual</div>
<div class="specs freelancer">
<div class="spec">
Support ongoing development
@ -306,7 +317,7 @@ Our professional and premium plans also include **priority support**. At any tim
*Billing is monthly and you can cancel at any time.*
Once you've signed up I'll contact you via email and arrange your ad placements on the site.
Once you've signed up, we will contact you via email and arrange your ad placements on the site.
For further enquires please contact <a href=mailto:funding@django-rest-framework.org>funding@django-rest-framework.org</a>.
@ -314,14 +325,7 @@ For further enquires please contact <a href=mailto:funding@django-rest-framework
## Accountability
In order to ensure that I can be fully focused on trying to secure a sustainable
& well-funded open source business I will be leaving my current role at [DabApps](http://www.dabapps.com)
at the end of May 2016.
I have formed a UK limited company, [Encode](http://www.encode.io), which will
act as the business entity behind REST framework. I will be issuing monthly reports
from Encode on progress both towards the [Mozilla grant](mozilla-grant.md), and for development time
funded via the REST framework paid plans.
In an effort to keep the project as transparent as possible, we are releasing [monthly progress reports](http://www.encode.io/reports/february-2017) and regularly include financial reports and cost breakdowns.
<!-- Begin MailChimp Signup Form -->
<link href="//cdn-images.mailchimp.com/embedcode/classic-10_7.css" rel="stylesheet" type="text/css">

View File

@ -38,6 +38,32 @@ You can determine your currently installed version using `pip freeze`:
---
## 3.6.x series
### 3.6.2
**Date**: [10th March 2017][3.6.2-milestone]
* Support for Safari & IE in API docs. ([#4959][gh4959], [#4961][gh4961])
* Add missing `mark_safe` in API docs template tags. ([#4952][gh4952], [#4953][gh4953])
* Add missing glyicon fonts. ([#4950][gh4950], [#4951][gh4951])
* Fix One-to-one fields in API docs. ([#4955][gh4955], [#4956][gh4956])
* Test clean ups. ([#4949][gh4949])
### 3.6.1
**Date**: [9th March 2017][3.6.1-milestone]
* Ensure `markdown` dependancy is optional. ([#4947][gh4947])
### 3.6.0
**Date**: [9th March 2017][3.6.0-milestone]
See the [release announcement][3.6-release].
---
## 3.5.x series
### 3.5.4
@ -625,6 +651,7 @@ For older release notes, [please see the version 2.x documentation][old-release-
[ticket-582]: https://github.com/tomchristie/django-rest-framework/issues/582
[rfc-6266]: http://tools.ietf.org/html/rfc6266#section-4.3
[old-release-notes]: https://github.com/tomchristie/django-rest-framework/blob/version-2.4.x/docs/topics/release-notes.md
[3.6-release]: 3.6-announcement.md
[3.0.1-milestone]: https://github.com/tomchristie/django-rest-framework/issues?q=milestone%3A%223.0.1+Release%22
[3.0.2-milestone]: https://github.com/tomchristie/django-rest-framework/issues?q=milestone%3A%223.0.2+Release%22
@ -658,6 +685,9 @@ For older release notes, [please see the version 2.x documentation][old-release-
[3.5.2-milestone]: https://github.com/tomchristie/django-rest-framework/issues?q=milestone%3A%223.5.2+Release%22
[3.5.3-milestone]: https://github.com/tomchristie/django-rest-framework/issues?q=milestone%3A%223.5.3+Release%22
[3.5.4-milestone]: https://github.com/tomchristie/django-rest-framework/issues?q=milestone%3A%223.5.4+Release%22
[3.6.0-milestone]: https://github.com/tomchristie/django-rest-framework/issues?q=milestone%3A%223.6.0+Release%22
[3.6.1-milestone]: https://github.com/tomchristie/django-rest-framework/issues?q=milestone%3A%223.6.1+Release%22
[3.6.2-milestone]: https://github.com/tomchristie/django-rest-framework/issues?q=milestone%3A%223.6.2+Release%22
<!-- 3.0.1 -->
[gh2013]: https://github.com/tomchristie/django-rest-framework/issues/2013
@ -1254,3 +1284,17 @@ For older release notes, [please see the version 2.x documentation][old-release-
[gh4634]: https://github.com/tomchristie/django-rest-framework/issues/4634
[gh4669]: https://github.com/tomchristie/django-rest-framework/issues/4669
[gh4712]: https://github.com/tomchristie/django-rest-framework/issues/4712
<!-- 3.6.1 -->
[gh4947]: https://github.com/tomchristie/django-rest-framework/issues/4947
<!-- 3.6.2 -->
[gh4959]: https://github.com/tomchristie/django-rest-framework/issues/4959
[gh4961]: https://github.com/tomchristie/django-rest-framework/issues/4961
[gh4952]: https://github.com/tomchristie/django-rest-framework/issues/4952
[gh4953]: https://github.com/tomchristie/django-rest-framework/issues/4953
[gh4950]: https://github.com/tomchristie/django-rest-framework/issues/4950
[gh4951]: https://github.com/tomchristie/django-rest-framework/issues/4951
[gh4955]: https://github.com/tomchristie/django-rest-framework/issues/4955
[gh4956]: https://github.com/tomchristie/django-rest-framework/issues/4956
[gh4949]: https://github.com/tomchristie/django-rest-framework/issues/4949

View File

@ -8,7 +8,7 @@ ______ _____ _____ _____ __
"""
__title__ = 'Django REST framework'
__version__ = '3.6.1'
__version__ = '3.6.2'
__author__ = 'Tom Christie'
__license__ = 'BSD 2-Clause'
__copyright__ = 'Copyright 2011-2017 Tom Christie'

View File

@ -819,7 +819,7 @@ class DocumentationRenderer(BaseRenderer):
class SchemaJSRenderer(BaseRenderer):
media_type = 'script/javascript'
media_type = 'application/javascript'
format = 'javascript'
charset = 'utf-8'
template = 'rest_framework/schema.js'

View File

@ -999,13 +999,15 @@ class ModelSerializer(Serializer):
fields[field_name] = declared_fields[field_name]
continue
extra_field_kwargs = extra_kwargs.get(field_name, {})
source = extra_field_kwargs.get('source') or field_name
# Determine the serializer field class and keyword arguments.
field_class, field_kwargs = self.build_field(
field_name, info, model, depth
source, info, model, depth
)
# Include any kwargs defined in `Meta.extra_kwargs`
extra_field_kwargs = extra_kwargs.get(field_name, {})
field_kwargs = self.include_extra_kwargs(
field_kwargs, extra_field_kwargs
)

View File

@ -150,7 +150,7 @@
</div>
<div class="response-info">
<pre class="prettyprint"><span class="meta nocode"><b>HTTP {{ response.status_code }} {{ response.status_text }}</b>{% autoescape off %}{% for key, val in response_headers.items %}
<pre class="prettyprint"><span class="meta nocode"><b>HTTP {{ response.status_code }} {{ response.status_text }}</b>{% autoescape off %}{% for key, val in response_headers|items %}
<b>{{ key }}:</b> <span class="lit">{{ val|break_long_headers|urlize_quoted_links }}</span>{% endfor %}
</span>{{ content|urlize_quoted_links }}</pre>{% endautoescape %}

View File

@ -14,17 +14,17 @@
</div>
</div>
{% for section_key, section in document.data.items %}
{% for section_key, section in document.data|items %}
{% if section_key %}
<h2 id="{{ section_key }}" class="coredocs-section-title">{{ section_key }} <a href="#{{ section_key }}"><i class="fa fa-link" aria-hidden="true"></i>
</a></h2>
{% endif %}
{% for link_key, link in section.links.items %}
{% for link_key, link in section.links|items %}
{% include "rest_framework/docs/link.html" %}
{% endfor %}
{% endfor %}
{% for link_key, link in document.links.items %}
{% for link_key, link in document.links|items %}
{% include "rest_framework/docs/link.html" %}
{% endfor %}

View File

@ -1,5 +1,6 @@
{% load rest_framework %}
{% load staticfiles %}
<pre class="highlight javascript hide" data-language="javascript"><code>{% code html %}<!-- Load the JavaScript client library -->
<script src="{% static 'rest_framework/js/coreapi-0.0.20.js' %}"></script>
<script src="{% static 'rest_framework/js/coreapi-0.1.0.js' %}"></script>
<script src="{% url 'api-docs:schema-js' %}"></script>{% endcode %}</code></pre>

View File

@ -1,15 +1,16 @@
{% load rest_framework %}
<div class="sidebar">
<h3 class="brand"><a href="#">{{ document.title }}</a></h3>
<i class="fa fa-bars fa-2x toggle-btn" data-toggle="collapse" data-target="#menu-content"></i>
<div class="menu-list">
<ul id="menu-content" class="menu-content collapse out">
{% for section_key, section in document.data.items %}
{% for section_key, section in document.data|items %}
<li data-toggle="collapse" data-target="#{{ section_key }}-dropdown" class="collapsed">
<a><i class="fa fa-dot-circle-o fa-lg"></i> {% if section_key %}{{ section_key }}{% else %}API Endpoints{% endif %} <span class="arrow"></span></a>
</li>
<ul class="sub-menu {% if section_key %}collapse{% endif %}" id="{{ section_key }}-dropdown">
{% for link_key, link in section.links.items %}
{% for link_key, link in section.links|items %}
<li><a href="#{{ section_key }}-{{ link_key }}">{{ link.title|default:link_key }}</a></li>
{% endfor %}
</ul>

View File

@ -9,14 +9,14 @@
<div class="col-sm-10">
{% if style.inline %}
{% for key, text in field.choices.items %}
{% for key, text in field.choices|items %}
<label class="checkbox-inline">
<input type="checkbox" name="{{ field.name }}" value="{{ key }}" {% if key|as_string in field.value|as_list_of_strings %}checked{% endif %}>
{{ text }}
</label>
{% endfor %}
{% else %}
{% for key, text in field.choices.items %}
{% for key, text in field.choices|items %}
<div class="checkbox">
<label>
<input type="checkbox" name="{{ field.name }}" value="{{ key }}" {% if key|as_string in field.value|as_list_of_strings %}checked{% endif %}>

View File

@ -19,7 +19,7 @@
</label>
{% endif %}
{% for key, text in field.choices.items %}
{% for key, text in field.choices|items %}
<label class="radio-inline">
<input type="radio" name="{{ field.name }}" value="{{ key }}" {% if key|as_string == field.value|as_string %}checked{% endif %} />
{{ text }}
@ -34,7 +34,7 @@
</label>
</div>
{% endif %}
{% for key, text in field.choices.items %}
{% for key, text in field.choices|items %}
<div class="radio">
<label>
<input type="radio" name="{{ field.name }}" value="{{ key }}" {% if key|as_string == field.value|as_string %}checked{% endif %} />

View File

@ -5,7 +5,7 @@
<label class="sr-only">{{ field.label }}</label>
{% endif %}
{% for key, text in field.choices.items %}
{% for key, text in field.choices|items %}
<div class="checkbox">
<label>
<input type="checkbox" name="{{ field.name }}" value="{{ key }}" {% if key|as_string in field.value|as_list_of_strings %}checked{% endif %}>

View File

@ -18,7 +18,7 @@
</div>
{% endif %}
{% for key, text in field.choices.items %}
{% for key, text in field.choices|items %}
<div class="radio">
<label>
<input type="radio" name="{{ field.name }}" value="{{ key }}" {% if key|as_string == field.value|as_string %}checked{% endif %}>

View File

@ -7,7 +7,7 @@
{% if style.inline %}
<div>
{% for key, text in field.choices.items %}
{% for key, text in field.choices|items %}
<label class="checkbox-inline">
<input type="checkbox" name="{{ field.name }}" value="{{ key }}" {% if key|as_string in field.value|as_list_of_strings %}checked{% endif %}>
{{ text }}
@ -15,7 +15,7 @@
{% endfor %}
</div>
{% else %}
{% for key, text in field.choices.items %}
{% for key, text in field.choices|items %}
<div class="checkbox">
<label>
<input type="checkbox" name="{{ field.name }}" value="{{ key }}" {% if key|as_string in field.value|as_list_of_strings %}checked{% endif %}>

View File

@ -18,7 +18,7 @@
</label>
{% endif %}
{% for key, text in field.choices.items %}
{% for key, text in field.choices|items %}
<label class="radio-inline">
<input type="radio" name="{{ field.name }}" value="{{ key }}" {% if key|as_string == field.value|as_string %}checked{% endif %}>
{{ text }}
@ -35,7 +35,7 @@
</div>
{% endif %}
{% for key, text in field.choices.items %}
{% for key, text in field.choices|items %}
<div class="radio">
<label>
<input type="radio" name="{{ field.name }}" value="{{ key }}" {% if key|as_string == field.value|as_string %}checked{% endif %}>

View File

@ -79,6 +79,9 @@ class ViewSetMixin(object):
handler = getattr(self, action)
setattr(self, method, handler)
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
# And continue as usual
return self.dispatch(request, *args, **kwargs)

View File

@ -101,6 +101,15 @@ class TestRootView(TestCase):
assert response.status_code == status.HTTP_200_OK
assert response.data == self.data
def test_head_root_view(self):
"""
HEAD requests to ListCreateAPIView should return 200.
"""
request = factory.head('/')
with self.assertNumQueries(1):
response = self.view(request).render()
assert response.status_code == status.HTTP_200_OK
def test_post_root_view(self):
"""
POST requests to ListCreateAPIView should create a new object.

View File

@ -24,6 +24,15 @@ class InitializeViewSetsTestCase(TestCase):
assert response.status_code == status.HTTP_200_OK
assert response.data == {'ACTION': 'LIST'}
def testhead_request_against_viewset(self):
request = factory.head('/', '', content_type='application/json')
my_view = BasicViewSet.as_view(actions={
'get': 'list',
})
response = my_view(request)
assert response.status_code == status.HTTP_200_OK
def test_initialize_view_set_with_empty_actions(self):
try:
BasicViewSet.as_view()