djangocon 2014 - django rest framework - so easy you can learn it in 25 minutes
TRANSCRIPT
REST
Describes an architecture
For the purpose of web apis:- stateless- support common HTTP methods- return internet media type (JSON or XML…)
What do REST endpoints look like?
/api/users/
- GET will return a collection of all users
/api/users/<id>
- GET will return a single user
Common HTTP Response Codes
200 - OK
201 - Created
401 - Not Authorized
404 - Not Found
500 - Server Error
Idempotency
Is a hard to pronounce word.
The operation will produce the same result, no matter how many times it is repeated.
PUT, DELETE - Idempotent.GET - Safe method. Produces no side effects.
A Modelclass Tweet(models.Model):
user = models.ForeignKey(User)
text = models.CharField(max_length=140)
timestamp = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-timestamp']
And a ModelSerializerclass TweetSerializer(serializers.ModelSerializer):
user = serializers.Field(source='user')
class Meta:
model = Tweet
fields = ('text', 'user', 'timestamp')
The Result [
{
"text": "Bob is the coolest name EVAR",
"user": "bob",
"timestamp": "2014-08-29T18:51:19Z"
}
]
Field Validation def validate_text(self, attrs, source):
value = attrs[source]
if len(value) < 5:
raise serializers.ValidationError(
"Text is too short!")
return attrs
Permissions
IsAuthenticated - Only allow authenticated Users
IsAdminUser - user.is_staff is True
class IsAuthorOrReadOnly(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
if request.method in permissions.SAFE_METHODS:
return True
return obj.user == request.user
ModelViewSetsclass TweetViewSet(viewsets.ModelViewSet):
queryset = Tweet.objects.all()
serializer_class = TweetSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly,
IsAuthorOrReadOnly,)
def pre_save(self, obj):
obj.user = self.request.user
Generic Views
APIView is base class. Takes care of routing.
Mixins provide common operations, and generic Views provide common combinations of mixins.
ex: ListCreateAPIView, UpdateAPIView
Requests
The DRF Request provides many methods we are used to seeing.
request.DATA is similar to request.POST
It handles data types we specified, and is available on all requests.
Responses
DRF Responses are unrendered.Return DATA, and status code.
Behind the scenes:serializer = TweetSerializer(tweets, many=True)
return Response(serializer.data)
ViewSet Routingrouter = DefaultRouter()
router.register(r'tweets', views.TweetViewSet)
router.register(r'users', views.UserViewSet)
urlpatterns = patterns('',
url(r'^api/', include(router.urls))
)
Does our validation work? def test_create_invalid_tweet(self):
self.client = APIClient()
self.client.login(username='bob', password='bob')
url = reverse('tweet-list')
data = {'text': "x" * 4}
response = self.client.post(url, data, format='json')
error_msg = response.data['text'][0]
self.assertEquals(response.status_code, 400)
self.assertEquals(error_msg, 'Text is too short!')
When to use it?
New projects.- You don’t have to code for the framework, but it’s easier to integrate.
Clean models.
When to be cautious (IMHO)
Complex models, tons of interdependent validation logic, dealing with saving non-model fields on a model
Legacy Django… It’s out there.
Next Steps
pip install djangorestframework
Also, the documentation rocks.http://www.django-rest-framework.org/