Giter Site home page Giter Site logo

django-rest-framework's Introduction

build-status-image coverage-status-image pypi-version

Awesome web-browsable Web APIs.

Full documentation for the project is available at https://www.django-rest-framework.org/.


Funding

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.

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.

Many thanks to all our wonderful sponsors, and in particular to our premium backers, Sentry, Stream, Spacinov, Retool, bit.io, PostHog, CryptAPI, FEZTO, and Svix.


Overview

Django REST framework is a powerful and flexible toolkit for building Web APIs.

Some reasons you might want to use REST framework:

Below: Screenshot from the browsable API

Screenshot


Requirements

  • Python 3.6+
  • Django 5.0, 4.2, 4.1, 4.0, 3.2, 3.1, 3.0

We highly recommend and only officially support the latest patch release of each Python and Django series.

Installation

Install using pip...

pip install djangorestframework

Add 'rest_framework' to your INSTALLED_APPS setting.

INSTALLED_APPS = [
    ...
    'rest_framework',
]

Example

Let's take a look at a quick example of using REST framework to build a simple model-backed API for accessing users and groups.

Startup up a new project like so...

pip install django
pip install djangorestframework
django-admin startproject example .
./manage.py migrate
./manage.py createsuperuser

Now edit the example/urls.py module in your project:

from django.contrib.auth.models import User
from django.urls import include, path
from rest_framework import routers, serializers, viewsets


# Serializers define the API representation.
class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = User
        fields = ['url', 'username', 'email', 'is_staff']


# ViewSets define the view behavior.
class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer


# Routers provide a way of automatically determining the URL conf.
router = routers.DefaultRouter()
router.register(r'users', UserViewSet)

# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
    path('', include(router.urls)),
    path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
]

We'd also like to configure a couple of settings for our API.

Add the following to your settings.py module:

INSTALLED_APPS = [
    ...  # Make sure to include the default installed apps here.
    'rest_framework',
]

REST_FRAMEWORK = {
    # Use Django's standard `django.contrib.auth` permissions,
    # or allow read-only access for unauthenticated users.
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly',
    ]
}

That's it, we're done!

./manage.py runserver

You can now open the API in your browser at http://127.0.0.1:8000/, and view your new 'users' API. If you use the Login control in the top right corner you'll also be able to add, create and delete users from the system.

You can also interact with the API using command line tools such as curl. For example, to list the users endpoint:

$ curl -H 'Accept: application/json; indent=4' -u admin:password http://127.0.0.1:8000/users/
[
    {
        "url": "http://127.0.0.1:8000/users/1/",
        "username": "admin",
        "email": "[email protected]",
        "is_staff": true,
    }
]

Or to create a new user:

$ curl -X POST -d username=new -d [email protected] -d is_staff=false -H 'Accept: application/json; indent=4' -u admin:password http://127.0.0.1:8000/users/
{
    "url": "http://127.0.0.1:8000/users/2/",
    "username": "new",
    "email": "[email protected]",
    "is_staff": false,
}

Documentation & Support

Full documentation for the project is available at https://www.django-rest-framework.org/.

For questions and support, use the REST framework discussion group, or #restframework on libera.chat IRC.

You may also want to follow the author on Twitter.

Security

Please see the security policy.

django-rest-framework's People

Contributors

adamchainz avatar arthur-github-user avatar auvipy avatar blueyed avatar carltongibson avatar craigds avatar d0ugal avatar dulacp avatar felixxm avatar flashingpumpkin avatar grimborg avatar ins1ne avatar j4mie avatar jakul avatar jdufresne avatar jpadilla avatar kevin-brown avatar lsanpablo avatar markotibold avatar maryokhin avatar maspwr avatar minddust avatar mjumbewu avatar rpkilby avatar sebpiq avatar thedrow avatar tomchristie avatar wronglink avatar xordoquy avatar yprez avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-rest-framework's Issues

Problem with "id" attribute in PUT

My standard views won't accept the "id" attribute when PUTing to them, I always get the {"field-errors": {"id": ["This field does not exist."]}} response

Bare except clauses in renderers.py hide real errors

renderers.py makes extensive use of bare except statements to try various ways of getting a form before falling back to alternatives.

This makes it almost impossible to be debug actual errors with the form rendering process since the errors are silently discarded and there's no way to bypass the bare except statements.

It would be preferable if these clauses instead used "except Exception:" to catch all typical errors, while still allowing SystemExit, KeyboardInterrupt, GeneratorExit and BaseException itself to escape.

Then a well-placed "raise BaseException('info')" could be used to help work out what is going wrong with the rendering process.

PaginatorMixin

I added a PaginatorMixin (now with added testy goodness) and was wondering if you would want this in core? I think it would be pretty useful having it built in as it's something I reckon would be used a lot.

As an aside, I think I messed up my original pull request

Throttle classes need refactoring, better .throttle attribute

I think it's refactor nicely to:

BaseThrottle(BasePermission):
get_cache_key(self) # Not Implemented
check_throttle(self, cache_key)
throttle_success(self, cache_key)
throttle_failure(self, cache_key)

PerUserThrottle(BaseThrottle):
get_cache_key(self)

PerResourceThrottle(BaseThrottle):
get_cache_key(self)

Also thinking about it I think it'd be nice if the .throttle attribute was string like '10/sec', '45/min', '100/hour', '100/day', '10/s' '45/m' etc... instead of being a 2-tuple

So something like:

num, period = getattr(self.view, 'throttle', '0/sec').partition('/')
num = int(num)
period = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}[period[0]]

Make ListModelMixin more CBV like (add get_queryset method)

what about this ?

class ListModelMixin(object):
    """
    Behavior to list a set of `model` instances on GET requests
    """

    # NB. Not obvious to me if it would be better to set this on the resource?
    #
    # Presumably it's more useful to have on the view, because that way you can
    # have multiple views across different querysets mapping to the same resource.
    #
    # Perhaps it ought to be:
    #
    #1) View.queryset
    #2) if None fall back to Resource.queryset
    #3) if None fall back to Resource.model.objects.all()
    #
    # Any feedback welcomed.
    queryset = None

    def get_queryset(self):
        if self.queryset is None:
            self.queryset = self.resource.model.objects.all()
        return self.queryset

    def get(self, request, *args, **kwargs):
        model = self.resource.model

        queryset = self.get_queryset()

        if hasattr(self, 'resource'):
            ordering = getattr(self.resource, 'ordering', None)
        else:
            ordering = None

        if ordering:
            args = as_tuple(ordering)
            queryset = queryset.order_by(*args)
        return queryset.filter(**kwargs)

this would enable for example, integration with django-filter (overwrite get_queryset instead of whole get()).

X-Throttled: Expires in x sec

This is an idea Tom came up with some time ago which I remembered just now.

Add an X-Throttled field to to the response of a throttled request.

This can be implemented with less then 3 lines of code I think, because the ErrorResponse class takes header fields as kwargs.

ListModelMixin.get() doesn't allow empty querysets

mixins.py

class ListModelMixin(object):
    [...]
    def get(self, request, *args, **kwargs):
        [...]
        queryset = self.queryset if self.queryset else model.objects.all()
        [...]

If self.queryset is set, but empty (= []), the statement evaluates to False and overwrites queryset with all objects.

Easily add/validate etags.

Django has an awesome etag/condition/last_modified decorator. It doesn't work with the d-r-f class-based views, as you cannot decorate 'get' with them. Because get returns an object that is not an http response, there is no way to add the etag header to the response.

I would like to see a way to do this from within d-r-f. I'm thinking something along the lines of an overridable method on a resource, or a view (or a mixin) that can be used to generate the etag.

The other way of doing it in django is to use the middleware, but it cannot shortcut running the body of the view altogether like the decorator can.

Readonly ModelResource fields

Perhaps there is a way to do this that I'm not a aware of, but is there a way to mark a field on a ModelResource as read-only on the resource level. I can make the model field non-editable, but that would go for all resources based on the model then.

Document Linked FKs better.

Needs to:

  1. Allow user to specify Resource and use that Resource's .url()
  2. Fall back to using the model's default resource .url()

UserLoggedInAuthentication is deleting request.POST

Using UserLoggedInAuthentication causes all the POST data to be removed from any POST request because of this line b508ca3#L0R92

class TestView(View):
    authentication = (UserLoggedInAuthentication,)

    def post(self, request):
        return request.POST # Returns <QueryDict: {}> no matter what post data was sent

Allow .json .html .xml style urls

  1. Tests
  2. Add 'format' attribute to Renderers.
  3. Modify can_handle_request so that if self.view.kwargs.get('format', None) == self.format, then True
  4. Ensure that format in kwargs wont screw anything else up
  5. Support these styles by default in the html renderer, in preference to the &accept= style.
  6. &format= style should also be supported. Ensure format in params wont screw anything else up (see accept, csrfmiddlewaretoken, etc... in resource.py) ie accessing self.PARAMS should ignore format.
  7. Added points (yes please) - ensure the html renderer can be super clever and coerce urls it finds into format appended urls if it is itself a format appended url. EG. If a given url has both an HTML browseable api, and a standard HTML rendering, then we can use something like '.api' for the browseable api urls, and '.html' for the standard urls.

HTTP PATCH

Recently I came over this cool new feature of the HTTP Protocol. It's a bit more sophisticated then the PUT method. You can actually partially modify a resource with it.

Check it out here:

http://tools.ietf.org/html/rfc5789

Document Nested FKs better.

Needs to

  1. Allow user to specify Resource and use that Resource's for serialization.
  2. Fall back to using the model's default resource for serialization.

Call POST internally

Hi. This is less of a bug than a support request.

I have created a REST interface using the Django authenticator that I need to use both internally (non-AJAX) and with JavaScript (AJAX). The JavaScript part works great, but now I need to "create" a POST request internally so that I don't have to create redundant code.

The "internal" view currently looks like this:

@render_to('monitoring_added.html')
def add_monitoring(request, entity_id):
    request.META['REQUEST_METHOD'] = 'POST'
    request.META['HTTP_ACCEPT'] = 'application/json'
    user_id = ... # Get user_id here
    request.POST = QueryDict('entity_id=%s&User=%s' % (entity_id, user_id))
    response = MonitoringApi.as_view()(request)
    return {'content': response.content}

The request gets passed on correctly, but django-rest-framework does not accept the POST data. It always returns an error message saying that entity_id and User are required fields.

Is my approach completely wrong? Ir have I just overlooked some issue with the request or my code? Should I create a new HttpRequest instead?

Test the throttling class.

I've still not got around to actually testing that code etc. Be great to actually give it a bit of a once-over. If it's not obvious, or it's not working and not clear why, then what point do things get to? Get it working, with decent docstrings, and check the auto doc is sufficient for users to get started with it.

shortcuts.autodiscover()

There's very little reason left why you shouldn't be able to auto-generate an API for all the installed models in an application, with a one-liner autodiscover. Ideally, if there's a resource defined for a model it ought to use that resource for the model (note that there's currently a commented out _RegisterModelResource in resources.py that can do the registration.)

Ideally this requires #13.

Ensure documentation for library reference is complete.

Make sure all the modules in the top level 'django-rest-framework' are in the 'library reference', and they're all auto-documenting from the source properly.

Make sure the auto-documenting stuff in there is doing stuff correctly, eg like linking to classes, attributes etc. Ensuring that only public methods are being documented.

Key name collision and serialitation error

If the returned object contains some key that collides with a dictionary operation name, the serialitation crashes.

Examples:

def get(self, request):
return {"keys": ["hello", "goodbye"]}

or

def get(self, request):
return {"items": ["hello", "goodbye"]}

Error message in serializer.py/serialize_model, line 248: unhashable type: 'dict'.

UserLoggedInAuthentication: Show Error Message on failed CSRF validation

I almost removed django-rest-framework from my project due to problems with the UserLoggedInAuthentication when using Ajax-Requests. But then I decided to debug the Code and realized that it wasn't a problem with my code architecture, it was simply a failed CSRF validation.

authentication.py:

94             if request.method.upper() == 'POST':
95                 # Temporarily replace request.POST with .DATA,
96                 # so that we use our more generic request parsing
97                 request._post = self.view.DATA
98                 resp = CsrfViewMiddleware().process_view(request, None, (), {})
99                 del(request._post)
100                 if resp is not None:  # csrf failed
101                     return None

Please provide a correct error message in the return data, instead of returning None, which results in a "you are not logged in" error.

Also, it would be good to reference this section of the Django docs from your documentation.

serializations for geodjango geometry

I am trying to use django-rest-framework for a geographic data API in a geodjango project.

In geodjango, a geometry is an instance of GEOSGeometry which can be serialized with differents properties such as GEOSGeometry.json or GEOSGeometry.wkt (seems to be the default behavior).

With django-rest-framework, a call to the api with "_accept=application/json" always returns a WKT string (the default) instead of a json string.

PUT should not do partial updates

Strictly speaking, a PUT should not do partial updates of a resource.

For instance, if you only PUT some fields, this implies that all other fields are null (or perhaps the db default, but I would say null).

The current behaviour of the UpdateModelMixin is to update whatever fields are passed in on the model, and leave everything else as-is.

This is more appropriate for a POST onto the resource.

Add OAuth authentication/permissions.

The plan would be to use David Larlet's OAuth plus, and keep it as an external dependency for anyone requiring OAuth support.

See: https://bitbucket.org/david/django-oauth-plus/overview

At least as a first pass this oughta be pretty easy - most of the OAuth stuff is just down to oauth-plus to deal with and you only need to tie in the very last leg.

You'll want to start off looking at examples/provider in oauth-plus. You'll see the 'outh_providers.urls' views listed in there. Those don't need to tie in at all to begin with. They'll just need to be unprotected un-api'ed views that just work exactly as they do already.
(At some point it'd be really great to tie them in with the auto-documenting API - that'd really really improve the ease of use I think.)

So the part you do need to tie in is CheckOAuth. With oauth-plus you'd normally apply that check to a view as a simple decorator, and it'd ensure that:

  1. The request is signed with a valid OAuth token
  2. The OAuth tokens 'name' matches the view name (I think that'd right.)

We'll prob want pretty much the same thing eg.

  1. A .scope attribute gets put on any Resource you want to protect with OAuth.
  2. The OAuthAuthenticator gets added to the Resource's authenticators.
  3. The OAuthAuthenticator.authenticate(request) method uses CheckOAuth (or some equivalent) to ensure the token is valid and the token's name matches the Resource's 'scope', or raises an HttpException (PERMISSION DENIED).

I think it's that simple. (?)

Example demonstrating throttling functionality

It'd be nice to have an example that demonstrates throttling behavior.

In this case we'd probably use the per-user throttlle.

We could start off with a 1/sec throttle.

Later on we could expand the example with a form where a user can set the rate him self or so...

Global per-resource throttling

It would be nice to be able to throttle requests to a resource, not only per user. Only question is: should we store the throttle in the cache based on the url of the resource or based on the View's class....

Finalize decoupling of Mixin classes

All the 4 base Mixin class ought to be usable independently. The acid test is that they should all be able to be added to the django tutorial step 4, independently, and still do something useful.

cannot import name LimitBytes

cannot import name LimitBytes

When using djangorestframework.mixins.ResponseMixin

from django.http.multipartparser import LimitBytes doesn't exist in django trunk nor does it look like LimitBytes is being used in mixins.py

docs - Getting Started - Model Views

url(r'^([0-9]+)/$', InstanceModelView.as_view(resource=MyModelResource)),

should be

url(r'^(?P[0-9]+)/$', InstanceModelView.as_view(resource=MyModelResource)),

to avoid 'NoReverseMatch' Error

Cheers

p.s. Not sure why but the issue edit box seems to not display (?P[0-9]+) correctly, there should be "less than id greater than" between the 'P' and '['. However if I go to 'update issue' it is still there, some meta/escape code weirdness shrug

Add API token authentication.

At the moment Basic authentication only support username/password.

It'd be great if it could also be used with token objects, stored in the database, where each token has a key, a secret, and is tied to a user.

The right way to do this would be to write a standard django auth backend that validates (username, password) arguments against an APIToken table rather than the standard backend which validates it against the User table.

After that I'd modify the BasicAuthentication class, adding a 'backend' attribute, which would be unset by default. If the attribute is not set then the class would simply call 'authenticate(username, password)', otherwise it would call backend.authenticate(username, password).

TokenBasicAuthentication would then simply extend BasicAuthentication, setting 'backend=APITokenBackend'.

It would be nice if the token table didn't get installed by default on syncdb unless it's actually being used.

Get 100% test coverage.

Up to ~70% at the moment.
Ought to remove compat from the coverage tests since it's environment dependent.

Documentation

Right now the main things that could be improved:

  • A proper walkthrough of how to use the framework.
  • A breakdown of the Mixin classes - RequestMixin, ResponseMixin, AuthMixin, ResourceMixin, examples how they can be used separately etc...
  • A section on how to contribute to the project.

Should Resource subclass docstrings overwrite view docstrings?

Since a Resource can be used in multiple views, it seems to me it would be better to use the Resource's docstring as a fallback rather than a replacement for the view's docstring.

From utils.description.get_description

# If this view has a resource that's been overridden, then use the resource's doctring
if getattr(view, 'resource', None) not in (None, Resource, FormResource, ModelResource):
    doc = view.resource.__doc__

# Otherwise use the view doctring
elif getattr(view, '__doc__', None):
    doc = view.__doc__

# I ain't got nuthin fo' ya
else:
    return ''

Clean up util imports

Everything that's in utils at the moment really ought to be private.
I'd also like to make sure that any imports from utils only require statements like:

from djangorestframework.utils import xxx

Rather than

from djangorestframework.utils.xxx import yyy

All the util imports should be regular functions - no importing classes anywhere from utils.
Finally the xml stuff ought to be split out into a separate file.

Creating objects with m2m relations fails

I have a sub-class of auth.User, which I have exposed an API for.

When I attempt to POST valid data to the ListOrCreateModelView, it fails when attempting to add groups, which are an m2m relation.

I'm looking into a patch where I do the m2m stuff after creating the instance, but it will almost certainly need testing against other stuff: this is my first foray into django-rest-framework.

serialize_model method in serializer.py may cause wrong value

following source code :

        if hasattr(self, fname):
            # check for a method 'fname' on self first
            meth = getattr(self, fname)
            if inspect.ismethod(meth) and len(inspect.getargspec(meth)[0]) == 2:
                obj = meth(instance)

may not give a value to 'obj' variable, so the 'obj' may contain the old value, then
val = self.serialize_val(fname, obj)
now this field 'fname' has the wrong value

forgive my pool English

Add ability for tests to use mock models.

At the moment none of the tests are able to create some mock Models and test stuff against them, because the tests don't have a models.py. It be good if we could just do something like add 'models.py' into the tests directory, and add 'djangorestframework.tests' as an INSTALLED_APP in the runtests.py script, or something like that. But needs someone to find out if that'd actually work, how to add them in the runtests.py script, and make sure they're not installed if you just do a regular syncdb on djangorestframework.
For example, would be nice to see some tests to check serializing of nested models, but we wouldn't want those models to actually be installed in djangorestframework by default.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.