74๐
No, not in your models.py โ on the models side of things, all you need to do is include the appropriate app (rest_framework.authtoken
) in your INSTALLED_APPS
. That will provide a Token model which is foreign-keyed to User.
What you need to do is decide when and how those token objects should be created. In your app, does every user automatically get a token? Or only certain authorized users? Or only when they specifically request one?
If every user should always have a token, there is a snippet of code on the page you linked to that shows you how to set up a signal to create them automatically:
@receiver(post_save, sender=User)
def create_auth_token(sender, instance=None, created=False, **kwargs):
if created:
Token.objects.create(user=instance)
(put this in a models.py file, anywhere, and it will be registered when a Django thread starts up)
If tokens should only be created at certain times, then in your view code, you need to create and save the token at the appropriate time:
# View Pseudocode
from rest_framework.authtoken.models import Token
def token_request(request):
if user_requested_token() and token_request_is_warranted():
new_token = Token.objects.create(user=request.user)
Once the token is created (and saved), it will be usable for authentication.
94๐
@ian-clelland has already provided the correct answer. There are just a few tiny pieces that wasnโt mentioned in his post, so I am going to document the full procedures (I am using Django 1.8.5 and DRF 3.2.4):
-
Do the following things BEFORE you create the superuser. Otherwise, the superuser does not get his/her token created.
-
Go to settings.py and add the following:
INSTALLED_APPS = ( 'rest_framework', 'rest_framework.authtoken', 'myapp', ) REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAuthenticated', ), 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.TokenAuthentication', ) }
-
Add the following code in myappโs models.py:
from django.db.models.signals import post_save from django.dispatch import receiver from rest_framework.authtoken.models import Token from django.conf import settings # This code is triggered whenever a new user has been created and saved to the database @receiver(post_save, sender=settings.AUTH_USER_MODEL) def create_auth_token(sender, instance=None, created=False, **kwargs): if created: Token.objects.create(user=instance)
Alternatively, if you want to be more explicit, create a file named signals.py under myapp project. Put the code above in it, then in __init__.py, write
import signals
-
Open up a console window, navigate to your project dir, and enter the following command:
python manage.py migrate python manage.py makemigrations
Take a look in your database, a table named authtoken_token should be created with the following fields: key (this is the token value), created (the datetime it was created), user_id (a foreign key that references the auth_user tableโs id column)
-
create a superuser with
python manage.py createsuperuser
. Now, take a look at the authtoken_token table in your DB withselect * from authtoken_token;
, you should see a new entry has been added. -
Using
curl
or a much simpler alternative httpie to test access to your api, I am using httpie:http GET 127.0.0.1:8000/whatever 'Authorization: Token your_token_value'
Thatโs it. From now on, for any API access, you need to include the following value in the HTTP header (pay attention to the whitespaces):
Authorization: Token your_token_value
-
(Optional) DRF also provides the ability to return a userโs token if you supply the username and password. All you have to do is to include the following in urls.py:
from rest_framework.authtoken import views urlpatterns = [ ... url(r'^api-token-auth/', views.obtain_auth_token), ]
Using httpie to verify:
http POST 127.0.0.1:8000/api-token-auth/ username='admin' password='whatever'
In the return body, you should see this:
{ "token": "blah_blah_blah" }
Thatโs it!
- [Django]-How to deal with "SubfieldBase has been deprecated. Use Field.from_db_value instead."
- [Django]-Django CMS fails to synch db or migrate
- [Django]-Creating a JSON response using Django and Python
20๐
On Django 1.8.2 and rest framework 3.3.2 following all of the above was not enough to enable token based authentication.
Although REST_FRAMEWORK setting is specified in django settings file, function based views required @api_view decorator:
from rest_framework.decorators import api_view
@api_view(['POST','GET'])
def my_view(request):
if request.user.is_authenticated():
...
Otherwise no token authentication is performed at all
- [Django]-Unittest Django: Mock external API, what is proper way?
- [Django]-Convert seconds to hh:mm:ss in Python
- [Django]-Fastest way to get the first object from a queryset in django?
16๐
Just to add my two cents to this, if youโve got a custom user manager that handles user creation (and activation), you may also perform this task like so:
from rest_framework.authtoken.models import Token
# Other imports
class UserManager(BaseUserManager):
def create_user(self, **kwargs):
"""
This is your custom method for creating user instances.
IMHO, if you're going to do this, you might as well use a signal.
"""
# user = self.model(**kwargs) ...
Token.objects.create(user=user)
#You may also choose to handle this upon user activation.
#Again, a signal works as well here.
def activate_user(**kwargs):
# user = ...
Token.objects.create(user=user)
If you already have users created, then you may drop down into the python shell in your terminal and create Tokens for all the users in your db.
>>> from django.contrib.auth.models import User
>>> from rest_framework.authtoken.models import Token
>>> for user in User.objects.all():
>>> ... Token.objects.create(user=user)
Hope that helps.
- [Django]-How to add multiple objects to ManyToMany relationship at once in Django ?
- [Django]-Django, Turbo Gears, Web2Py, which is better for what?
- [Django]-Django's ManyToMany Relationship with Additional Fields
10๐
There is a cleaner way to get the user token.
simply run manage.py shell
and then
from rest_framework.authtoken.models import Token
from django.contrib.auth.models import User
u = User.objects.get(username='admin')
token = Token.objects.create(user=u)
print token.key
then a record should be found in table DB_Schema.authtoken_token
- [Django]-How to test "render to template" functions in django? (TDD)
- [Django]-How to add custom search box in Django-admin?
- [Django]-Django admin: How to display the field marked as "editable=False" in the model?
7๐
In addition to the excellent answers here, Iโd like to mention a better approach to token authentication: JSON Web Token Authentication. The implementation offered by http://getblimp.github.io/django-rest-framework-jwt/ is very easy to use.
The benefits are explained in more detail in this answer.
- [Django]-Speeding up Django Testing
- [Django]-How can I enable CORS on Django REST Framework
- [Django]-How to pass information using an HTTP redirect (in Django)
1๐
JSON Web Token Authentication is a better alternative than Token Authentication. This project has implemented JWT Auth with Django (http://getblimp.github.io/django-rest-framework-jwt/) but currently the project is unmaintained.
For alternatives you can follow : https://github.com/davesque/django-rest-framework-simplejwt
- [Django]-Set Django's FileField to an existing file
- [Django]-Django: Model Form "object has no attribute 'cleaned_data'"
- [Django]-Get the latest record with filter in Django