Last active
June 10, 2023 21:05
-
-
Save padurets/7f376cd7e40d76a0d1550c2d79c4b2b0 to your computer and use it in GitHub Desktop.
django rest api framework session auth example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from django.contrib import admin | |
from .models import User | |
admin.site.register([User]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'), | |
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment