Python: Iterators

If you have written some Python code and used the for loop, you have already used iterators behind the scene but you probably didn’t know about it. Iterators are objects that we can iterate over one by one.¬†They are practically everywhere in a Python codebase. Understanding the concepts of iterators and how they work can help us write better, more efficient code from time to time. In this post, we will discuss iterators and other related concepts.

How does iteration work?

Before we can dive into iterators, we first need to understand how iteration works in Python. When we do the for loop, how does Python fetch one item at a time? How does this process work?

There are two functions that come into play – iter¬†and next. The iter¬†function gets an iterator from an object. It actually calls the __iter__¬†special method on the object to get the iterator. So if an object wants to allow iteration, it has to implement the __iter__¬†method. Once it gets the iterator object, it continues to call next¬†on the iterator. The next function in turn calls the __next__¬†method on the iterator object. Let’s see a quick example:

>>> l = [1, 2, 3]

>>> i = iter(l)

>>> type(l)
<class 'list'>

>>> type(i)
<class 'list_iterator'>

>>> next(i)
1

>>> next(i)
2

>>> next(i)
3

>>> next(i)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration


>>>

Let’s see. We first create a list named l¬†with 3 elements. We then call iter()¬†on it. The type of l¬†is list¬†but look at the type of i¬†– it’s list_iterator¬†– interesting! Now we keep calling next¬†on i¬†and it keeps giving us the values we saw in the list, one by one, until there’s a StopIteration¬†exception.

Here the list is an iterable because we can get an iterator from it to iterate over the list. The list_iterator¬†object we got is an iterator, it’s an object that we can actually iterate over. When we loop over a list, this is what happens:

l = [1, 2, 3]

iterator = iter(l)

while True:
    try:
        item = next(iterator)
        print(item)
    except StopIteration:
        break

Makes sens? The for loop actually gets the iterator and keeps looping over until a StopIteration exception is encountered.

Iterator

The iterator is an object which implements __next__¬†method so we can call next¬†on it repeatedly to get the items. Let’s write an iterator that keeps us giving us the next integer, without ever stopping. Let’s name it InfiniteIterator.

class InfiniteIterator:
    def __init__(self):
        self.__int = 0

    def __next__(self):
        self.__int += 1
        return self.__int

If we keep calling next on it, we will keep getting the integers, starting from one.

>>> inf_iter = InfiniteIterator()
>>> next(inf_iter)
1
>>> next(inf_iter)
2
>>> next(inf_iter)
3
>>> next(inf_iter)
4
>>>

Iterable

What if we wanted to create an InfiniteNumbers iterable? It would be such that when we use the for loop on it, it never stops. It keeps producing the next integer in each loop. What would we do? Well, we have an InfiniteIterator. All we need is to define an __iter__ method that returns a new instance of InfiniteIterator.

class InfiniteNumbers:
    def __iter__(self):
        return InfiniteIterator()


infinite_numbers = InfiniteNumbers()

for x in infinite_numbers:
    print(x)

    if x > 99:
        break

If you remove the break statement and the if block, you will notice, it keeps running Рlike forever.

Using StopIteration

Instead of breaking out from our code ourselves, we could use the StopIteration exception in our iterator so it stops after giving us the 100 numbers.

class HundredIterator:
    def __init__(self):
        self.__int = 0

    def __next__(self):
        if self.__int > 99:
            raise StopIteration

        self.__int += 1
        return self.__int


class InfiniteNumbers:
    def __iter__(self):
        return HundredIterator()


one_hundred = InfiniteNumbers()

for x in one_hundred:
    print(x)

Iterators must also implement __iter__

We saw that the __next__¬†method does it’s work just fine. But we also need to implement the __iter__¬†method on an iterator (just like we did in iterable). Why is this required? Let me quote from the official docs:

Iterators are required to have an__iter__() method that returns the iterator object itself so every iterator is also iterable and may be used in most places where other iterables are accepted.

If we tried to use the for loop over our iterator, it would fail:

class HundredIterator:
    def __init__(self):
        self.__int = 0

    def __next__(self):
        if self.__int > 99:
            raise StopIteration

        self.__int += 1
        return self.__int


one_hundred = HundredIterator()

for x in one_hundred:
    print(x)

We will get the following exception:

Traceback (most recent call last):
  File "iter.py", line 15, in <module>
    for x in one_hundred:
TypeError: 'HundredIterator' object is not iterable

That kind of makes sense because we saw that the for loop runs the iter¬†function on an object to get an iterator from it. Then calls next¬†on the iterator. That’s the problem, we don’t have an __iter__¬†method. The official documentation suggests that every iterator should be a proper iterable too. That is, it should implement the __iter__¬†method and just return an instance of itself. Let’s do that:

class HundredIterator:
    def __init__(self):
        self.__int = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.__int > 99:
            raise StopIteration

        self.__int += 1
        return self.__int


one_hundred = HundredIterator()

for x in one_hundred:
    print(x)

Now the code works fine ūüôā

The Iterator Protocol

The iterator protocol defines the special methods that an object must implement to allow iteration. We can summarize the protocol in this way:

  • Any object that can be iterated over needs to implement the __iter__¬†method which should return an iterator object. Any object that returns an iterator is an iterable.
  • An iterator must implement the __next__¬†method which returns the next item when called. When all items are exhausted (read retrieved), it must raise the StopIteration¬†exception.
  • An iterator must also implement the __iter__¬†method to behave like an iterable.

Why do we need Iterables?

In our last example, we saw that it’s possible for an object to implement a __next__¬†method and an __iter__¬†method that returns self. In this way, an iterator behaves just like an iterable alright. Then why do we need Iterables? Why can’t we just keep using Iterators which refer to itself?

Let’s get back to our HundredIterator¬†example. Once you have iterated over the items once, try to iterate again. What happens? No numbers are output on the screen. Why? Well, because the iterator objects store “state”. Once it has reached StopIteration, it has reached the end line. It’s now exhausted.¬†Every time you call iter¬†on it, it returns the same instace (self) which has nothing more to output.

This is why Iterables are useful. You can just return a fresh instance of an iterator every time the iterable is looped over. This is actually what many built in types like list does.

Why is Iterators so important?

Iterators allow us to consume data each item at a time. Just imagine, if there’s a one GB file and we tried to load it all in memory, it would require huge memory. But what if we implemented an iterator that reads the file one line at a time? We could then just store that one line in memory and do necessary processing before moving on to the next item. This allow us to write really efficient programs ūüôā

This all seems very confusing

If you find the concepts very confusing and hard to grasp, don’t worry. Give it a few tries, write the codes by hand and see the output. Tinker with the examples. Inspect the code, try to see what happens when you modify part of it. All things become easier when you practise more and more. Try writing your own iterables and iterators – perhaps try to clone the built in containers’ functionalities? May be write your own list implementation? Don’t worry, it will come to you in time.

 

Django REST Framework: JSON Web Tokens (JWT)

(This post is a part of a tutorial series on Building REST APIs in Django)

Our last post was about Authentication and Permissions and we covered the available methods of authentication in Django REST Framework. In that post, we learned how to use the built in Token based authentication in DRF. In this post, we will learn more about JSON Web Tokens aka JWT and we will see if JWT can be a better authentication mechanism for securing our REST APIs.

Understanding JSON Web Tokens (JWTs)

We have actually written a detailed blog post about JSON Web Tokens earlier. In case you have missed it, you probably should read it first. We have also described how to use JWT with Flask – reading that one might also help better understand how things work. And of course, we will briefly cover the idea of JWT in this post as well.

If we want to put it simply – you take some data in JSON format, you hash it with a secret and you get a string that you use as a token. You (your web app actually) pass this token to the user when s/he logs in. The user takes the token and on subsequent requests, passes it back in the “Authorization” header. The web app now takes this token back, “decodes” it back to the original JSON payload. It can now read the stored data (identity of the user, token expiry and other data which was embedded in the JSON). While decoding, the same secret is used, so third party attackers can’t just forge a JWT. We would want our token to be small in size, so the JSON payload is usually intentionally kept small. And of course, it should not contain any sensitive information like user password.

JWT vs DRF’s Token Based Authentication

So in our last blog post, we saw Django REST Framework includes a token based authentication system which can generate a token for the user. That works fine, right? Why would we want to switch to JSON Web Tokens instead of that?

Let’s first see how DRF generates the tokens:

    def generate_key(self):
        return binascii.hexlify(os.urandom(20)).decode()

It’s just¬†random. The token generated can not be anyway related to the user that it belongs to. So how does it associate a token with an user? It stores the token and a reference to the user in a table in database. Here comes the first point – while using DRF’s token based auth, we need to query database on every request (unless of course we have cached that token which). But what if we have multiple application servers?¬†Now we need all our application servers to connect to the same database or same cache server. How will that scale when the project gets really really big? What if we want to provide single sign on across multiple services? We will need to maintain a central auth service where other services request to verify a token. Can JWT simplify these¬†for us?

JWT is just an encoded (read – hashed / signed) JSON data. As long as any webservice has access to the secret used in signing the data, it can also decode and read the embedded data. It doesn’t need any database calls. You can generate the token from one service and other services can read and verify it just fine. It’s more efficient and simply scales better.

JWT in Django REST Framework

DRF does not directly support JWTs out of the box. But there’s an excellent package that adds support for it. Let’s see how easily we can integrate JWT in our REST APIs.

Install and Configure

Let’s first install the package using pip¬†–

pip install djangorestframework-jwt

That should install the package. Now we need to add rest_framework_jwt.authentication.JSONWebTokenAuthentication to the default authentication classes in REST Framework settings.

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.TokenAuthentication',
    )
}

We added it to the top of the list. Next, we just have to add it’s built in view to our urlpatterns.

from rest_framework_jwt.views import obtain_jwt_token

urlpatterns = router.urls + [
    url(r'^jwt-auth/', obtain_jwt_token),
]
Obtain a Token

The obtain_jwt_token¬†view will check the user credentials and provide a JWT if everything goes alright. Let’s try it.

$ curl --request POST \
  --url http://localhost:8000/api/jwt-auth/ \
  --header 'content-type: application/json' \
  --data '{"username": "test_user", "password": "awesomepwd"}'

{"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyLCJlbWFpbCI6IiIsInVzZXJuYW1lIjoidGVzdF91c2VyIiwiZXhwIjoxNDk1OTkyOTg2fQ.sWSzdiBNNcXDqhcdcjWKjwpPsVV7tCIie-uit_Yz7W0"}

Awesome, everything worked just fine. We have got our token too. What do we do next? We use this token to access a secured resource.

Using the obtained JWT

We need to pass the token in the form of JWT <token>¬†as the value of the Authorization¬†header. Here’s a sample curl request:

$ curl -H "Content-Type: application/json" -H "Authorization: JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyLCJlbWFpbCI6IiIsInVzZXJuYW1lIjoidGVzdF91c2VyIiwiZXhwIjoxNDk1OTkyOTg2fQ.sWSzdiBNNcXDqhcdcjWKjwpPsVV7tCIie-uit_Yz7W0" -X GET  http://localhost:8000/api/subscribers/

[{"id":1,"name":"Abu Ashraf Masnun","age":29,"email":"[email protected]"},{"id":2,"name":"Abu Ashraf Masnun","age":29,"email":"[email protected]"},{"id":3,"name":"Abu Ashraf Masnun","age":29,"email":"[email protected]"},{"id":4,"name":"Abu Ashraf Masnun","age":29,"email":"[email protected]"}]

So our token worked fine! Cool!

Where to go next?

Now that you have seen how simple and easy it is to add JSON Web Token based authentication to Django REST Framework, you probably should dive deeper into the package documentation. Specially these topics might be interesting –

  • Refresh Tokens: If you enable JWT token refreshing, you can exchange your current token with a new, fresh one before¬†the existing one expires. The new token will of course have a renewed expiry time set.
  • Verify Token: If you just share the secret, all services can verify the user on their own. However, in modern micro service based architecture, you may want to provide an API end point that other services can use to verify a JWT they received from the user. This can be useful for those scenarios.
  • And of course look at the settings options available¬†and see how you can customize the token generation process.

In the future, we shall try to cover more about Django, Django REST Framework and Python in general. If you liked the content, please subscribe to the mailing list so we can notify you when we post new contents.

Kotlin: An Introduction

In Google I/O 2017, Kotlin was announced as an officially supported language for android development. The news created a massive buzz among the developers community. Google is a big name and so is Android. So that level of attention was only¬†natural. But many of those who have followed the language since¬†it’s inception, didn’t need to wait this long to fall in love with the language. Kotlin is a brilliant language. It’s statically typed yet quite productive. The syntax does not feel rigid or restrictive, rather it feels rather expressive and enjoyable. Writing code in Kotlin is really fun. You don’t have to trust my word for that,¬†just give it a try.

History of Kotlin

In case you didn’t know, Kotlin is named after the Kotlin Island near Saint Petersburg, Russia. You can read more about the Island in Wikipedia. So another programming language named after an Island, but why? Well, Kotlin is developed by those awesome guys at Jetbrains¬†¬†who build our favorite IDEs. Apparently Kotlin was developed in their Saint Petersburg office and the developers named it after the Island.

Jetbrains was using Java to build their IDEs but why did they decide to create a language of their own? The answer is probably obvious to you by now. Every new language is created out of frustration from the existing ones. We already saw a similar story in our post about Golang. The same thing happened here too. Jetbrains lead Dmitry Jemerov mentioned they were looking for features not offered by Java or most other languages. They liked Scala but the compile time was a bugger. So they came up with Kotlin and thanks to them that they did!

Work on Kotlin started in 2010 and Jetbrains announced the language publicly in July 2011. They made the project open source under the Apache 2 License in 2012. They continued developing the language by accepting and reviewing user’s feedback. After a lot of improvements and iteration, the language reached version 1.0 in February 2016, the first officially stable release with commitment towards backward compatibility. That was just a year go. Kotlin became quickly popular and developers seemed to love it. Many large companies started adopting it even before it became officially supported on Android. But the official support didn’t take long either, in Google I/O 2017, first class support came for Kotlin on Android.

Write once, Run Everywhere

Do you recognize the words – “Write once, run anywhere / everywhere”? If you’re a Java developer, you might recognize them. Kotlin takes things a little bit further than that. Kotlin started off as a language based on the JVM. You could run Kotlin anywhere you could run Java. But that’s not all, Kotlin code now can be transpiled into Javascript too! You already know it works on Android. The guys are also working on a native version based on LLVM. Once that happens, you can truly write code once and run them anywhere and everywhere. Of course you can’t fully port all codes from one platform to another, for example if you’re using JavaFX on the JVM, those will not work on the browser. But the common business logic can be ported without much¬†efforts in most cases.

Kotlin is fully interoperable with Java and can take advantage of the JVM. So the plethora of existing Java libraries and packages are at your disposal. This opens up enormous possibilities and a large eco system to the enterprising Kotlin developer.

Most Loved Kotlin Features

So what makes Kotlin great? Why do people love it? Here are some of the features people love in the language:

  • Full interoperability with Java (and the JVM)
  • Multi platform – JVM, Android, Browser and Native (coming soon)
  • The syntax is quite similar to other popular programming languages. Expressive and productive.
  • Type inference is another cool feature. You can just write val number = 23¬†and it an identify that it’s an Int. You can of course declare the type if you wish ūüôā
  • The when¬†block can cut the need of complex if/else block or switch statements and makes things simpler.
  • Libraries like Anko¬†not only makes android development faster, it also makes if more enjoyable. Also the android extensions for Kotlin makes many pain points easier to handle.
  • Functions are fun, literally ūüėČ fun meaningOfLife() = 42¬†– see? fun¬†– it is! ūüėÄ
  • Simple one line functions paired with string interpolation is pretty useful¬†– fun fullName() = "${first} ${last}"
  • The idea of data class is to provide easy POJOs in a very short, concise manner.
  • Operator overloading is quite simple.
  • You can add extension functions to classes, even built in ones, easily extending their functionality.
  • Kotlin provides null safety by forcing you to check nullable types for null first. No more NullPointerException¬†for you! ūüėČ
  • Lambdas are super fun. Expressive, powerful and of course productive.
  • Easy to use and useful ranges.
  • Easy to add custom get¬†and set¬†methods to public fields. Pair that with simple functions. You have got properties without much boilerplate code.
  • The default arguments and named arguments are pretty cool
  • You can use ==¬†for checking equality, no need for equals¬†calls.
  • The is¬†operator provides automatic smart casts. When you write if (param is String) { // code }, the param¬†is cast into a string for you in the block. So no more instance checks.
  • Super expressive maps, filters with lambdas
  • Ability to create custom DSLs
  • Coroutines
  • Awesome tooling support. IntelliJ Idea lets you convert Java code to Kotlin in just a click. You know their IDE is the best, right? But there’s also support for other popular IDEs like Eclipse.

Learning Kotlin

You can also visit us on the Facebook, we have a group named – Kotlin Ninja¬†where some Kotlin enthusiasts learn and share together ūüôā

Django REST Framework: Authentication and Permissions

(This post is a part of a tutorial series on Building REST APIs in Django)

In our last post about ViewSet, ModelViewSet and Router, we saw how easily we can create REST APIs with the awesome Django REST Framework. In this blog post, we would see how we can secure our endpoints with user authentication and permissions. Authentication will help us identify which user is currently logged in and permissions will decide which user(s) can access which resources.

Authentication

The idea of authentication is pretty simple. When a new incoming request comes, we have to check the request and see if we can identify any user credentials along with it. If you have read the Flask HTTP Auth tutorial or the one about JWT, you might remember how we were checking the authorization header to authenticate our users. We might also receive the user login data via a POST request (form submission) or the user may already be logged in and we can identify using the session data.

We can see that the authentication mechanism can largely vary. Django REST Framework is very flexible in accommodating them. We can give DRF a list of classes, DRF will run the authenticate method on those classes. As soon as a class successfully authenticates the user, the return values from the call is set to request.user and request.auth. If none of the classes manage to authenticate the user, then the user is set to django.contrib.auth.models.AnonymousUser .

We can set these classes using the DEFAULT_AUTHENTICATION_CLASSES¬†settings under the DRF settings. Here’s an example:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    )
}

In the example above we used BasicAuthentication and SessionAuthentication Рtwo of the built in classes from Django REST Framework. We will look at how they work and we will also check how we can write our own class for our custom authentication.

(PS: Here we set the authentication policy globally, for all views / paths / resources – if we want, we can also use different authentication mechanism for each one, individually but that is usually not done in most cases).

Basic Authentication

In our example before, we mentioned the BasicAuthentication class. This class first checks the http authorization header (HTTP_AUTHORIZATION in request.META ). If the header contains appropriate string (something like Basic <Base64 Encoded Login>), it will decode the string, split the username, password and try to authenticate the user.

Basic Authentication is very simple, easy to setup and might be quite convenient for testing / debugging but I would highly discourage using this method on production.

Session Authentication

If you have used Django, you already know about session based authentication. In fact, Django itself handles the session based auth and sets the user as part of the request¬†object (an instance of HttpRequest¬†object. DRF just reads the user data from the request and checks for CSRF. That’s it.

Session Authentication works very well if your users are interacting with your API on the web, perhaps using ajax calls? In such cases, if the user is once logged in, his/her auth¬†is stored in the session and we can depend on those data while making requests from our web app. However, this will not work well if the client doesn’t or can not accept cookies (apps on different domains, mobile or desktop apps, other micro services etc).

Token Authentication

If you understand JWT, this one will feel similar, except in this case, the token will be just a “token”, no JSON or no signing. The user logs in and gets a token. On subsequent requests, this token must be passed as part of the authorization header.

To use token based auth, we first need to add the rest_framework.authtoken app to the INSTALLED_APPS list in your settings.py file. And then run the migration to create the related tables.

python manage.py migrate

We also need to add the TokenAuthentication class to our DRF auth class list:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.TokenAuthentication',
    )
}

Now let’s create a view to issue tokens to user.

from django.contrib.auth import authenticate
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.status import HTTP_401_UNAUTHORIZED
from rest_framework.authtoken.models import Token


@api_view(["POST"])
def login(request):
    username = request.data.get("username")
    password = request.data.get("password")

    user = authenticate(username=username, password=password)
    if not user:
        return Response({"error": "Login failed"}, status=HTTP_401_UNAUTHORIZED)

    token, _ = Token.objects.get_or_create(user=user)
    return Response({"token": token.key})

The code here should be self explanatory. We take username and password. We then try to authenticate the user using Django’s default authentication (checking username and password against what’s stored in the database). If the authentication fails, we return error message along with http status code 401.¬†If the authentication succeeds, we issue a token for the user and pass it in the response.

We need to add this view to our urlpatterns next:

url(r'^login', login)

Now let’s try it out:

$ curl --request POST \
  --url http://localhost:8000/api/login \
  --header 'content-type: application/json' \
  --data '{"username": "test_user", "password": "awesomepwd"}'

{"token":"5e2effff34c85c11a8720a597b96d73a4634c9ad"}%

So we’re getting the tokens successfully. Now to access a secured resource, we need to pass it as part of the authorization header. But how do we make a resource available only to a logged in user? Well, permissions come into play here.

Permissions

While authentication tells us which user is logged in (or not), it’s our responsibility to check if the current user (a valid logged in user or a guest, not logged in visitor) has access to the resource. Permissions¬†can help us deal with that. Just like authentication, we can also set a class of permissions globally or on each resource individually. Let’s start with the IsAuthenticated¬†permission first. Let’s add this to our SubscriberViewSet.

from rest_framework.permissions import IsAuthenticated

class SubscriberViewSet(ModelViewSet):
    serializer_class = SubscriberSerializer
    queryset = Subscriber.objects.all()
    permission_classes = (IsAuthenticated,)

If we try to access subscribers without any authentication, we will get an error message now:

{
  "detail": "Authentication credentials were not provided."
}

So let’s provide authentication using the token we got.

$ curl -H "Content-Type: application/json" -H "Authorization: Token 5e2effff34c85c11a8720a597b96d73a4634c9ad" http://localhost:8000/api/subscribers/

Now it works fine! There are many useful, already provided permission classes with Django REST Framework. You can find a list of them here http://www.django-rest-framework.org/api-guide/permissions/#api-reference.

Custom Authentication and Permissions

The authentication and permission classes which come with DRF are quite enough for many cases. But what if we needed to create our own? Let’s see how we can do that.

Writing a custom authentication class is very simple. You define your custom authenticate method which would receive the request object. You will have to return an instance of the default User model if authentication succeeds, otherwise raise an exception. You can also return an optional value for the auth object to be set on request. If our authentication method can not be used for this request, we should return None so other classes are tried.

Here’s an example from DRF docs:

from django.contrib.auth.models import User
from rest_framework import authentication
from rest_framework import exceptions

class ExampleAuthentication(authentication.BaseAuthentication):
    def authenticate(self, request):
        username = request.META.get('X_USERNAME')
        if not username:
            return None

        try:
            user = User.objects.get(username=username)
        except User.DoesNotExist:
            raise exceptions.AuthenticationFailed('No such user')

        return (user, None)

In this example, the username is being retrieved from a custom header (X_USERNAME) and the rest is quite easy to understand.

Next, let’s see how we can create our custom permission class. For permissions, we can have two types of permissions – global permission or per object permission. Here’s an example of global permission from DRF docs:

from rest_framework import permissions

class BlacklistPermission(permissions.BasePermission):
    """
    Global permission check for blacklisted IPs.
    """

    def has_permission(self, request, view):
        ip_addr = request.META['REMOTE_ADDR']
        blacklisted = Blacklist.objects.filter(ip_addr=ip_addr).exists()
        return not blacklisted

If the has_permission¬†method returns True¬†then the user has permission, otherwise not. Let’s see the example for per object permission:

class IsOwnerOrReadOnly(permissions.BasePermission):
    """
    Object-level permission to only allow owners of an object to edit it.
    Assumes the model instance has an `owner` attribute.
    """

    def has_object_permission(self, request, view, obj):
        # Read permissions are allowed to any request,
        # so we'll always allow GET, HEAD or OPTIONS requests.
        if request.method in permissions.SAFE_METHODS:
            return True

        # Instance must have an attribute named `owner`.
        return obj.owner == request.user

For dealing with per object permission, we can override the has_object_permission method. It can take the request, the view and the obj. We have to check if the current user can access the obj in question. Just like before, we need to return True or False to allow or deny the request.

In this blog post, we learned the basics of authentication and permissions. We now know how we can secure our API endpoints with DRF. While the token based authentication was very useful, we kind of like JWT. So in our next post, we will be using a third party package to implement JWT for Django REST Framework.

Django REST Framework: ViewSet, ModelViewSet and Router

(This post is a part of a tutorial series on Building REST APIs in Django)

In our last blog post on ModelSerializer and Generic Views, we demonstrated how we can use the generic views along with ModelSerializer classes to rapidly develop our REST APIs. In this post, we will discuss about ViewSet and ModelViewset and see how they can speed up building APIs even further. At the same time we will take a look at the concepts of Routers which allow us to manage our api routes in a cleaner fashion.

Understanding ViewSet

So far we have learned how we can use the generic views. We can now use them to create the two kinds of resources – “collections” and “elements”. It works very well but we need to write at least two different classes to handle them properly. But if we think about it, both resources focus on the same entity, the same model – “Subscriber”. Wouldn’t it make more sense if we could have all the actions related to a Subscriber in a single class? Wouldn’t that be more convenient if we can put all the Subscriber related logic in a single place?

ViewSets come to the rescue. A ViewSet¬†is, as the name suggests, a class that provides the functionality of a set of views which are closely related. It’s one class but provides a set of views. We can handle both “collection” and “element” type of resources from the same class. And not just those, we can add even other¬†related actions.

Since a ViewSet handles both type of resources, we can no longer think in terms of the http verbs. Because both /api/subscriber and /api/subscriber/1 can respond to  GET requests and should produce different types of response. So we can no longer work with the get, post, put etc methods. We need to think more along the actions we can take on the entity (Subscriber) as a whole. A ViewSet works with these methods instead:

  • list¬†– list all elements, serves GET¬†to /api/subscriber
  • create¬†– create a new element, serves POST¬†to /api/subscriber
  • retrieve¬†– retrieves one element, serves GET¬†to /api/subscriber/1
  • update¬†and partial_update – updates single element, handles PUT/PATCH¬†to /api/subscriber/1
  • destroy¬†– deletes single element, handles DELETE¬†to /api/subscriber/1

Instead of our old get¬†and post¬†methods in separate classes, we can now define these methods in one single class and be done with it. But with general ViewSet, we have to provide logic / code for these views. That would¬†require more time and efforts. What if, we could generate these methods from our models / querysets? Well, we can! ūüėÄ

The ModelViewSet

The ModelViewSet¬†would only ask for the serializer class and the queryset. And then it will provide all the functionality of the different¬†ViewSet¬†methods. Let’s see the example:

from rest_framework.viewsets import ModelViewSet

from .serializers import SubscriberSerializer
from .models import Subscriber


class SubscriberViewSet(ModelViewSet):
    serializer_class = SubscriberSerializer
    queryset = Subscriber.objects.all()

Our SubscriberViewSet now extends the ModelViewSet and we provided the queryset and the serializer_class. Done. Really!

But there’s one slight problem, the ViewSet¬†and ModelViewSet¬†both handle at least two distincts url paths – /api/subscriber¬†(the collection path) and /api/subscriber/1¬†– the elements path. How do we tell Django’s URLConf to route requests to both urls to our single ViewSet? Well, we have to declare those paths ourselves. We can use the as_view¬†to both paths, defining which http verb should be routed to which methods:

SubscriberViewSet.as_view({'get': 'list', 'post':'create'}) # For: /api/subscriber
SubscriberViewSet.as_view({'get': 'retrieve', 'put':'update'}) # For: /api/subscriber/1

Or we can simply use a Router.

Using Routers

A Router¬†instance let’s us register¬†our ViewSet¬†to it and then we can just add the router.urls¬†to our urlpatterns. It will keep track of the view sets we register and the urls¬†property will generate all the url patterns required for those view sets to work. ¬†Let’s add our newly created SubscriberViewSet¬†to a router and see for ourselves. Open the api/urls.py¬†file and create the router there and register the viewset.

from rest_framework.routers import SimpleRouter

from .views import SubscriberViewSet

router = SimpleRouter()
router.register("subscribers", SubscriberViewSet)

urlpatterns = router.urls

That’s all that is required. Now try visiting – http://localhost:8000/api/subscribers or¬†http://localhost:8000/api/subscribers/1 – it all works.

Fantastic, so we just generated a full RESTful API from a model with¬†a surprisingly short amount of code! Isn’t that wonderful? Just don’t trust my words, go and look at your SubscriberViewSet¬†or the SubscriberSerializer¬†or the above defined router.

With the help of ModelSerializer, ModelViewSet and a router instance, we can build elegant CRUD APIs from our Django models insanely fast. At the same time, if we need, we can just override one of those methods (list, retrieve, create etc) to alter the default behavior with our own.

What’s Next?

We have crafted a nice, functional REST API. The next stop would be securing it. In our next post, we will be discussing Authentication and Permissions.

In the mean time, I would request you to subscribe to the mailing list so I can keep you posted about new exciting contents on this site. If you liked the post, please do share with your friends!

 

Django REST Framework: ModelSerializer and Generic Views

(This post is a part of a tutorial series on Building REST APIs in Django)

In our last post on Serializers, we learned how to use Serializers with APIViews. In this post we will discuss how ModelSerializer and the Generic views can take things even further.

Model + Serializer = ModelSerializer

That one line equation is probably enough to explain the concepts of ModelSerializers. In our example, we had to define similar fields on both Serializer and the Model class. We had to write codes for the same fields twice. That is 2x the efforts. ModelSerializers can help solve that problem. A ModelSerializer might remind us of ModelForm. The idea is the same. We extend ModelSerializer and pass it the model. The serializer inspects the model and knows what fields to use and what their types are.

Let’s refactor our old serializer to be a ModelSerializer:

from rest_framework import serializers

from .models import Subscriber


class SubscriberSerializer(serializers.ModelSerializer):
    class Meta:
        model = Subscriber
        fields = "__all__"

That’s all we need – our new SubscriberSerializer¬†now infers the fields from the model (Subscriber) we passed to it. We can however choose which fields should be used while serializing / deserializing. In this example we pass the special value “__all__” which means we want to use all fields. But in many cases we would want to selectively use some fields. For example, for Django’s default¬†User¬†model, we don’t want to leak the password¬†data to public, so we will exclude the password¬†field on our User model serializer.

If we try out our API, we would notice everything is working just like before. Except our serializer class is now shorter and more concise. Awesome, right? Let’s move on to our next topic – generic views.

Generic Views

If you have decent amount of experience with Django, you probably have already come across and used the built in generic views. They provide useful functionality around common database operations. For example, we can use the generic list view and provide it with a queryset and the template, it will do the rest for us.

In the same way, we can pass a queryset and serializer to a ListAPIView¬†and it will create the list view for us. Same way we can use CreateAPIView¬†to implement the create view. What’s even better, since we’re using class based views, we can use both of them together, cool, no? Let’s refactor old code to use these two classes.

from rest_framework.generics import ListAPIView, CreateAPIView

from .serializers import SubscriberSerializer
from .models import Subscriber


class SubscriberView(ListAPIView, CreateAPIView):
    serializer_class = SubscriberSerializer
    queryset = Subscriber.objects.all()

Please note how we no longer need to provide the get and post methods but the API still works. The generic views just know how to deal with those.

There is actually a ListCreateAPIView which is the combination of these two as you can probably understand from the class name. We can just use that one.

from rest_framework.generics import ListCreateAPIView

from .serializers import SubscriberSerializer
from .models import Subscriber


class SubscriberView(ListCreateAPIView):
    serializer_class = SubscriberSerializer
    queryset = Subscriber.objects.all()

As you can see this generic view is quite helpful for generating “collection” resources (/api/subscriber) easily. There’s also RetrieveUpdateDestroyAPIView which we can use to generate “element” resources. As you can guess from the name, they provide get, put, patch¬†and delete¬†handler for single items (/api/subscriber/12).

Generic views are very handy for quickly generating resources from our models (querysets actually). This allows rapid API development.

What’s Next?

We have seen how we can very quickly create working REST APIs using model serializers and generic views.¬†Things will be even more amazing when we learn about ViewSets, specially ModelViewSets. You will have to wait for our next post for those ūüôā

In case you didn’t notice, we have a mailing list where you can subscribe to get latest updates. We don’t spam, only contents we post. Also if you enjoyed reading the post and found it informative, shouldn’t you share it with your friends? ūüėÄ

Django REST Framework: Serializers

(This post is a part of a tutorial series on Building REST APIs in Django)

In our last blog post, Getting started with Django REST Framework, we saw how we could use the APIView and accept inputs from users using request.data. In our example, we dealt with string, so it was pretty straightforward. But consider the case of age or account_balance Рone has to be integer, the other has to be float / decimal. How do we properly validate the incoming data?

We can manually check every input field and send an error if the field type doesn’t match. But soon we’re going to have a problem at our hand – when the number of inputs will grow, we can’t just keep doing this kind of manual validation. In Django, we would probably use Django Forms for validation. Does DRF provide us with something similar? Yes, it does. The solution to our problem is Serializers.

What can a Serializer do for us?

Have you ever tried JSON serializing a Django model? Or a queryset? You can’t directly because they are not JSON serializable. So what do we do instead? We convert them to Python’s native data structures which could be serialized into JSON. We can serialize querysets into lists and model instances to dictionaries. But doing that by hand is cumbersome.

On the other hand, we saw how we can get incoming data from request.data¬†– we get this data¬†as key value pairs. We can’t just store them in database directly – we have to transform them into Django’s data structures like models and querysets. Doing that by hand is also cumbersome.

Serializers can help us with that. It can serialize complex types into Python natives types and then again deserialize native types into those complex types. Besides that, it also does basic validation based on the serializer field types. If a field is defined as an integer field, it will raise an error if we pass a string to that field. If we need more advanced validation rules, we can plug in the built in Validators¬†or even write our own. Let’s see code examples to understand the use case better.

Defining a Serializer

Create a file named serializers.py inside the api app directory. Put the following codes into it.

from rest_framework import serializers


class HelloWorldSerializer(serializers.Serializer):
    name = serializers.CharField(required=True, max_length=6)
    age = serializers.IntegerField(required=False, min_value=10, default=10)

We’re creating a HelloWorldSerializer¬†which extends serializers.Serializer. We’re defining two fields on this serializer –

  • name¬†is a CharField¬†so it accepts string. It has a max_length¬†of 6.
  • age¬†is an optional integer field. The value must be at least 10 if provided. If not provided, default value will be 10.

With this serializer setup, let’s modify our view to use it.

from .serializers import HelloWorldSerializer


class HelloWorldView(APIView):
    def get(self, request):
        return Response({"message": "Hello World!"})

    def post(self, request):
        serializer = HelloWorldSerializer(data=request.data)
        if serializer.is_valid():
            valid_data = serializer.data

            name = valid_data.get("name")
            age = valid_data.get("age")

            return Response({"message": "Hello {}, you're {} years old".format(name, age)})
        else:
            return Response({"errors": serializer.errors})

We pass the request.data as the data parameter to HelloWorldSerializer so it can read all the request data and parse them. Then we check if the serializer is valid. If you have used Django Forms, this will feel very similar. If the serializer is valid, that means we have a valid set of data available. So we can take the value of name and age and show a pretty message. On the other hand, if the serializer is not valid, we can pass the serializer.errors back to the client, which will contain elaborate error messages.

Let’s try out the API to see what happens. Let’s first send an empty request:

$ curl -H "Content-Type: application/json" -X POST http://localhost:8000/api/hello

{"errors":{"name":["This field is required."]}}

The errors say the name¬†field is required. Of course it is! Let’s pass the name.

$ curl -H "Content-Type: application/json" -X POST -d '{"name": "masnun"}' http://localhost:8000/api/hello

{"message":"Hello masnun, you're 10 years old"}

We just passed the name but didn’t pass the age. Since it is not required and has a default value set, we get the default value. But what if we set a low value?

$ curl -H "Content-Type: application/json" -X POST -d '{"name": "masnun", "age": '8'}' http://localhost:8000/api/hello

{"errors":{"age":["Ensure this value is greater than or equal to 10."]}}

So we passed 8¬†and it’s not happy about that. Please note we passed the 8 as a string but DRF doesn’t mind as long as it can convert it to an integer successfully. What if we pass a value that is no number?

$ curl -H "Content-Type: application/json" -X POST -d '{"name": "masnun", "age": "ten"}' http://localhost:8000/api/hello

{"errors":{"age":["A valid integer is required."]}}

That works too! Cool, okay then let’s give it a rest and pass a valid value.

$ curl -H "Content-Type: application/json" -X POST -d '{"name": "masnun", "age": 12}' http://localhost:8000/api/hello

{"message":"Hello masnun, you're 12 years old"}

 Serializer with Model

How does Serializers help us in working with models? To understand that, let’s first create one model.

Creating the Subscriber Model

Open api/models.py and add the Subscriber model like this:

class Subscriber(models.Model):
    name = models.CharField("Name", max_length=50)
    age = models.IntegerField("Age")
    email = models.EmailField("Email")

Now create and run the migration.

python manage.py makemigrations
python manage.py migrate

That should setup the table for our new model.

Update The Serializer

We added an email field to our model, also the max length for name is now 50 chars. Let’s update our serializer to match these constraints. Also rename it as SubscriberSerializer.

from rest_framework import serializers


class SubscriberSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=50)
    age = serializers.IntegerField()
    email = serializers.EmailField()
Update The View

And now let’s refactor our view.

from .serializers import SubscriberSerializer
from .models import Subscriber


class SubscriberView(APIView):
    def get(self, request):
        return Response({"message": "Hello World!"})

    def post(self, request):
        serializer = SubscriberSerializer(data=request.data)
        if serializer.is_valid():
            subscriber_instance = Subscriber.objects.create(**serializer.data)
            return Response({"message": "Created subscriber {}".format(subscriber_instance.id)})
        else:
            return Response({"errors": serializer.errors})

The code is very simple and straightforward. If the serializer validation succeeds, we create a new subscriber out of the validated data.

Update URLConf

Let’s update the urls.py¬†to update our url end point.

url(r'^subscriber', SubscriberView.as_view(), name="subscriber")

Now let’s try it out. We will post the following JSON using curl or postman:

{"name": "Abu Ashraf Masnun", "email": "[email protected]", "age": 29}

And we will get back the following response:

{
  "message": "Created subscriber 1"
}

With the serializer, we needed so much less codes. And we did it in a very clean way.

List All Subscribers

According to the REST Best Practices, the GET¬†call to a resource route (/api/subscriber) should return a list of all the items (subscribers). So let’s refactor the get¬†method to return the subscribers list.

    def get(self, request):
        all_subscribers = Subscriber.objects.all()
        serialized_subscribers = SubscriberSerializer(all_subscribers, many=True)
        return Response(serialized_subscribers.data)

We are fetching all subscribers and then passing the queryset to the serializer constructor. Since we’re passing a query set (not just a single model instance rather a list of model instances), we need to set ¬†many=True¬†. Also note,¬†we don’t need to call is_valid¬†– the data is coming from database, they’re already valid. In fact, we can’t call is_valid¬†unless we’re passing some value to the data¬†parameter (SubscriberSerializer(data=request.data)). When we pass queryset or model, the data is automatically available as serializer.data.

What’s Next?

We have so far learned how to use APIView¬†and Serializer¬†to build beautiful APIs with clean code. But we still have some duplication of efforts, for example when we had to define fields on both the model and the serializer. Also, we have to implement both collection and element resources. So that’s like 5 method implementation. Wouldn’t it be great if, by some mechanism we could¬†make things simpler, shorter and cleaner?

We’ll see, in our next blog post ūüôā Please subscribe to our mailing list for email updates. Also if you liked the content, please don’t forget to share with your friends!

 

Django REST Framework: Getting Started

(This post is a part of a tutorial series on Building REST APIs in Django)

In our last post about Building APIs in Django, we explained why using Django REST Framework would be a good idea. In this post, we will start writing our APIs using this awesome framework. DRF itself works on top of Django and provides many useful functionality that can help with rapid API development.

Installing Django REST Framework

We have to install DRF first. We can install it using pip as usual.

pip install djangorestframework

Once the installation succeeds, add rest_framework to the INSTALLED_APPS list in settings.py.

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    

    'rest_framework',
    
    'api'
]

Now we are ready to start building our awesome APIs!

Using APIView

APIView¬†class is quite similar to Django’s View¬†class except it is more REST-y! The APIView¬†class can be considered as quite similar to the Flask Resource class from our Flask Tutorial. An APIView¬†has methods for the HTTP verbs. We can implement our own methods to handle those requests the way we want.

Let’s modify the function we wrote in our first post¬†to use APIView¬†instead.

from rest_framework.views import APIView
from rest_framework.response import Response


class HelloWorldView(APIView):
    def get(self, request):
        return Response({"message": "Hello World!"})

We have done two things –

  • Our¬†HelloWorldView¬†extends APIView¬†and overrides the get¬†method. So now DRF knows how to handle a GET¬†request to the API.
  • We return an instance of the Response¬†class. DRF will do the content negotiation for us and it will render the response in the correct format. We don’t have to worry about rendering JSON / XML any more.

Since we are now using a class based view, let’s update the urlconf and make the following change:

url(r'^hello', HelloWorldView.as_view(), name="hello_world")

That’s all the change that is necessary – we import the class based view and call the as_view¬†method on it to return a view that Django can deal with. Under the hood, the as_view¬†class method works as an entry point for the request. The class inspects the request and properly dispatches to the get, post, put¬†etc methods¬†to process the request. It then takes the result and sends back like a normal function based view would do. In short, the as_view¬†method kind of works as a bridge between the class based view and the function based views commonly used with Django.

The Web Browsable API

If you visit `http://localhost:8000/api/hello` you will now see a nice html view with our json response displayed along with other useful information (response headers). This html view is an excellent feature of DRF – it’s called the web browsable API. The APIs we create, DRF automagically generates a web view for us from where we can interact with our API, testing / debugging things. No need for swagger or any other external clients for testing. Awesome, no?

Function Based APIView

We can also use a function based form of APIView where we write a function and wrap it using the api_view decorator. An example would look like this:

from rest_framework.response import Response
from rest_framework.decorators import api_view


@api_view(["GET", "POST"])
def hello_world(request):
    if request.method == "GET":
        return Response({"message": "Hello World!"})

    else:
        name = request.data.get("name")
        if not name:
            return Response({"error": "No name passed"})
        return Response({"message": "Hello {}!".format(name)})

And in the urls.py, the entry will look like this:

url(r'^hello', hello_world, name="hello_world")

I mostly use function based views when things are really simple and I have to handle just one type of request (say, POST or GET). But in case I have to handle multiple type of requests, I will then have to check request.method to determine the type and handle accordingly. I find the class based view cleaner and well organized than writing a bunch of if else blocks.

You can read more about the function based APIView in the docs.

Accepting Input

We have seen how to write a simple end point to say “hello world!” – that is great. But now we must learn how we can handle inputs from our user. For this demonstration, on our /api/hello¬†endpoint, we would accept a name¬†in a POST request. If the name is passed, we will show a customized greeting. Let’s get to work!

class HelloWorldView(APIView):
    def get(self, request):
        return Response({"message": "Hello World!"})

    def post(self, request):
        name = request.data.get("name")
        if not name:
            return Response({"error": "No name passed"})
        return Response({"message": "Hello {}!".format(name)})

We have added a post method that should handle the POST requests. Instead of request.POST, we would use request.data which works across POST, PUT, PATCH  Рall other methods too. If the name is not passed we send error message. Otherwise we send a hello world message.

With that code written, let’s try it out –

$ curl -H "Content-Type: application/json" -X POST -d '{"name":"masnun"}' http://localhost:8000/api/hello

{"message":"Hello masnun!"}

Aha, things worked as expected! Cool! What if we don’t pass the name?

$ curl -H "Content-Type: application/json" -X POST  http://localhost:8000/api/hello

{"error":"No name passed"}

It works exactly like we wanted it to! Fantastic!

What’s next?

In this post, we saw how the APIView works and how we can accept inputs and send responses for different http verbs. In the next post, we will discuss about serializers and how they can be useful.

If you would like to get notified when we post new content, please subscribe to our mailing list. We will email you when there’s something new here ūüôā

Django: Building REST APIs

Recently, I have written a few pieces on REST API development. We have discussed the Fundamentals of REST APIs, Built a Simple REST API, Secured it with HTTP Basic Authentication and JSON Web Tokens. However, the example codes were all based on Flask. I chose Flask for those examples because¬†the framework was minimal in it’s core, light weight yet popular and with a matured eco system – very well¬†suited for¬†demonstrating simple REST APIs.¬†But if we consider popularity, probably no other framework is as popular as Django in the Python land. In my day to day work,¬†I use the framework quite extensively. Over the years, I have grown to become a passionate fan of Django. Naturally a tutorial series on building REST APIs with Django was just a matter of time.

Tutorial Index

This is the first part of the series. I shall update the index here as I keep adding new contents.

Code: https://github.com/masnun/djmailer

Prerequisites

The tutorial series will be heavily focused on building REST APIs. So there will be less scope of discussing the fundamentals of Django as we go. I would expect the reader to have decent familiarity of Django before hand. If you are new to Django, please spend some time with the Official Tutorial. It is very well written.

The tutorial series will use Python 3.6.0 (but any versions above Python 3.0 should work fine). As for Django, I have just installed the latest release as of today – ¬†1.11.¬†. We would also be using Django REST Framework, I have 3.6.3¬†right now. The example code repository will have an up-to-date requirements.txt¬†file – so don’t worry much about dependencies or their versions right now. Just make sure you use Python 3 and not Python 2.

Setting Up Django

Before we can start working on our awesome REST API, we first need to setup and configure our Django project. We need to install Django, install dependencies, start a project and an app, configure the database connection and write our first view. So what are we waiting for? Let’s get started!

Install Django and Dependencies

For now, we need the latest Django and a database driver. We will be using MySQL since it’s very popular and most people are familiar with it. In our production systems though, we mostly run PostgreSQL. We will discuss that choice in some later posts. Let’s install Django and the MySQL client using pip.

pip install django
pip install mysqlclient

Done? Cool. If Django installed successfully, you should be able to run the django-admin.py command. See if you can run it. If the command runs successfully, your installation worked. Time to move on to the next phase.

Create the Django Project

We want to build REST APIs for a mailing list. Let’s call it djmailer. We use the startproject¬†admin command to start our project.

django-admin startproject djmailer

We would now have a directory named djmailer¬†created in the current directory. Within that, there’s the default djmailer¬†app directory which contains the settings and root urlconf and the uwsgi app.

Create a New App

For the API related stuff, we would now create a new app named api. Let’s do that. First cd¬†into the project so you ¬†can access the manage.py¬†file. Now run this command:

python manage.py startapp api

Cool, now we have the api app created for us. Open up djmailer/settings.py and add api to the INSTALLED_APPS list.

Configure Database

In the default djmailer¬†app, there’s a file named settings.py. Open it up in your favorite text editor. We need to add our database credentials here. We will notice that a sample database configuration is already generated for us. Something like:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

The above example uses SQLite. But we want to use MySQL. So first create a database named djmailer on your MySQL server and create the database user and password. Then replace the above code with these lines:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'djmailer',
        'USER': 'djmailer',
        'PASSWORD': 'suP3rS3CR3t!X$%^',
    }
}

Once you have configured the database, please run the migrate management command.

python manage.py migrate

This should create the tables Django needs for itself.

Hello World!

Time to create our first view. Open api/views.py file and create the view:

from django.http.response import JsonResponse


def hello_world(request):
    return JsonResponse({"message": "hello world!"})

Instead of the usual HttpResponse, we used JsonResponse because we want to render our response as JSON. Using this class ensures that the reponse is JSON and the appropriate content type is set.

We can add this view directly to the root urlconf in djmailer/urls.py but we would like to better organize our urls. So we are going to create a new file named urls.py in the api directory and put the following content:

from django.conf.urls import url

from .views import hello_world

urlpatterns = [
    url(r'^hello', hello_world, name="hello_world")
]

If we add urls from all apps to the root urlconf, it will soon become a mess. Also the apps will not be reusable. But if we keep our app specific routes inside the app, we can just import them from the root urlconf. This keeps things clean and the app can be easily plugged into a different project if needed.

Let’s edit djmailer/urls.py¬†(the root urlconf) and import our api urls.

from django.conf.urls import url, include
from django.contrib import admin

from api import urls as api_urls

urlpatterns = [
    url(r'^api/', include(api_urls, namespace="api")),
    url(r'^admin/', admin.site.urls),
]

Focus on line 4 and 7. We are importing our api urls and putting them under the /api/ path. Run the django dev server:

python manage.py runserver

If we visit `http://localhost:8000/api/hello`, we would see the response:

{"message": "hello world!"}

Cool? We just built our first RESTful view with Django.

Introducing Django REST Framework (DRF)

Building REST APIs with plain old Django is very possible but we have to do a lot. We need to read incoming requests, parse them as JSON or XML (through content negotiation), in case of CRUD operations,¬†we also have to work with models and finally¬†we have to send back the response in appropriate format. It’s all possible in Django – but like I said, I have to do so many things on our own. Our initial hello world view was very basic, very simple. As the project grows and we have more and more complexities, things will start to get out of hands.

In our Flask examples, using a third party extension helped us get started faster and saved us much time and efforts. Django REST Framework is one such framework for Django. It provides so much functionality out of the box РI am a big fan of the framework. So while we can do everything without this framework, using it would make us productive and keep things sane.

So from now on, we would be using DRF to continue building our APIs. In the next blog post, we would be getting started with Django REST Framework.

What’s Next?

On our next post –¬†Django REST Framework: Getting Started, we introduce you to the wonderful world of DRF and demonstrate how we can use APIView¬†to build our endpoints.

In the mean time, please subscribe to our mailing list. We will keep you posted when we publish new content. ūüôā

JWT Authentication with Python and Flask

In our blog post about HTTP Authentication, we promised we would next cover JSON Web Tokens aka JWT based authentication. So we wrote a detailed blog post on The Concepts of JWT explaining how the technology works behind the scene. And in this blog post, we would see how we can actually implement it in our REST API. In case you have missed them, we have also explained the basics of REST APIs  along with a Python / Flask tutorial walking through some of the best practices.

PyJWT or a Flask Extension?

In our last blog post on JWT, we saw code examples based on the PyJWT library. A quick Google search also revealed a couple of Flask specific libraries. What do we use?

We can implement the functionality with PyJWT alright. It will allow us fine grained control. We would be able to customize every aspect of how the authentication process works. On the other hand, if we use Flask extensions, we would need to do less since these libraries or extensions already provide some sort of integrations with Flask itself. Also personally, I tend to choose my framework specific libraries for a task. They reduce the amount of task required to get things going.

In this blog post, we would be using the Flask-JWT package.

Getting Started

Before we can begin, we have to install the package using pip.

pip install Flask-JWT

We also need an API end point that we want to secure. We can refer to the initial code we wrote for our HTTP Auth tutorial.

from flask import Flask
from flask_restful import Resource, Api

app = Flask(__name__)
api = Api(app, prefix="/api/v1")


class PrivateResource(Resource):
    def get(self):
        return {"meaning_of_life": 42}


api.add_resource(PrivateResource, '/private')

if __name__ == '__main__':
    app.run(debug=True)

Now we work on securing it ūüôā

Flask JWT Conventions

Flask JWT has the following convention:

  • There needs to be two functions – one for authenticating the user, this would be quite similar to the verify¬†function we wrote in our last tutorial (http auth tutorial). The second function’s job is to identify user from a token. Let’s call this function identity.
  • The authentication function must return an object instance that has an attribute named id.
  • To secure an endpoint, we use the @jwt_required¬†decorator.
  • An API endpoint is setup at /auth¬†that accepts username¬†and password¬†via JSON payload and returns access_token¬†which is the JSON Web Token we can use.
  • We must pass the token as part of the Authorization¬†header, like – JWT <token>.

Authentication and Identity

First let’s write the function that will authenticate the user. The function will take in username and password and return an object instance that has the id¬†attribute. In general, we would use database and the id would be user id. But for this example, we would just create an object with an ID of our choice.

USER_DATA = {
    "masnun": "abc123"
}


class User(object):
    def __init__(self, id):
        self.id = id

    def __str__(self):
        return "User(id='%s')" % self.id


def verify(username, password):
    if not (username and password):
        return False
    if USER_DATA.get(username) == password:
        return User(id=123)

We are storing the user details in a dictionary like before. We have created User class with id attribute so we can fulfil the requirement of having id attribute. In our verify function, we compare the username and password and if it matches, we return an User instance with the id being 123. We will use this function to verify user logins.

Next we need the identity function that will give us user details for a logged in user.

def identity(payload):
    user_id = payload['identity']
    return {"user_id": user_id}

The identity function will receive the decoded JWT. An example would be like:

{'exp': 1494589408, 'iat': 1494589108, 'nbf': 1494589108, 'identity': 123}

Note the identity¬†key in the dictionary. It’s the value we set¬†in the id¬†attribute of the object returned from the verify¬†function. We should load the user details based on this value. But since we are not using the database, we are just constructing a simple dictionary with the user id.

Securing Endpoint

Now that we have a function to authenticate and another function to identify the user, we can start integrating Flask JWT with our REST API. First the imports:

from flask_jwt import JWT, jwt_required

Then we construct the jwt instance:

jwt = JWT(app, verify, identity)

We pass the flask app instance, the authentication function and the identity function to the JWT class.

Then in the resource, we use the @jwt_required decorator to enforce authentication.

class PrivateResource(Resource):
    @jwt_required()
    def get(self):
        return {"meaning_of_life": 42}

Please note the jwt_required¬†decorator takes a parameter (realm) which has a default value of None. Since it takes the parameter, we must use the parentheses to call the function first – @jwt_required()¬†and not just @jwt_required. If this doesn’t make sense right away, don’t worry, please do some study on how decorators work in Python and it will come to you ūüôā

Here’s the full code:

from flask import Flask
from flask_restful import Resource, Api
from flask_jwt import JWT, jwt_required

app = Flask(__name__)
app.config['SECRET_KEY'] = 'super-secret'

api = Api(app, prefix="/api/v1")

USER_DATA = {
    "masnun": "abc123"
}


class User(object):
    def __init__(self, id):
        self.id = id

    def __str__(self):
        return "User(id='%s')" % self.id


def verify(username, password):
    if not (username and password):
        return False
    if USER_DATA.get(username) == password:
        return User(id=123)


def identity(payload):
    user_id = payload['identity']
    return {"user_id": user_id}


jwt = JWT(app, verify, identity)


class PrivateResource(Resource):
    @jwt_required()
    def get(self):
        return {"meaning_of_life": 42}


api.add_resource(PrivateResource, '/private')

if __name__ == '__main__':
    app.run(debug=True)

Looks good? Let’s try it out.

Trying it out

Run the app and try to access the secured resource:

$ curl -X GET http://localhost:5000/api/v1/private
{
  "description": "Request does not contain an access token",
  "error": "Authorization Required",
  "status_code": 401
}

Makes sense. The endpoint now requires authorization token. But we don’t have one, yet!

Let’s get one – we must send a POST request to /auth¬†with a JSON payload containing username¬†and password. Please note, the api prefix is not used, that is the url for the auth end point is not /api/v1/auth. But it is just /auth.

$ curl -H "Content-Type: application/json" -X POST -d '{"username":"masnun","password":"abc123"}' http://localhost:5000/auth
{
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0OTQ1OTE4MjcsImlhdCI6MTQ5NDU5MTUyNywibmJmIjoxNDk0NTkxNTI3LCJpZGVudGl0eSI6MTIzfQ.q0p02opL0OxL7EGD7wiLbXbdfP8xQ7rXf7-3Iggqdi4"
}

Cool, we got the token. Now let’s use it to access the resource.

curl -X GET http://localhost:5000/api/v1/private -H "Authorization: JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0OTQ1OTE4MjcsImlhdCI6MTQ5NDU5MTUyNywibmJmIjoxNDk0NTkxNTI3LCJpZGVudGl0eSI6MTIzfQ.q0p02opL0OxL7EGD7wiLbXbdfP8xQ7rXf7-3Iggqdi4"
{
    "meaning_of_life": 42
}

Whoa, it worked! Amazing, now our JWT authentication is working great!

Getting the Authenticated User

Once our JWT authentication is functional, we can get the currently authenticated user by using the current_identity object.

Let’s add the import:

from flask_jwt import JWT, jwt_required, current_identity

And then let’s update our resource to return the logged in user identity.

class PrivateResource(Resource):
    @jwt_required()
    def get(self):
        return dict(current_identity)

The current_identity¬†object is a LocalProxy instance which can’t be directly JSON serialized. But if we pass it to a dict()¬†call, we can get a dictionary representation.

Now let’s try it out:

$ curl -X GET http://localhost:5000/api/v1/private -H "Authorization: JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0OTQ1OTE4MjcsImlhdCI6MTQ5NDU5MTUyNywibmJmIjoxNDk0NTkxNTI3LCJpZGVudGl0eSI6MTIzfQ.q0p02opL0OxL7EGD7wiLbXbdfP8xQ7rXf7-3Iggqdi4"
{
    "user_id": 123
}

As we can see the current_identity object returns the exact same data our identity function returns because Flask JWT uses that function to load the user identity.

What’s Next?

Go ahead and implement the same functionality using PyJWT and your own code. You will need to create an endpoint that encodes current user data and returns the access token. Then you will need to intercept the http headers, parse the Authorization header and verify the JWT token. It should be a fun and yet excellent learning exercise.