Skip to content

Commit c7a786e

Browse files
committed
docs: Add syntax highlighting to code examples
1 parent f0ba887 commit c7a786e

7 files changed

+932
-909
lines changed

docs/tutorial/1-serialization.md

Lines changed: 261 additions & 257 deletions
Large diffs are not rendered by default.

docs/tutorial/2-requests-and-responses.md

Lines changed: 124 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@ Let's introduce a couple of essential building blocks.
66
## Request objects
77

88
REST framework introduces a `Request` object that extends the regular `HttpRequest`, and provides more flexible request parsing. The core functionality of the `Request` object is the `request.data` attribute, which is similar to `request.POST`, but more useful for working with Web APIs.
9-
10-
request.POST # Only handles form data. Only works for 'POST' method.
11-
request.data # Handles arbitrary data. Works for 'POST', 'PUT' and 'PATCH' methods.
12-
9+
```python
10+
request.POST # Only handles form data. Only works for 'POST' method.
11+
request.data # Handles arbitrary data. Works for 'POST', 'PUT' and 'PATCH' methods.
12+
```
1313
## Response objects
1414

1515
REST framework also introduces a `Response` object, which is a type of `TemplateResponse` that takes unrendered content and uses content negotiation to determine the correct content type to return to the client.
16-
17-
return Response(data) # Renders to content type as requested by the client.
18-
16+
```python
17+
return Response(data) # Renders to content type as requested by the client.
18+
```
1919
## Status codes
2020

2121
Using numeric HTTP status codes in your views doesn't always make for obvious reading, and it's easy to not notice if you get an error code wrong. REST framework provides more explicit identifiers for each status code, such as `HTTP_400_BAD_REQUEST` in the `status` module. It's a good idea to use these throughout rather than using numeric identifiers.
@@ -34,60 +34,60 @@ The wrappers also provide behavior such as returning `405 Method Not Allowed` re
3434
## Pulling it all together
3535

3636
Okay, let's go ahead and start using these new components to refactor our views slightly.
37-
38-
from rest_framework import status
39-
from rest_framework.decorators import api_view
40-
from rest_framework.response import Response
41-
from snippets.models import Snippet
42-
from snippets.serializers import SnippetSerializer
43-
44-
45-
@api_view(['GET', 'POST'])
46-
def snippet_list(request):
47-
"""
48-
List all code snippets, or create a new snippet.
49-
"""
50-
if request.method == 'GET':
51-
snippets = Snippet.objects.all()
52-
serializer = SnippetSerializer(snippets, many=True)
53-
return Response(serializer.data)
54-
55-
elif request.method == 'POST':
56-
serializer = SnippetSerializer(data=request.data)
57-
if serializer.is_valid():
58-
serializer.save()
59-
return Response(serializer.data, status=status.HTTP_201_CREATED)
60-
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
61-
37+
```python
38+
from rest_framework import status
39+
from rest_framework.decorators import api_view
40+
from rest_framework.response import Response
41+
from snippets.models import Snippet
42+
from snippets.serializers import SnippetSerializer
43+
44+
45+
@api_view(["GET", "POST"])
46+
def snippet_list(request):
47+
"""
48+
List all code snippets, or create a new snippet.
49+
"""
50+
if request.method == "GET":
51+
snippets = Snippet.objects.all()
52+
serializer = SnippetSerializer(snippets, many=True)
53+
return Response(serializer.data)
54+
55+
elif request.method == "POST":
56+
serializer = SnippetSerializer(data=request.data)
57+
if serializer.is_valid():
58+
serializer.save()
59+
return Response(serializer.data, status=status.HTTP_201_CREATED)
60+
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
61+
```
6262
Our instance view is an improvement over the previous example. It's a little more concise, and the code now feels very similar to if we were working with the Forms API. We're also using named status codes, which makes the response meanings more obvious.
6363

6464
Here is the view for an individual snippet, in the `views.py` module.
65-
66-
@api_view(['GET', 'PUT', 'DELETE'])
67-
def snippet_detail(request, pk):
68-
"""
69-
Retrieve, update or delete a code snippet.
70-
"""
71-
try:
72-
snippet = Snippet.objects.get(pk=pk)
73-
except Snippet.DoesNotExist:
74-
return Response(status=status.HTTP_404_NOT_FOUND)
75-
76-
if request.method == 'GET':
77-
serializer = SnippetSerializer(snippet)
65+
```python
66+
@api_view(["GET", "PUT", "DELETE"])
67+
def snippet_detail(request, pk):
68+
"""
69+
Retrieve, update or delete a code snippet.
70+
"""
71+
try:
72+
snippet = Snippet.objects.get(pk=pk)
73+
except Snippet.DoesNotExist:
74+
return Response(status=status.HTTP_404_NOT_FOUND)
75+
76+
if request.method == "GET":
77+
serializer = SnippetSerializer(snippet)
78+
return Response(serializer.data)
79+
80+
elif request.method == "PUT":
81+
serializer = SnippetSerializer(snippet, data=request.data)
82+
if serializer.is_valid():
83+
serializer.save()
7884
return Response(serializer.data)
85+
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
7986

80-
elif request.method == 'PUT':
81-
serializer = SnippetSerializer(snippet, data=request.data)
82-
if serializer.is_valid():
83-
serializer.save()
84-
return Response(serializer.data)
85-
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
86-
87-
elif request.method == 'DELETE':
88-
snippet.delete()
89-
return Response(status=status.HTTP_204_NO_CONTENT)
90-
87+
elif request.method == "DELETE":
88+
snippet.delete()
89+
return Response(status=status.HTTP_204_NO_CONTENT)
90+
```
9191
This should all feel very familiar - it is not a lot different from working with regular Django views.
9292

9393
Notice that we're no longer explicitly tying our requests or responses to a given content type. `request.data` can handle incoming `json` requests, but it can also handle other formats. Similarly we're returning response objects with data, but allowing REST framework to render the response into the correct content type for us.
@@ -97,25 +97,23 @@ Notice that we're no longer explicitly tying our requests or responses to a give
9797
To take advantage of the fact that our responses are no longer hardwired to a single content type let's add support for format suffixes to our API endpoints. Using format suffixes gives us URLs that explicitly refer to a given format, and means our API will be able to handle URLs such as [http://example.com/api/items/4.json][json-url].
9898

9999
Start by adding a `format` keyword argument to both of the views, like so.
100-
101-
def snippet_list(request, format=None):
102-
100+
`def snippet_list(request, format=None):`
103101
and
104-
105-
def snippet_detail(request, pk, format=None):
102+
`def snippet_detail(request, pk, format=None):`
106103

107104
Now update the `snippets/urls.py` file slightly, to append a set of `format_suffix_patterns` in addition to the existing URLs.
105+
```python
106+
from django.urls import path
107+
from rest_framework.urlpatterns import format_suffix_patterns
108+
from snippets import views
108109

109-
from django.urls import path
110-
from rest_framework.urlpatterns import format_suffix_patterns
111-
from snippets import views
112-
113-
urlpatterns = [
114-
path('snippets/', views.snippet_list),
115-
path('snippets/<int:pk>/', views.snippet_detail),
116-
]
110+
urlpatterns = [
111+
path("snippets/", views.snippet_list),
112+
path("snippets/<int:pk>/", views.snippet_detail),
113+
]
117114

118-
urlpatterns = format_suffix_patterns(urlpatterns)
115+
urlpatterns = format_suffix_patterns(urlpatterns)
116+
```
119117

120118
We don't necessarily need to add these extra url patterns in, but it gives us a simple, clean way of referring to a specific format.
121119

@@ -124,65 +122,67 @@ We don't necessarily need to add these extra url patterns in, but it gives us a
124122
Go ahead and test the API from the command line, as we did in [tutorial part 1][tut-1]. Everything is working pretty similarly, although we've got some nicer error handling if we send invalid requests.
125123

126124
We can get a list of all of the snippets, as before.
125+
```bash
126+
http http://127.0.0.1:8000/snippets/
127127

128-
http http://127.0.0.1:8000/snippets/
129-
130-
HTTP/1.1 200 OK
131-
...
132-
[
133-
{
134-
"id": 1,
135-
"title": "",
136-
"code": "foo = \"bar\"\n",
137-
"linenos": false,
138-
"language": "python",
139-
"style": "friendly"
140-
},
141-
{
142-
"id": 2,
143-
"title": "",
144-
"code": "print(\"hello, world\")\n",
145-
"linenos": false,
146-
"language": "python",
147-
"style": "friendly"
148-
}
149-
]
128+
HTTP/1.1 200 OK
129+
...
130+
[
131+
{
132+
"id": 1,
133+
"title": "",
134+
"code": "foo = \"bar\"\n",
135+
"linenos": false,
136+
"language": "python",
137+
"style": "friendly"
138+
},
139+
{
140+
"id": 2,
141+
"title": "",
142+
"code": "print(\"hello, world\")\n",
143+
"linenos": false,
144+
"language": "python",
145+
"style": "friendly"
146+
}
147+
]
148+
```
150149

151150
We can control the format of the response that we get back, either by using the `Accept` header:
152-
153-
http http://127.0.0.1:8000/snippets/ Accept:application/json # Request JSON
154-
http http://127.0.0.1:8000/snippets/ Accept:text/html # Request HTML
155-
151+
```bash
152+
http http://127.0.0.1:8000/snippets/ Accept:application/json # Request JSON
153+
http http://127.0.0.1:8000/snippets/ Accept:text/html # Request HTML
154+
```
156155
Or by appending a format suffix:
157-
158-
http http://127.0.0.1:8000/snippets.json # JSON suffix
159-
http http://127.0.0.1:8000/snippets.api # Browsable API suffix
160-
156+
```bash
157+
http http://127.0.0.1:8000/snippets.json # JSON suffix
158+
http http://127.0.0.1:8000/snippets.api # Browsable API suffix
159+
```
161160
Similarly, we can control the format of the request that we send, using the `Content-Type` header.
162-
163-
# POST using form data
164-
http --form POST http://127.0.0.1:8000/snippets/ code="print(123)"
165-
166-
{
167-
"id": 3,
168-
"title": "",
169-
"code": "print(123)",
170-
"linenos": false,
171-
"language": "python",
172-
"style": "friendly"
173-
}
174-
175-
# POST using JSON
176-
http --json POST http://127.0.0.1:8000/snippets/ code="print(456)"
177-
178-
{
179-
"id": 4,
180-
"title": "",
181-
"code": "print(456)",
182-
"linenos": false,
183-
"language": "python",
184-
"style": "friendly"
185-
}
161+
```bash
162+
# POST using form data
163+
http --form POST http://127.0.0.1:8000/snippets/ code="print(123)"
164+
165+
{
166+
"id": 3,
167+
"title": "",
168+
"code": "print(123)",
169+
"linenos": false,
170+
"language": "python",
171+
"style": "friendly"
172+
}
173+
174+
# POST using JSON
175+
http --json POST http://127.0.0.1:8000/snippets/ code="print(456)"
176+
177+
{
178+
"id": 4,
179+
"title": "",
180+
"code": "print(456)",
181+
"linenos": false,
182+
"language": "python",
183+
"style": "friendly"
184+
}
185+
```
186186

187187
If you add a `--debug` switch to the `http` requests above, you will be able to see the request type in request headers.
188188

0 commit comments

Comments
 (0)