Skip to content

Instantly share code, notes, and snippets.

@herotux
Forked from padurets/admin.py
Created May 11, 2018 11:32
Show Gist options
  • Save herotux/911a0d4744845d9f7e3d35e2a69b720d to your computer and use it in GitHub Desktop.
Save herotux/911a0d4744845d9f7e3d35e2a69b720d to your computer and use it in GitHub Desktop.
django rest api framework session auth example
from django.contrib import admin
from .models import User
admin.site.register([User])
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import BaseUserManager, AbstractBaseUser, PermissionsMixin
class UserManager(BaseUserManager):
def _create_user(self, email, password, is_staff, is_superuser, **extra_fields):
if not email:
raise ValueError('Users must have an email address')
now = timezone.now()
user = self.model(
email=self.normalize_email(email),
is_staff=is_staff,
is_active=True,
is_superuser=is_superuser,
last_login=now,
joined_at=now,
**extra_fields
)
user.set_password(password)
user.save(using=self._db)
return user
def get_by_natural_key(self, username):
return self.get(**{'{}__iexact'.format(self.model.USERNAME_FIELD): username})
def create_user(self, email, password, **extra_fields):
return self._create_user(email, password, False, False, **extra_fields)
def create_superuser(self, email, password, **extra_fields):
return self._create_user(email, password, True, True, **extra_fields)
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField('Email', max_length=255, unique=True)
name = models.CharField('Name', max_length=255, blank=True)
is_staff = models.BooleanField('Is staff', default=False)
is_active = models.BooleanField('Is active', default=True)
joined_at = models.DateTimeField('Joined at', default=timezone.now)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
# def __str__(self):
# return str(self.pk)
class Meta:
verbose_name = 'User'
verbose_name_plural = 'Users'
def get_full_name(self):
return self.name
def get_short_name(self):
return self.name
from django.contrib.auth import authenticate
from rest_framework import serializers
from .models import User
from .validators import validate_username
class LoginSerializer(serializers.Serializer):
email = serializers.EmailField()
password = serializers.CharField()
def validate(self, attrs):
user = authenticate(username=attrs['email'], password=attrs['password'])
if not user:
raise serializers.ValidationError('Incorrect email or password.')
if not user.is_active:
raise serializers.ValidationError('User is disabled.')
return {'user': user}
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = (
'id',
'last_login',
'email',
'name',
'is_active',
'joined_at',
'password'
)
read_only_fields = ('last_login', 'is_active', 'joined_at')
extra_kwargs = {
'password': {'required': True, 'write_only': True},
'name': {'required': True}
}
@staticmethod
def validate_email(value):
return validate_username(value)
def create(self, validated_data):
return User.objects.create_user(
validated_data.pop('email'),
validated_data.pop('password'),
**validated_data
)
from django.conf.urls import url
from rest_framework import routers
from . import views
urlpatterns = [
url(r'^register/$', views.RegisterView.as_view(), name='user-register'),
url(r'^login/$', views.LoginView.as_view(), name='user-login'),
url(r'^logout/$', views.LogoutView.as_view(), name='user-logout'),
url(r'^current/$', views.UserView.as_view(), name='user-current'),
]
from django.core.exceptions import ValidationError
from .models import User
def validate_username(username):
if User.objects.filter(**{'{}__iexact'.format(User.USERNAME_FIELD): username}).exists():
raise ValidationError('User with this {} already exists'.format(User.USERNAME_FIELD))
return username
from django.conf import settings
from django.contrib.auth import login, logout
from rest_framework import views, generics, response, permissions, authentication
from .serializers import UserSerializer, LoginSerializer
class CsrfExemptSessionAuthentication(authentication.SessionAuthentication):
def enforce_csrf(self, request):
return
class LoginView(views.APIView):
permission_classes = (permissions.AllowAny,)
authentication_classes = (CsrfExemptSessionAuthentication,)
def post(self, request):
serializer = LoginSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.validated_data['user']
login(request, user)
return response.Response(UserSerializer(user).data)
class LogoutView(views.APIView):
def post(self, request):
logout(request)
return response.Response()
class RegisterView(generics.CreateAPIView):
serializer_class = UserSerializer
permission_classes = (permissions.AllowAny,)
def perform_create(self, serializer):
user = serializer.save()
user.backend = settings.AUTHENTICATION_BACKENDS[0]
login(self.request, user)
class UserView(generics.RetrieveAPIView):
serializer_class = UserSerializer
lookup_field = 'pk'
def get_object(self, *args, **kwargs):
return self.request.user
@PritpalSingh786
Copy link

Your LoginView is not working for me.

@dopeboy
Copy link

dopeboy commented Dec 27, 2021

This was helpful, thank you. I needed this line in my LogoutView to get it working:

authentication_classes = (CsrfExemptSessionAuthentication,)

I also found this example helpful to complement this gist.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment