Skip to content

Commit fac8322

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

7 files changed

+926
-731
lines changed

docs/tutorial/1-serialization.md

Lines changed: 258 additions & 201 deletions
Large diffs are not rendered by default.

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

Lines changed: 127 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,18 @@ Let's introduce a couple of essential building blocks.
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.
99

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.
10+
```python
11+
request.POST # Only handles form data. Only works for 'POST' method.
12+
request.data # Handles arbitrary data. Works for 'POST', 'PUT' and 'PATCH' methods.
13+
```
1214

1315
## Response objects
1416

1517
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.
1618

17-
return Response(data) # Renders to content type as requested by the client.
19+
```python
20+
return Response(data) # Renders to content type as requested by the client.
21+
```
1822

1923
## Status codes
2024

@@ -35,87 +39,90 @@ The wrappers also provide behavior such as returning `405 Method Not Allowed` re
3539

3640
Okay, let's go ahead and start using these new components to refactor our views slightly.
3741

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)
42+
```python
43+
from rest_framework import status
44+
from rest_framework.decorators import api_view
45+
from rest_framework.response import Response
46+
from snippets.models import Snippet
47+
from snippets.serializers import SnippetSerializer
48+
49+
50+
@api_view(["GET", "POST"])
51+
def snippet_list(request):
52+
"""
53+
List all code snippets, or create a new snippet.
54+
"""
55+
if request.method == "GET":
56+
snippets = Snippet.objects.all()
57+
serializer = SnippetSerializer(snippets, many=True)
58+
return Response(serializer.data)
59+
60+
elif request.method == "POST":
61+
serializer = SnippetSerializer(data=request.data)
62+
if serializer.is_valid():
63+
serializer.save()
64+
return Response(serializer.data, status=status.HTTP_201_CREATED)
65+
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
66+
```
6167

6268
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.
6369

6470
Here is the view for an individual snippet, in the `views.py` module.
6571

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)
72+
```python
73+
@api_view(["GET", "PUT", "DELETE"])
74+
def snippet_detail(request, pk):
75+
"""
76+
Retrieve, update or delete a code snippet.
77+
"""
78+
try:
79+
snippet = Snippet.objects.get(pk=pk)
80+
except Snippet.DoesNotExist:
81+
return Response(status=status.HTTP_404_NOT_FOUND)
82+
83+
if request.method == "GET":
84+
serializer = SnippetSerializer(snippet)
85+
return Response(serializer.data)
86+
87+
elif request.method == "PUT":
88+
serializer = SnippetSerializer(snippet, data=request.data)
89+
if serializer.is_valid():
90+
serializer.save()
7891
return Response(serializer.data)
92+
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
7993

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)
94+
elif request.method == "DELETE":
95+
snippet.delete()
96+
return Response(status=status.HTTP_204_NO_CONTENT)
97+
```
9098

9199
This should all feel very familiar - it is not a lot different from working with regular Django views.
92100

93101
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.
94102

95103
## Adding optional format suffixes to our URLs
96104

97-
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].
105+
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].
98106

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

107112
Now update the `snippets/urls.py` file slightly, to append a set of `format_suffix_patterns` in addition to the existing URLs.
108113

109-
from django.urls import path
110-
from rest_framework.urlpatterns import format_suffix_patterns
111-
from snippets import views
114+
```python
115+
from django.urls import path
116+
from rest_framework.urlpatterns import format_suffix_patterns
117+
from snippets import views
112118

113-
urlpatterns = [
114-
path('snippets/', views.snippet_list),
115-
path('snippets/<int:pk>/', views.snippet_detail),
116-
]
119+
urlpatterns = [
120+
path("snippets/", views.snippet_list),
121+
path("snippets/<int:pk>/", views.snippet_detail),
122+
]
117123

118-
urlpatterns = format_suffix_patterns(urlpatterns)
124+
urlpatterns = format_suffix_patterns(urlpatterns)
125+
```
119126

120127
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.
121128

@@ -125,68 +132,76 @@ Go ahead and test the API from the command line, as we did in [tutorial part 1][
125132

126133
We can get a list of all of the snippets, as before.
127134

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-
]
135+
```bash
136+
http http://127.0.0.1:8000/snippets/
137+
138+
HTTP/1.1 200 OK
139+
...
140+
[
141+
{
142+
"id": 1,
143+
"title": "",
144+
"code": "foo = \"bar\"\n",
145+
"linenos": false,
146+
"language": "python",
147+
"style": "friendly"
148+
},
149+
{
150+
"id": 2,
151+
"title": "",
152+
"code": "print(\"hello, world\")\n",
153+
"linenos": false,
154+
"language": "python",
155+
"style": "friendly"
156+
}
157+
]
158+
```
150159

151160
We can control the format of the response that we get back, either by using the `Accept` header:
152161

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
162+
```bash
163+
http http://127.0.0.1:8000/snippets/ Accept:application/json # Request JSON
164+
http http://127.0.0.1:8000/snippets/ Accept:text/html # Request HTML
165+
```
155166

156167
Or by appending a format suffix:
157168

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
169+
```bash
170+
http http://127.0.0.1:8000/snippets.json # JSON suffix
171+
http http://127.0.0.1:8000/snippets.api # Browsable API suffix
172+
```
160173

161174
Similarly, we can control the format of the request that we send, using the `Content-Type` header.
162175

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-
}
176+
```bash
177+
# POST using form data
178+
http --form POST http://127.0.0.1:8000/snippets/ code="print(123)"
179+
180+
{
181+
"id": 3,
182+
"title": "",
183+
"code": "print(123)",
184+
"linenos": false,
185+
"language": "python",
186+
"style": "friendly"
187+
}
188+
189+
# POST using JSON
190+
http --json POST http://127.0.0.1:8000/snippets/ code="print(456)"
191+
192+
{
193+
"id": 4,
194+
"title": "",
195+
"code": "print(456)",
196+
"linenos": false,
197+
"language": "python",
198+
"style": "friendly"
199+
}
200+
```
186201

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

189-
Now go and open the API in a web browser, by visiting [http://127.0.0.1:8000/snippets/][devserver].
204+
Now go and open the API in a web browser, by visiting [<http://127.0.0.1:8000/snippets/>][devserver].
190205

191206
### Browsability
192207

0 commit comments

Comments
 (0)