Skip to content

Instantly share code, notes, and snippets.

@AmirTugi
Created December 4, 2015 14:35
Show Gist options
  • Save AmirTugi/52ac9f4cce3f21fae569 to your computer and use it in GitHub Desktop.
Save AmirTugi/52ac9f4cce3f21fae569 to your computer and use it in GitHub Desktop.
Default values not showing the the browsable api
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.db import models
class AccountManager(BaseUserManager):
def create_user(self, username, password=None, **kwargs):
if not username:
raise ValueError('Users must have a valid username.')
if not kwargs.get('email'):
raise ValueError('Users must have a valid email address.')
# Create a dictionary for all values but email and confirm_password (username & password are already extracted)
attr_dict = {}
for attr, value in kwargs.items():
if attr in ['email', 'confirm_password']:
continue
attr_dict[attr] = value
# Create the new Account instance.
account = self.model(
email=self.normalize_email(kwargs.get('email')),
username=username,
**attr_dict
)
account.set_password(password)
account.save()
return account
def create_superuser(self, username, password, **kwargs):
account = self.create_user(username, password, **kwargs)
account.is_staff = True
account.save()
return account
class Account(AbstractBaseUser):
GENDER_CHOICES = (('Male', 'Male'),
('Female', 'Female'))
DEFAULT_AVATAR = 'avatar1'
email = models.EmailField()
username = models.CharField(max_length=40, unique=True)
first_name = models.CharField(max_length=40, blank=True)
last_name = models.CharField(max_length=40, blank=True)
# Default gender is Male
gender = models.CharField(max_length=40, choices=GENDER_CHOICES, default=GENDER_CHOICES[0][0])
avatar = models.CharField(max_length=100, default=DEFAULT_AVATAR)
# Administrator
is_staff = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = AccountManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
def get_full_name(self):
return " ".join([self.first_name, self.last_name])
def get_short_name(self):
return self.first_name
def __unicode__(self):
return self.username
from rest_framework import permissions
__author__ = 'Amir'
class IsAccountOwner(permissions.BasePermission):
def has_object_permission(self, request, view, account):
return request.user and account == request.user
from rest_framework.serializers import raise_errors_on_nested_writes
from django.contrib.auth import update_session_auth_hash
from rest_framework import serializers
from authentication.models import Account
__author__ = 'Amir'
class AccountSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True, required=False)
confirm_password = serializers.CharField(write_only=True, required=False, default='asd')
# TODO: Give related information
# items = serializers.StringRelatedField(many=True)
class Meta:
model = Account
fields = ('id', 'email', 'username', 'created_at', 'updated_at',
'first_name', 'last_name', 'gender', 'avatar', 'is_staff', 'password',
'confirm_password')
read_only_fields = ('created_at', 'updated_at',)
def create(self, validated_data):
return Account.objects.create_user(**validated_data)
def update(self, instance, validated_data):
# First, update passwords
password = validated_data.get('password', None)
confirm_password = validated_data.get('confirm_password', None)
if password and confirm_password and password == confirm_password:
instance.set_password(password)
instance.save()
update_session_auth_hash(self.context.get('request'), instance)
# This is from the original update, with a small monkey patch - Skip updating password
raise_errors_on_nested_writes('update', self, validated_data)
# Update all attributes but passwords.
for attr, value in validated_data.items():
if attr in ['password', 'confirm_password']:
continue
setattr(instance, attr, value)
instance.save()
return instance
import json
from traceback import format_exc
from django.contrib.auth import authenticate, login, logout
from rest_framework.response import Response
from authentication.models import Account
from authentication.permissions import IsAccountOwner
from authentication.serializers import AccountSerializer
from rest_framework import viewsets, permissions, views, status
class AccountViewSet(viewsets.ModelViewSet):
queryset = Account.objects.all()
serializer_class = AccountSerializer
def get_permissions(self):
# TODO: See how to to make OR operator with permission classes
# If read-only request
if self.request.method in permissions.SAFE_METHODS:
return permissions.AllowAny(),
# If POST request (To create a new account)
if self.request.method == "POST":
return permissions.AllowAny(),
# If admin
if self.request.user.is_staff:
return permissions.AllowAny(),
return IsAccountOwner(),
def create(self, request, *args, **kwargs):
serializer = self.serializer_class(data=request.data)
if serializer.is_valid():
Account.objects.create_user(**serializer.validated_data)
return Response(serializer.validated_data, status=status.HTTP_201_CREATED)
if 'username' in serializer.errors:
bad_request_message = 'That username already exists.'
else:
bad_request_message = 'Account could not be created with received data.'
return Response({
'status': 'Bad request',
'message': bad_request_message
}, status=status.HTTP_400_BAD_REQUEST)
class LoginView(views.APIView):
def post(self, request):
try:
data = json.loads(request.body)
username = data.get('username', None)
password = data.get('password', None)
account = authenticate(username=username, password=password)
# If no account was found
if account is None:
return Response({
'status': 'Unauthorized',
'message': 'Username/ password combination invalid.'
}, status=status.HTTP_401_UNAUTHORIZED)
# Or if the account is inactive
if not account.is_active:
return Response({
'status': 'Unauthorized',
'message': 'This account has been disabled.'
}, status=status.HTTP_401_UNAUTHORIZED)
# Else, login and return the account
login(request, account)
serialized = AccountSerializer(account)
return Response(serialized.data, status=status.HTTP_200_OK)
except Exception:
print format_exc()
class LogoutView(views.APIView):
# permission_classes = (permissions.IsAuthenticated, )
def post(self, request, format=None):
logout(request)
return Response({
'message': 'Logged-out successfully.'
}, status=status.HTTP_200_OK)
"""Arihav URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/1.9/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
Including another URLconf
1. Add an import: from blog import urls as blog_urls
2. Import the include() function: from django.conf.urls import url, include
3. Add a URL to urlpatterns: url(r'^blog/', include(blog_urls))
"""
from django.conf.urls import url, include
from authentication.views import AccountViewSet, LoginView, LogoutView
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'users', AccountViewSet)
urlpatterns = [
url(r'^', include(router.urls)),
url(r'^login', LoginView.as_view(), name='login'),
url(r'^logout', LogoutView.as_view(), name='logout'),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment