mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-08-06 21:40:13 +03:00
Merge f4245040be
into 932d04a4be
This commit is contained in:
commit
57daca419f
|
@ -1,126 +1,179 @@
|
||||||
# Quickstart
|
# Quickstart
|
||||||
|
|
||||||
We're going to create a simple API to allow admin users to view and edit the users and groups in the system.
|
We're going to create a simple API to allow admin users to view and edit the
|
||||||
|
users and groups in the system.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
* [Python][python]
|
||||||
|
* [pip][pip] - a tool for installing Python packages
|
||||||
|
* [virtualenv][virtualenv] - a tool to create isolated Python environments
|
||||||
|
|
||||||
## Project setup
|
## Project setup
|
||||||
|
|
||||||
Create a new Django project named `tutorial`, then start a new app called `quickstart`.
|
### Create a new Django project named `tutorial`, then start a new app called `quickstart`.
|
||||||
|
|
||||||
# Create the project directory
|
Create the project directory
|
||||||
mkdir tutorial
|
|
||||||
cd tutorial
|
|
||||||
|
|
||||||
# Create a virtualenv to isolate our package dependencies locally
|
```text
|
||||||
virtualenv env
|
mkdir tutorial
|
||||||
source env/bin/activate # On Windows use `env\Scripts\activate`
|
cd tutorial
|
||||||
|
```
|
||||||
|
|
||||||
# Install Django and Django REST framework into the virtualenv
|
Create a virtualenv to isolate our package dependencies locally
|
||||||
pip install django
|
|
||||||
pip install djangorestframework
|
|
||||||
|
|
||||||
# Set up a new project with a single application
|
```text
|
||||||
django-admin.py startproject tutorial . # Note the trailing '.' character
|
virtualenv env
|
||||||
cd tutorial
|
source env/bin/activate # On Linux or OS X
|
||||||
django-admin.py startapp quickstart
|
source env\Scripts\activate # On Windows
|
||||||
cd ..
|
```
|
||||||
|
|
||||||
|
Install Django and Django REST framework into the virtualenv
|
||||||
|
|
||||||
|
```text
|
||||||
|
pip install django
|
||||||
|
pip install djangorestframework
|
||||||
|
```
|
||||||
|
|
||||||
|
Set up a new project with a single application
|
||||||
|
|
||||||
|
```text
|
||||||
|
django-admin.py startproject tutorial . # Note the trailing '.' character
|
||||||
|
|
||||||
|
cd tutorial
|
||||||
|
django-admin.py startapp quickstart
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
```
|
||||||
|
|
||||||
|
### Database
|
||||||
|
|
||||||
Now sync your database for the first time:
|
Now sync your database for the first time:
|
||||||
|
|
||||||
python manage.py migrate
|
```text
|
||||||
|
python manage.py migrate
|
||||||
|
```
|
||||||
|
|
||||||
We'll also create an initial user named `admin` with a password of `password123`. We'll authenticate as that user later in our example.
|
We'll also create an initial user named `admin` with a password of
|
||||||
|
`password123`. We'll authenticate as that user later in our example.
|
||||||
|
|
||||||
python manage.py createsuperuser
|
```text
|
||||||
|
python manage.py createsuperuser
|
||||||
|
```
|
||||||
|
|
||||||
Once you've set up a database and initial user created and ready to go, open up the app's directory and we'll get coding...
|
Once you've set up a database and initial user created and ready to go, open up
|
||||||
|
the app's directory and we'll get coding...
|
||||||
|
|
||||||
## Serializers
|
## Serializers
|
||||||
|
|
||||||
First up we're going to define some serializers. Let's create a new module named `tutorial/quickstart/serializers.py` that we'll use for our data representations.
|
First up we're going to define some serializers. Let's create a new module named
|
||||||
|
`tutorial/quickstart/serializers.py` that we'll use for our data
|
||||||
|
representations.
|
||||||
|
|
||||||
from django.contrib.auth.models import User, Group
|
```python
|
||||||
from rest_framework import serializers
|
from django.contrib.auth.models import User, Group
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
|
||||||
class UserSerializer(serializers.HyperlinkedModelSerializer):
|
class UserSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
fields = ('url', 'username', 'email', 'groups')
|
fields = ('url', 'username', 'email', 'groups')
|
||||||
|
|
||||||
|
|
||||||
class GroupSerializer(serializers.HyperlinkedModelSerializer):
|
class GroupSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Group
|
model = Group
|
||||||
fields = ('url', 'name')
|
fields = ('url', 'name')
|
||||||
|
```
|
||||||
|
|
||||||
Notice that we're using hyperlinked relations in this case, with `HyperlinkedModelSerializer`. You can also use primary key and various other relationships, but hyperlinking is good RESTful design.
|
Notice that we're using hyperlinked relations in this case, with
|
||||||
|
`HyperlinkedModelSerializer`. You can also use primary key and various other
|
||||||
|
relationships, but hyperlinking is good RESTful design.
|
||||||
|
|
||||||
## Views
|
## Views
|
||||||
|
|
||||||
Right, we'd better write some views then. Open `tutorial/quickstart/views.py` and get typing.
|
Right, we'd better write some views then. Open `tutorial/quickstart/views.py`
|
||||||
|
and get typing.
|
||||||
|
|
||||||
from django.contrib.auth.models import User, Group
|
```python
|
||||||
from rest_framework import viewsets
|
from django.contrib.auth.models import User, Group
|
||||||
from tutorial.quickstart.serializers import UserSerializer, GroupSerializer
|
from rest_framework import viewsets
|
||||||
|
from tutorial.quickstart.serializers import UserSerializer, GroupSerializer
|
||||||
|
|
||||||
|
|
||||||
class UserViewSet(viewsets.ModelViewSet):
|
class UserViewSet(viewsets.ModelViewSet):
|
||||||
"""
|
"""
|
||||||
API endpoint that allows users to be viewed or edited.
|
API endpoint that allows users to be viewed or edited.
|
||||||
"""
|
"""
|
||||||
queryset = User.objects.all().order_by('-date_joined')
|
queryset = User.objects.all().order_by('-date_joined')
|
||||||
serializer_class = UserSerializer
|
serializer_class = UserSerializer
|
||||||
|
|
||||||
|
|
||||||
class GroupViewSet(viewsets.ModelViewSet):
|
class GroupViewSet(viewsets.ModelViewSet):
|
||||||
"""
|
"""
|
||||||
API endpoint that allows groups to be viewed or edited.
|
API endpoint that allows groups to be viewed or edited.
|
||||||
"""
|
"""
|
||||||
queryset = Group.objects.all()
|
queryset = Group.objects.all()
|
||||||
serializer_class = GroupSerializer
|
serializer_class = GroupSerializer
|
||||||
|
```
|
||||||
|
|
||||||
Rather than write multiple views we're grouping together all the common behavior into classes called `ViewSets`.
|
Rather than write multiple views we're grouping together all the common behavior
|
||||||
|
into classes called `ViewSets`.
|
||||||
|
|
||||||
We can easily break these down into individual views if we need to, but using viewsets keeps the view logic nicely organized as well as being very concise.
|
We can easily break these down into individual views if we need to, but using
|
||||||
|
viewsets keeps the view logic nicely organized as well as being very concise.
|
||||||
|
|
||||||
## URLs
|
## URLs
|
||||||
|
|
||||||
Okay, now let's wire up the API URLs. On to `tutorial/urls.py`...
|
Okay, now let's wire up the API URLs. On to `tutorial/urls.py`...
|
||||||
|
|
||||||
from django.conf.urls import url, include
|
```python
|
||||||
from rest_framework import routers
|
from django.conf.urls import url, include
|
||||||
from tutorial.quickstart import views
|
from rest_framework import routers
|
||||||
|
from tutorial.quickstart import views
|
||||||
|
|
||||||
router = routers.DefaultRouter()
|
router = routers.DefaultRouter()
|
||||||
router.register(r'users', views.UserViewSet)
|
router.register(r'users', views.UserViewSet)
|
||||||
router.register(r'groups', views.GroupViewSet)
|
router.register(r'groups', views.GroupViewSet)
|
||||||
|
|
||||||
# Wire up our API using automatic URL routing.
|
# Wire up our API using automatic URL routing.
|
||||||
# Additionally, we include login URLs for the browsable API.
|
# Additionally, we include login URLs for the browsable API.
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^', include(router.urls)),
|
url(r'^', include(router.urls)),
|
||||||
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
|
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
|
||||||
]
|
]
|
||||||
|
```
|
||||||
|
|
||||||
Because we're using viewsets instead of views, we can automatically generate the URL conf for our API, by simply registering the viewsets with a router class.
|
Because we're using viewsets instead of views, we can automatically generate the
|
||||||
|
URL conf for our API, by simply registering the viewsets with a router class.
|
||||||
|
|
||||||
Again, if we need more control over the API URLs we can simply drop down to using regular class-based views, and writing the URL conf explicitly.
|
Again, if we need more control over the API URLs we can simply drop down to
|
||||||
|
using regular class-based views, and writing the URL conf explicitly.
|
||||||
|
|
||||||
Finally, we're including default login and logout views for use with the browsable API. That's optional, but useful if your API requires authentication and you want to use the browsable API.
|
Finally, we're including default login and logout views for use with the
|
||||||
|
browsable API. That's optional, but useful if your API requires authentication
|
||||||
|
and you want to use the browsable API.
|
||||||
|
|
||||||
## Settings
|
## Settings
|
||||||
|
|
||||||
We'd also like to set a few global settings. We'd like to turn on pagination, and we want our API to only be accessible to admin users. The settings module will be in `tutorial/settings.py`
|
We'd also like to set a few global settings. We'd like to turn on pagination,
|
||||||
|
and we want our API to only be accessible to admin users. The settings module
|
||||||
|
will be in `tutorial/settings.py`
|
||||||
|
|
||||||
INSTALLED_APPS = (
|
```python
|
||||||
...
|
INSTALLED_APPS = (
|
||||||
'rest_framework',
|
...
|
||||||
)
|
'rest_framework',
|
||||||
|
)
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAdminUser',),
|
'DEFAULT_PERMISSION_CLASSES': (
|
||||||
'PAGE_SIZE': 10
|
'rest_framework.permissions.IsAdminUser', # Note the trailing ',' character, this needs to be a tuple
|
||||||
}
|
),
|
||||||
|
'PAGE_SIZE': 10
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
Okay, we're done.
|
Okay, we're done.
|
||||||
|
|
||||||
|
@ -128,72 +181,92 @@ Okay, we're done.
|
||||||
|
|
||||||
## Testing our API
|
## Testing our API
|
||||||
|
|
||||||
We're now ready to test the API we've built. Let's fire up the server from the command line.
|
We're now ready to test the API we've built. Let's fire up the server from the
|
||||||
|
command line.
|
||||||
|
|
||||||
python manage.py runserver
|
python manage.py runserver
|
||||||
|
|
||||||
We can now access our API, both from the command-line, using tools like `curl`...
|
We can now access our API, both from the command-line, using tools like
|
||||||
|
`curl`...
|
||||||
|
|
||||||
bash: curl -H 'Accept: application/json; indent=4' -u admin:password123 http://127.0.0.1:8000/users/
|
```bash
|
||||||
{
|
curl -H 'Accept: application/json; indent=4' -u admin:password123 http://127.0.0.1:8000/users/
|
||||||
"count": 2,
|
```
|
||||||
"next": null,
|
|
||||||
"previous": null,
|
```json
|
||||||
"results": [
|
{
|
||||||
{
|
"count": 2,
|
||||||
"email": "admin@example.com",
|
"next": null,
|
||||||
"groups": [],
|
"previous": null,
|
||||||
"url": "http://127.0.0.1:8000/users/1/",
|
"results": [
|
||||||
"username": "admin"
|
{
|
||||||
},
|
"email": "admin@example.com",
|
||||||
{
|
"groups": [],
|
||||||
"email": "tom@example.com",
|
"url": "http://127.0.0.1:8000/users/1/",
|
||||||
"groups": [ ],
|
"username": "admin"
|
||||||
"url": "http://127.0.0.1:8000/users/2/",
|
},
|
||||||
"username": "tom"
|
{
|
||||||
}
|
"email": "tom@example.com",
|
||||||
]
|
"groups": [ ],
|
||||||
}
|
"url": "http://127.0.0.1:8000/users/2/",
|
||||||
|
"username": "tom"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
Or using the [httpie][httpie], command line tool...
|
Or using the [httpie][httpie], command line tool...
|
||||||
|
|
||||||
bash: http -a admin:password123 http://127.0.0.1:8000/users/
|
```bash
|
||||||
|
http -a admin:password123 http://127.0.0.1:8000/users/
|
||||||
|
```
|
||||||
|
|
||||||
HTTP/1.1 200 OK
|
```text
|
||||||
...
|
HTTP/1.1 200 OK
|
||||||
{
|
...
|
||||||
"count": 2,
|
```
|
||||||
"next": null,
|
|
||||||
"previous": null,
|
|
||||||
"results": [
|
|
||||||
{
|
|
||||||
"email": "admin@example.com",
|
|
||||||
"groups": [],
|
|
||||||
"url": "http://localhost:8000/users/1/",
|
|
||||||
"username": "paul"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"email": "tom@example.com",
|
|
||||||
"groups": [ ],
|
|
||||||
"url": "http://127.0.0.1:8000/users/2/",
|
|
||||||
"username": "tom"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"count": 2,
|
||||||
|
"next": null,
|
||||||
|
"previous": null,
|
||||||
|
"results": [
|
||||||
|
{
|
||||||
|
"email": "admin@example.com",
|
||||||
|
"groups": [],
|
||||||
|
"url": "http://localhost:8000/users/1/",
|
||||||
|
"username": "paul"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"email": "tom@example.com",
|
||||||
|
"groups": [ ],
|
||||||
|
"url": "http://127.0.0.1:8000/users/2/",
|
||||||
|
"username": "tom"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
Or directly through the browser, by going to the URL `http://127.0.0.1:8000/users/`...
|
Or directly through the browser, by going to the URL
|
||||||
|
`http://127.0.0.1:8000/users/`...
|
||||||
|
|
||||||
![Quick start image][image]
|
![Quick start image][image]
|
||||||
|
|
||||||
If you're working through the browser, make sure to login using the control in the top right corner.
|
If you're working through the browser, make sure to login using the control in
|
||||||
|
the top right corner.
|
||||||
|
|
||||||
Great, that was easy!
|
Great, that was easy!
|
||||||
|
|
||||||
If you want to get a more in depth understanding of how REST framework fits together head on over to [the tutorial][tutorial], or start browsing the [API guide][guide].
|
If you want to get a more in depth understanding of how REST framework fits
|
||||||
|
together head on over to [the tutorial][tutorial], or start browsing the [API
|
||||||
|
guide][guide].
|
||||||
|
|
||||||
[readme-example-api]: ../#example
|
[readme-example-api]: ../#example
|
||||||
[image]: ../img/quickstart.png
|
[image]: ../img/quickstart.png
|
||||||
[tutorial]: 1-serialization.md
|
[tutorial]: 1-serialization.md
|
||||||
[guide]: ../#api-guide
|
[guide]: ../#api-guide
|
||||||
[httpie]: https://github.com/jakubroztocil/httpie#installation
|
[httpie]: https://github.com/jakubroztocil/httpie#installation
|
||||||
|
[python]: https://www.python.org/downloads/
|
||||||
|
[pip]: https://pip.pypa.io/en/stable/
|
||||||
|
[virtualenv]: https://virtualenv.pypa.io/en/stable/
|
||||||
|
|
Loading…
Reference in New Issue
Block a user