Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: markotibold/rest-framework-tutorial
base: ad85bf5957
...
head fork: markotibold/rest-framework-tutorial
compare: c5b52eacf0
Checking mergeability… Don't worry, you can still create the pull request.
  • 15 commits
  • 9 files changed
  • 0 commit comments
  • 3 contributors
Commits on Jan 11, 2013
@tomchristie tomchristie Update import to match tutorial docs 6df2d07
Commits on Jan 15, 2013
@tomchristie tomchristie Fix for pygments 1.6rc. 87cf4c5
Commits on Jan 16, 2013
Richard Wackerbarth Correct comment to reflect actual functionality 0b9607a
Richard Wackerbarth Class name from docs/tutorial
This class name is more consistent with Django
conventions
b1dbb34
Richard Wackerbarth Additional Comments 18c7cb1
Richard Wackerbarth Conforming Line Breaks e933d8a
Richard Wackerbarth For Conformity with new Repository d47b7a2
Richard Wackerbarth Reordering to match new Repository b9144a2
Richard Wackerbarth Suppress trailing whitespace f20e225
Richard Wackerbarth Artifacts from startproject eaed235
Richard Wackerbarth Comments retained in new Repository
However, I notice that all of the comments are
suppressed in the tutorial docs. I will move them
to the "Additional Comments" commit at the end of
the new repository.
81e29bf
@tomchristie tomchristie Merge pull request #5 from Wackerbarth/Transition
Transition
1e27e65
Commits on Feb 23, 2013
@tomchristie tomchristie Add missing `blank=True`. b6fb1b3
Commits on Feb 26, 2013
@tomchristie tomchristie UserInstance -> UserDetail a2447ee
Commits on Mar 02, 2013
@markotibold Upgrade to Django 1.5 and latest REST Framework c5b52ea
View
6 .gitignore
@@ -1,7 +1,11 @@
-*.pyc
+# Database content will be handled by fixtures
*.db
+
+# These are normally defined globally
+*.pyc
*~
.*
+# Accept these files in the repository
!.gitignore
!.travis.yml
View
4 requirements.txt
@@ -1,5 +1,5 @@
-git+git://github.com/tomchristie/django-rest-framework/@restframework2#egg=rest_framework
-django==1.4.2
+git+git://github.com/tomchristie/django-rest-framework/@master#egg=rest_framework==2.2.1
+django==1.5
Pygments==1.5
Markdown==2.2.0
View
110 snippets/fixtures/initial_data.json
@@ -1,73 +1,73 @@
[
{
- "pk": 2,
- "model": "auth.user",
+ "pk": 2,
+ "model": "auth.user",
"fields": {
- "username": "aziz",
- "first_name": "",
- "last_name": "",
- "is_active": true,
- "is_superuser": false,
- "is_staff": false,
- "last_login": "2012-10-28T21:36:57.799Z",
- "groups": [],
- "user_permissions": [],
- "password": "pbkdf2_sha256$10000$2x3LOiFCb9sq$3jiN4zgb3wYHQ9fpn/elUrcn1S1Bq/q0djZFBjb8Y2w=",
- "email": "",
+ "username": "aziz",
+ "first_name": "",
+ "last_name": "",
+ "is_active": true,
+ "is_superuser": false,
+ "is_staff": false,
+ "last_login": "2012-10-28T21:36:57.799Z",
+ "groups": [],
+ "user_permissions": [],
+ "password": "pbkdf2_sha256$10000$2x3LOiFCb9sq$3jiN4zgb3wYHQ9fpn/elUrcn1S1Bq/q0djZFBjb8Y2w=",
+ "email": "",
"date_joined": "2012-10-28T21:36:57.799Z"
}
- },
+ },
{
- "pk": 3,
- "model": "auth.user",
+ "pk": 3,
+ "model": "auth.user",
"fields": {
- "username": "amy",
- "first_name": "",
- "last_name": "",
- "is_active": true,
- "is_superuser": false,
- "is_staff": false,
- "last_login": "2012-10-28T21:42:34.081Z",
- "groups": [],
- "user_permissions": [],
- "password": "pbkdf2_sha256$10000$wjy2WvTgw1Ro$oR8pVFHIBqZUmD9XEHdRl5m4TxWOF+qnvZn/q+npTlc=",
- "email": "",
+ "username": "amy",
+ "first_name": "",
+ "last_name": "",
+ "is_active": true,
+ "is_superuser": false,
+ "is_staff": false,
+ "last_login": "2012-10-28T21:42:34.081Z",
+ "groups": [],
+ "user_permissions": [],
+ "password": "pbkdf2_sha256$10000$wjy2WvTgw1Ro$oR8pVFHIBqZUmD9XEHdRl5m4TxWOF+qnvZn/q+npTlc=",
+ "email": "",
"date_joined": "2012-10-28T21:42:34.081Z"
}
- },
+ },
{
- "pk": 4,
- "model": "auth.user",
+ "pk": 4,
+ "model": "auth.user",
"fields": {
- "username": "max",
- "first_name": "",
- "last_name": "",
- "is_active": true,
- "is_superuser": false,
- "is_staff": false,
- "last_login": "2012-10-28T21:42:45.711Z",
- "groups": [],
- "user_permissions": [],
- "password": "pbkdf2_sha256$10000$NhDNt8GNYfjC$0FlcsJxt8Sac0dvGv+xcaUVSUfh1UYZfWEq3C1WoHjc=",
- "email": "",
+ "username": "max",
+ "first_name": "",
+ "last_name": "",
+ "is_active": true,
+ "is_superuser": false,
+ "is_staff": false,
+ "last_login": "2012-10-28T21:42:45.711Z",
+ "groups": [],
+ "user_permissions": [],
+ "password": "pbkdf2_sha256$10000$NhDNt8GNYfjC$0FlcsJxt8Sac0dvGv+xcaUVSUfh1UYZfWEq3C1WoHjc=",
+ "email": "",
"date_joined": "2012-10-28T21:42:45.711Z"
}
- },
+ },
{
- "pk": 5,
- "model": "auth.user",
+ "pk": 5,
+ "model": "auth.user",
"fields": {
- "username": "jose",
- "first_name": "",
- "last_name": "",
- "is_active": true,
- "is_superuser": false,
- "is_staff": false,
- "last_login": "2012-10-28T21:43:03.591Z",
- "groups": [],
- "user_permissions": [],
- "password": "pbkdf2_sha256$10000$ibnHXtPQKwBN$Kab9tTROT6bpxnAI1imgb0kdlAmBuAQ5Z0fAzHbkL68=",
- "email": "",
+ "username": "jose",
+ "first_name": "",
+ "last_name": "",
+ "is_active": true,
+ "is_superuser": false,
+ "is_staff": false,
+ "last_login": "2012-10-28T21:43:03.591Z",
+ "groups": [],
+ "user_permissions": [],
+ "password": "pbkdf2_sha256$10000$ibnHXtPQKwBN$Kab9tTROT6bpxnAI1imgb0kdlAmBuAQ5Z0fAzHbkL68=",
+ "email": "",
"date_joined": "2012-10-28T21:43:03.591Z"
}
}
View
17 snippets/models.py
@@ -1,16 +1,17 @@
from django.db import models
-from pygments.lexers import get_all_lexers, get_lexer_by_name
+from pygments.lexers import get_all_lexers
from pygments.styles import get_all_styles
+from pygments.lexers import get_lexer_by_name
from pygments.formatters import HtmlFormatter
from pygments import highlight
-LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in get_all_lexers()])
-STYLE_CHOICES = sorted((item, item) for item in list(get_all_styles()))
-
+LEXERS = [item for item in get_all_lexers() if item[1]]
+LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS])
+STYLE_CHOICES = sorted((item, item) for item in get_all_styles())
class Snippet(models.Model):
created = models.DateTimeField(auto_now_add=True)
- title = models.CharField(max_length=100, default='')
+ title = models.CharField(max_length=100, blank=True, default='')
code = models.TextField()
linenos = models.BooleanField(default=False)
language = models.CharField(choices=LANGUAGE_CHOICES,
@@ -26,6 +27,10 @@ class Meta:
ordering = ('created',)
def save(self, *args, **kwargs):
+ """
+ Use the `pygments` library to create a highlighted HTML
+ representation of the code snippet.
+ """
lexer = get_lexer_by_name(self.language)
linenos = self.linenos and 'table' or False
options = self.title and {'title': self.title} or {}
@@ -34,7 +39,7 @@ def save(self, *args, **kwargs):
self.highlighted = highlight(self.code, lexer, formatter)
super(Snippet, self).save(*args, **kwargs)
- # maximize the amount of instances to be created
+ # limit the number of instances retained
snippets = Snippet.objects.all()
if len(snippets) > 100:
snippets[0].delete()
View
8 snippets/permissions.py
@@ -1,12 +1,18 @@
from rest_framework import permissions
-
class IsOwnerOrReadOnly(permissions.BasePermission):
+ """
+ Custom permission to only allow owners of an object to edit it.
+ """
+
def has_permission(self, request, view, obj=None):
+ # Skip the check unless this is an object-level test
if obj is None:
return True
+ # Read permissions are allowed to any request
if request.method in permissions.SAFE_METHODS:
return True
+ # Write permissions are only allowed to the owner of the snippet
return obj.owner == request.user
View
7 snippets/serializers.py
@@ -1,14 +1,13 @@
-from snippets import models
-from django.contrib.auth.models import User
from rest_framework import serializers
-
+from snippets.models import Snippet
+from django.contrib.auth.models import User
class SnippetSerializer(serializers.HyperlinkedModelSerializer):
owner = serializers.Field(source='owner.username')
highlight = serializers.HyperlinkedIdentityField(view_name='snippet-highlight', format='html')
class Meta:
- model = models.Snippet
+ model = Snippet
fields = ('url', 'highlight', 'owner',
'title', 'code', 'linenos', 'language', 'style')
View
14 snippets/views.py
@@ -1,13 +1,14 @@
-from rest_framework import generics, permissions, renderers
+from django.contrib.auth.models import User
+from rest_framework import generics
+from rest_framework import permissions
+from rest_framework import renderers
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.reverse import reverse
-from django.contrib.auth.models import User
from snippets.models import Snippet
from snippets.permissions import IsOwnerOrReadOnly
from snippets.serializers import SnippetSerializer, UserSerializer
-
@api_view(('GET',))
def api_root(request, format=None):
"""
@@ -48,7 +49,7 @@ def pre_save(self, obj):
obj.owner = self.request.user
-class SnippetInstance(generics.RetrieveUpdateDestroyAPIView):
+class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
"""
This view presents an instance of a code snippet.
@@ -62,7 +63,8 @@ class SnippetInstance(generics.RetrieveUpdateDestroyAPIView):
"""
model = Snippet
serializer_class = SnippetSerializer
- permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly,)
+ permission_classes = (permissions.IsAuthenticatedOrReadOnly,
+ IsOwnerOrReadOnly,)
def pre_save(self, obj):
obj.owner = self.request.user
@@ -88,7 +90,7 @@ class UserList(generics.ListAPIView):
serializer_class = UserSerializer
-class UserInstance(generics.RetrieveAPIView):
+class UserDetail(generics.RetrieveAPIView):
"""
This view presents a instance of one of the users in the system.
"""
View
10 tutorial/settings.py
@@ -11,8 +11,8 @@
DATABASES = {
'default': {
- 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
- 'NAME': 'tmp.db', # Or path to database file if using sqlite3.
+ 'ENGINE': 'django.db.backends.sqlite3', # Or use an alternate database backend.
+ 'NAME': 'tmp.db', # Path to sqlite3 database file.
'USER': '', # Not used with sqlite3.
'PASSWORD': '', # Not used with sqlite3.
'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
@@ -115,8 +115,12 @@
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
- 'snippets',
+ # Uncomment the next line to enable the admin:
+ # 'django.contrib.admin',
+ # Uncomment the next line to enable admin documentation:
+ # 'django.contrib.admindocs',
'rest_framework',
+ 'snippets',
)
# A sample logging configuration. The only tangible logging
View
4 tutorial/urls.py
@@ -5,10 +5,10 @@
urlpatterns = format_suffix_patterns(patterns('snippets.views',
url(r'^$', 'api_root'),
url(r'^snippets/$', views.SnippetList.as_view(), name='snippet-list'),
- url(r'^snippets/(?P<pk>[0-9]+)/$', views.SnippetInstance.as_view(), name='snippet-detail'),
+ url(r'^snippets/(?P<pk>[0-9]+)/$', views.SnippetDetail.as_view(), name='snippet-detail'),
url(r'^snippets/(?P<pk>[0-9]+)/highlight/$', views.SnippetHighlight.as_view(), name='snippet-highlight'),
url(r'^users/$', views.UserList.as_view(), name='user-list'),
- url(r'^users/(?P<pk>[0-9]+)/$', views.UserInstance.as_view(), name='user-detail')
+ url(r'^users/(?P<pk>[0-9]+)/$', views.UserDetail.as_view(), name='user-detail')
))
urlpatterns += patterns('',

No commit comments for this range

Something went wrong with that request. Please try again.