using 'pk' in fields throws KeyError

add missing imports
Browsable API seems to be working fine with FBV's (2.0.0)
removing snippets from the URI doesn't make sense
remain consistent in using SnippetDetail
This commit is contained in:
Pavel Savchenko 2012-10-31 00:37:30 +02:00
parent 166025c0fc
commit a3ace366db
5 changed files with 16 additions and 11 deletions

View File

@ -201,7 +201,7 @@ Open the file `snippets/serializers.py` again, and edit the `SnippetSerializer`
class SnippetSerializer(serializers.ModelSerializer):
class Meta:
model = Snippet
fields = ('pk', 'title', 'code', 'linenos', 'language', 'style')
fields = ('id', 'title', 'code', 'linenos', 'language', 'style')

View File

@ -130,8 +130,6 @@ Go ahead and test the API from the command line, as we did in [tutorial part 1][
Now go and open the API in a web browser, by visiting [http://127.0.0.1:8000/snippets/][devserver]."
**Note: Right now the Browseable API only works with the CBV's. Need to fix that.**
### Browsability
Because the API chooses a return format based on what the client asks for, it will, by default, return an HTML-formatted representation of the resource when that resource is requested by a browser. This allows for the API to be easily browsable and usable by humans.

View File

@ -69,8 +69,8 @@ We'll also need to refactor our URLconf slightly now we're using class based vie
from snippetpost import views
urlpatterns = patterns('',
url(r'^$', views.SnippetList.as_view()),
url(r'^(?P<pk>[0-9]+)$', views.SnippetDetail.as_view())
url(r'^snippets/$', views.SnippetList.as_view()),
url(r'^snippets/(?P<pk>[0-9]+)/$', views.SnippetDetail.as_view())
)
urlpatterns = format_suffix_patterns(urlpatterns)

View File

@ -59,7 +59,7 @@ Now that we've got some users to work with, we'd better add representations of t
class Meta:
model = User
fields = ('pk', 'username', 'snippets')
fields = ('id', 'username', 'snippets')
Because `'snippets'` is a *reverse* relationship on the User model, it will not be included by default when using the `ModelSerializer` class, so we've needed to add an explicit field for it.
@ -85,7 +85,7 @@ Right now, if we created a code snippet, there'd be no way of associating the us
The way we deal with that is by overriding a `.pre_save()` method on our snippet views, that allows us to handle any information that is implicit in the incoming request or requested URL.
On **both** the `SnippetList` and `SnippetInstance` view classes, add the following method:
On **both** the `SnippetList` and `SnippetDetail` view classes, add the following method:
def pre_save(self, obj):
obj.owner = self.request.user
@ -112,7 +112,11 @@ Now that code snippets are associated with users we want to make sure that only
REST framework includes a number of permission classes that we can use to restrict who can access a given view. In this case the one we're looking for is `IsAuthenticatedOrReadOnly`, which will ensure that authenticated requests get read-write access, and unauthenticated requests get read-only access.
Add the following property to **both** the `SnippetList` and `SnippetInstance` view classes.
First add the following import in the views module
from rest_framework import permissions
Then, add the following property to **both** the `SnippetList` and `SnippetDetail` view classes.
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
@ -169,7 +173,7 @@ In the snippets app, create a new file, `permissions.py`
# Write permissions are only allowed to the owner of the snippet
return obj.owner == request.user
Now we can add that custom permission to our snippet instance endpoint, by editing the `permission_classes` property on the `SnippetInstance` class:
Now we can add that custom permission to our snippet instance endpoint, by editing the `permission_classes` property on the `SnippetDetail` class:
permission_classes = (permissions.IsAuthenticatedOrReadOnly,
IsOwnerOrReadOnly,)

View File

@ -29,7 +29,10 @@ Unlike all our other API endpoints, we don't want to use JSON, but instead just
The other thing we need to consider when creating the code highlight view is that there's no existing concreate generic view that we can use. We're not returning an object instance, but instead a property of an object instance.
Instead of using a concrete generic view, we'll use the base class for representing instances, and create our own `.get()` method.
Instead of using a concrete generic view, we'll use the base class for representing instances, and create our own `.get()` method. In your snippets.views add:
from rest_framework import renderers
from rest_framework.response import Response
class SnippetHighlight(generics.SingleObjectAPIView):
model = Snippet
@ -111,7 +114,7 @@ After adding all those names into our URLconf, our final `'urls.py'` file should
views.SnippetList.as_view(),
name='snippet-list'),
url(r'^snippets/(?P<pk>[0-9]+)/$',
views.SnippetInstance.as_view(),
views.SnippetDetail.as_view(),
name='snippet-detail'),
url(r'^snippets/(?P<pk>[0-9]+)/highlight/$'
views.SnippetHighlight.as_view(),