DjangoRestFramework: Unit Testing AssertionError: 404 != 200 while Test update - python

I've started writing unit tests for my API's but am stuck while updating user details received an assertion error of 404!=200. I'm sharing mycode for the reference.
Please do let me know my mistake and a brief explanation as I'm new to django rest.
I've created only one class "class TestUser(APITestCase):" for testing 2 API is it fine as I'm extending the URL in the update client patch?
models.py
mport email
from pyexpat import model
from django.db import models
from django.conf import settings
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser)
GENDER_CHOICES = (
(0, 'male'),
(1, 'female'),
(2, 'not specified'),)
class UserManager(BaseUserManager):
def create_user(self, email, name,contact_number,gender,address,state,city,country,pincode,dob ,password=None, password2=None):
"""
Creates and saves a User with the given email, name and password.
"""
if not email:
raise ValueError('User must have an email address')
user = self.model(
email=self.normalize_email(email),
name=name,
contact_number=contact_number,
gender=gender,
address=address,
state=state,
city=city,
country=country,
pincode=pincode,
dob=dob,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, name,contact_number,gender,address,state,city,country,pincode,dob , password=None):
"""
Creates and saves a superuser with the given email, name and password.
"""
user = self.create_user(
email,
name=name,
contact_number=contact_number,
gender=gender,
address=address,
state=state,
city=city,
country=country,
pincode=pincode,
dob=dob,
password=password,
)
user.is_admin = True
user.save(using=self._db)
return user
class User(AbstractBaseUser):
email = models.EmailField(verbose_name='Email',max_length=255,unique=True)
name = models.CharField(max_length=200)
contact_number= models.IntegerField()
gender = models.IntegerField(choices=GENDER_CHOICES)
address= models.CharField(max_length=100)
state=models.CharField(max_length=100)
city=models.CharField(max_length=100)
country=models.CharField(max_length=100)
pincode= models.IntegerField()
dob = models.DateField(null= True)
# is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name','contact_number','gender','address','state','city','country','pincode','dob']
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
"Does the user have a specific permission?"
# Simplest possible answer: Yes, always
return True
def has_module_perms(self, app_label):
"Does the user have permissions to view the app `app_label`?"
# Simplest possible answer: Yes, always
return True
#property
def is_staff(self):
"Is the user a member of staff?"
# Simplest possible answer: All admins are staff
return self.is_admin
views.py
class UserListCreateAPIView(generics.ListCreateAPIView):
permission_classes = [IsUserOrIsAdmin]
serializer_class = UserSerializer
def get_queryset(self):
"""
This view should return a list of all the purchases
for the currently authenticated user.
"""
if self.request.user.is_staff == False:
user_data= self.request.user.id
data = User.objects.filter(id= user_data)
return data
else:
data = User.objects.all()
return data
class UserRetrtieveUpdateDestroyAPIView(generics.RetrieveUpdateDestroyAPIView):
permission_classes = [IsUserOrIsAdmin]
serializer_class = UserSerializer
def get_queryset(self):
"""
This view should return a list of all the purchases
for the currently authenticated user.
"""
if self.request.user.is_staff == False:
user_data= self.request.user.id
data = User.objects.filter(id= user_data)
return data
else:
data = User.objects.all()
return data
urls.py
path('customer_info/', UserListCreateAPIView.as_view()),
path('customer_info/<int:pk>/', UserRetrtieveUpdateDestroyAPIView.as_view()),
tests.py
from rest_framework.test import APITestCase
from .models import User
class TestUser(APITestCase):
url = "/api/v1/customer_info/"
def setUp(self):
User.objects.create(email="naveen#example.com",name="Naveen",contact_number="9090909098",gender="0",address="jaipur",state="Rajasthan",city="Jaipur",country="India",pincode="302016",dob="1907-07-20",is_active="True",
is_admin= "False")
def test_get_User(self):
response = self.client.get(self.url)
print(response)
result = response.json()
# print(result)
self.assertEqual(response.status_code, 200)
self.assertIsInstance(result, list)
def test_post_User(self):
# definition
data = {
"email":"ujjval#example.com",
"password":"123456",
"name":"ujjval",
"contact_number":"9090909098",
"gender":"0",
"address":"jaipur",
"state":"Rajasthan",
"city":"Jaipur",
"country":"India",
"pincode":"302016",
"dob":"1907-07-20"
}
# process
response = self.client.post(self.url, data=data)
# print(response)
result = response.json()
# print(result)
# assert
self.assertEqual(response.status_code, 201)
self.assertEqual(result["email"], "ujjval#example.com")
def test_update_User(self):
pk = "1"
data = {
"email":"naveen#example.com",
}
response = self.client.patch(self.url + f"{pk}/", data=data)
result = response.json()
print(result)
self.assertEqual(response.status_code, 200)
self.assertEqual(result["email"], "ujjval#example.com")

I think you need to set the names of the URL paths and use them in the test class.
path('customer_info/', UserListCreateAPIView.as_view(), name="customer_info_view"),
path('customer_info/<int:pk>/', UserRetrtieveUpdateDestroyAPIView.as_view(), name="customer_info_detail_view"),
And in the test class,
from django.urls import reverse
class TestUser(APITestCase):
def setUp(self):
self.user = User.objects.create(email="naveen#example.com",name="Naveen",contact_number="9090909098",gender="0",address="jaipur",state="Rajasthan",city="Jaipur",country="India",pincode="302016",dob="1907-07-20",is_active="True", is_admin= "False")
def test_get_User(self):
response = self.client.get(reverse('customer_info_view'))
...
def test_post_User(self):
data = {
...
}
response = self.client.post(reverse('customer_info_view'), data=data)
...
def test_update_user(self):
pk = self.user.id
data = {
"email":"naveen#example.com",
}
response = self.client.patch(reverse('customer_info_detail_view', kwargs={
'pk': pk,
}), data, content_type='application/json')
result = response.json()
self.assertEqual(response.status_code, 200)
# self.assertEqual(result["email"], "ujjval#example.com")

Related

Django/React/Postgres One-to-Many wont update hero_id column to user_id

I am trying to store the UsersHeroes to the UserAccount database by doing a one-to-many relational database. It seems to work fine when I manually set the UserHero from the Admin site to relate to a user but when it comes to trying to submit it on the front end, it just defaults it to 1 since I set it up that way in the model. If I am logged in as user id = 2 and create a hero with that user logged in, it will only save it to user id = 1. This is how my models is set up:
class UserAccountManager(BaseUserManager):
def create_user(self, email, name, password=None): #allows you to create user
if not email:
raise ValueError("Adventurers must have an email address or you shall not pass.")
email = self.normalize_email(email) #normalize is a built in function to normalize email
user = self.model(email = email, name = name) #normalizes capital to lowercase
user.set_password(password) #hashes password for security and sets database
# if hacker hacks database you see it
user.save() #saves the user
return user
def create_superuser(self, email, name, password=None ):
u = self.create_user(email, name, password)
u.is_staff = True
u.is_active = True
u.is_superuser = True
u.save(using=self._db)
return u
class UserAccount(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length = 255, unique = True)
name = models.CharField(max_length = 255)
# id = models.IntegerField(unique=True)
# date_of_birth = models.DateField(max_length=8)
is_active = models.BooleanField(default = True)
is_staff = models.BooleanField(default = False)
objects = UserAccountManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name']
def get_fullname(self):
return self.name
def get_short_name(self):
return self.name
# def get_DOB(self):
# return self.date_of_birth
def __str__(self):
return self.email
class UsersHeroes(models.Model):
name = models.CharField(max_length = 255)
race_type = models.CharField(max_length= 255, default="")
class_type = models.CharField(max_length= 255, default="")
#do we need to replace 8 with the variable name from front end??
STR = models.IntegerField()
DEX = models.IntegerField()
CON = models.IntegerField()
INT = models.IntegerField()
WIS = models.IntegerField()
CHA = models.IntegerField()
def get_heroname(self):
return self.name
def get_race(self):
return self.race_type
def get_class(self):
return self.class_type
def get_str(self):
return self.STR
def get_dex(self):
return self.DEX
def get_con(self):
return self.CON
def get_int(self):
return self.INT
def get_wis(self):
return self.WIS
def get_cha(self):
return self.CHA
hero = models.ForeignKey(UserAccount, default = 1, on_delete=models.CASCADE)
# Create your models here.
This is my Serializer.py
from rest_framework import serializers
from djoser.serializers import UserCreateSerializer
from django.contrib.auth import get_user_model
from . models import *
User = get_user_model()
class UserCreateSerializer(UserCreateSerializer):
class Meta(UserCreateSerializer.Meta):
model = User
fields = ('id', 'email', 'first_name', 'last_name', 'password')
class UsersHeroesSerializer(serializers.ModelSerializer):
class Meta:
model = UsersHeroes
fields = ['name', 'race_type', 'class_type',
'STR', 'DEX', 'CON', 'INT', 'WIS', 'CHA']
parent = UserCreateSerializer(many=False)
this is my views.py
from django.shortcuts import render
from rest_framework.views import APIView
from . models import *
from rest_framework.response import Response
from . serializers import *
from django.views.decorators.csrf import csrf_exempt
# Create your views here.
class ReactView(APIView):
serializer_class = UsersHeroesSerializer
#csrf_exempt
def get(self, request):
detail = [ {"name": detail.name,
"race_type": detail.race_type,
"class_type": detail.class_type,
"STR" : detail.STR,
"DEX" : detail.DEX,
"CON" : detail.CON,
"INT" : detail.INT,
"WIS" : detail.WIS,
"CHA" : detail.CHA,
"hero": detail.hero
}
for detail in UsersHeroes.objects.all()]
return Response(detail)
#csrf_exempt
def post(self, request):
serializer = UsersHeroesSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
And the Post request to save the heros is in my react front end folder like so:
index.js starting at line 43 (above are just variables)
const onSubmit = (e) => {
e.preventDefault();
const postData = {
name,
race_type: selectedRace,
class_type: selectedClass,
STR: valueStr,
DEX: valueDex,
CON: valueCon,
INT: valueInt,
WIS: valueWis,
CHA: valueCha,
};
Axios.post(`${process.env.REACT_APP_API_URL}/heroes/`,
postData, )
.then((res) => {
console.log(res);
})
.catch((err) => {
console.error( err ) ;
});
}
//*************************************************/
const [raceOptions, setRaceOptions] = useState([]);
it wont update the column hero_id on my postgres unless I do it manually on the Admin site. If anyone can help that be great!
Update your UsersHeroesSerializer and the field list add hero into it.
class UsersHeroesSerializer(serializers.ModelSerializer):
class Meta:
model = UsersHeroes
fields = ['name', 'race_type', 'class_type',
'STR', 'DEX', 'CON', 'INT', 'WIS', 'CHA', 'hero']
parent = UserCreateSerializer(many=False)
and your view correct the userAccount from request.user and assign it as hero in the serializer data.

Django OperationalError: table sampleapp_userprofile has no column named email

Git Repo
I'm a beginner in the Django. I tried to implement JWT inside Python but when I add a new user I get an error, which is as follows.
django.db.utils.OperationalError: table sampleapp_userprofile has no column named email
I have created the email field and also put the default value in the email field, and I still get this error .. I have provided the git repository and given some code below, please help.
models.py
from django.db import models
from django.contrib.auth.models import User
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
# Create your models here.
class MyAccountManager(BaseUserManager):
def create_user(self, email, username, password=None):
if not email:
raise ValueError('Users must have an email address')
if not username:
raise ValueError('Users must have a username')
user = self.model(
email=self.normalize_email(email),
username=username,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, username, password):
user = self.create_user(
email=self.normalize_email(email),
password=password,
username=username,
)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class UserProfile(AbstractBaseUser):
email = models.EmailField(verbose_name="email",max_length=60, unique=True,default='')
username = models.CharField(max_length=30,default='Null')
password = models.CharField(verbose_name='password',max_length=16)
last_login = models.DateTimeField(verbose_name='last login', auto_now=True)
objects = MyAccountManager()
USERNAME_FIELD = 'username'
EmailField = 'email'
REQUIRED_FIELDS = ['username']
def __str__(self):
return self.email
views.py
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status, generics
from rest_framework_simplejwt.views import TokenObtainPairView
from .serializers import *
from rest_framework.decorators import api_view
# Create your views here.
class LoginView(TokenObtainPairView):
"""
Login View with jWt token authentication
"""
serializer_class = MyTokenObtainPairSerializer
class registrationView(APIView):
def post(self,request,format=None):
if request.method == 'POST':
serializer = RegistrationSerializer(data=request.data)
data = {}
if serializer.is_valid():
account = serializer.save()
data['response'] = 'successfully registered new user.'
else:
data = serializer.errors
return Response(data)
serializers.py
from rest_framework import serializers, status
from django.contrib.auth.models import User
from django.contrib.auth import authenticate
from .models import UserProfile
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView
class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
def validate(self, attrs):
print('in')
user = authenticate(username=attrs['username'], password=attrs['password'])
if user is not None:
if user.is_active:
data = super().validate(attrs)
refresh = self.get_token(self.user)
refresh['username'] = self.user.username
try:
obj = UserProfile.objects.get(user=self.user)
refresh['employeeRole'] = obj.employeeRole
data["refresh"] = str(refresh)
data["access"] = str(refresh.access_token)
data["employee_id"] = self.user.id
data['user_name']= self.user.username
data["employeeRole"] = obj.employeeRole
data['first_name']= self.user.first_name
data['last_name']= self.user.last_name
except Exception as e:
raise serializers.ValidationError('Something Wrong!')
return data
else:
raise serializers.ValidationError('Account is Blocked')
else:
raise serializers.ValidationError('Incorrect userid/email and password combination!')
class RegistrationSerializer(serializers.ModelSerializer):
email = serializers.EmailField(style={'input_type': 'email'})
username = serializers.CharField(min_length=1)
class Meta:
model = UserProfile
fields = ['email','username', 'password']
extra_kwargs = {
'password': {'write_only': True,'min_length':8},
}
def save(self):
account = UserProfile(
email=self.validated_data['email'],
username=self.validated_data['username'],
password=self.validated_data['password']
)
account.save()
return account

DRF ImageField Inconsistent behavior

I'm creating a Django API with DRF. I have a custom User Model like this :
models.py :
from typing import Type, List
from uuid import uuid4
from django.db import models
from django.contrib.auth.models import PermissionsMixin
from django.contrib.auth.base_user import AbstractBaseUser
from django.utils.translation import ugettext_lazy as _
from django_extensions.db.models import TimeStampedModel
from main.apps.user.managers import UserManager
def to_profile_picture(instance: "User", filename: str) -> str:
return f"profile_pictures/{instance.email}/{uuid4()}_{filename}"
class User(AbstractBaseUser, TimeStampedModel, PermissionsMixin):
email = models.EmailField(_("Email Address"), unique=True)
first_name = models.CharField(
_("First Name"), max_length=128, blank=True, null=True
)
last_name = models.CharField(_("Last Name"), max_length=128, blank=True, null=True)
display_name = models.CharField(_("Display Name"), max_length=128)
is_active = models.BooleanField(_("Active"), default=True)
is_staff = models.BooleanField(_("Is staff"), default=False)
profile_picture = models.ImageField(
upload_to=to_profile_picture, null=True, blank=True
)
objects: Type[UserManager] = UserManager()
USERNAME_FIELD: str = "email"
REQUIRED_FIELDS: List[str] = []
class Meta:
verbose_name: str = _("User")
verbose_name_plural: str = _("Users")
#property
def get_full_name(self) -> str:
return f"{self.first_name} {self.last_name}"
managers.py :
from django.contrib.auth.base_user import BaseUserManager
class UserManager(BaseUserManager):
use_in_migrations = True
def _create_user(self, email, password, **extra_fields):
"""
Creates and saves a User with the given email and password.
"""
if not email:
raise ValueError("The given email must be set")
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email: str, password: str = None, **extra_fields):
extra_fields.setdefault("is_superuser", False)
extra_fields.setdefault("is_staff", False)
return self._create_user(email, password, **extra_fields)
def create_superuser(self, email, password, **extra_fields):
extra_fields.setdefault("is_superuser", True)
extra_fields.setdefault("is_staff", True)
if extra_fields.get("is_superuser") is not True:
raise ValueError("Superuser must have is_superuser=True.")
return self._create_user(email, password, **extra_fields)
viewsets.py :
from typing import Type
from rest_framework import viewsets, status
from rest_framework.permissions import IsAuthenticated, AllowAny
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.decorators import action
from main.apps.user.models import User
from main.apps.user.serializers import UserSerializer
class UsersViewset(viewsets.ModelViewSet):
def get_permissions(self):
"""
Instantiates and returns the list of permissions that this view requires.
"""
if self.action == "create":
permission_classes = [AllowAny]
else:
permission_classes = [IsAuthenticated]
return [permission() for permission in permission_classes]
queryset = User.objects.all()
serializer_class: Type[UserSerializer] = UserSerializer
def create(self, request, *args, **kwargs):
serializer: UserSerializer = UserSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = User.objects.create_user(
serializer.validated_data.pop("email"),
serializer.validated_data.pop("password"),
**serializer.validated_data,
)
return Response(status=status.HTTP_201_CREATED, data=UserSerializer(user).data)
#action(detail=False)
def me(self, request: Request):
return Response(
status=status.HTTP_200_OK, data=UserSerializer(request.user).data
)
serializers.py :
from typing import Type, Tuple, Dict, Any
from rest_framework import serializers
from main.apps.user.models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model: Type[User] = User
fields: Tuple[str] = (
"id",
"email",
"password",
"display_name",
"first_name",
"last_name",
"profile_picture",
)
extra_kwargs: Dict[str, Any] = {"password": {"write_only": True}}
My issue here is that when I go to the route I defined for the UserViewset and trigger the list action, it returns the full URL with the http://domain/ in front of the file path, which is actually exactly what I want. But on the /me route or the create route, only the path is returned, without the domain.
I'm thinking it might have something to do with the context that is not passed to the serializer in custom routes, but might be in the default ModelViewset routes.
If anyone knows how I can replicate the list action behavior on my other routes, I'll be glad !
Okay, found out that it was what I thought, I just needed to pass the request as context to my serializer.
Change the method me in file viewsets.py from that :
#action(detail=False)
def me(self, request: Request):
return Response(
status=status.HTTP_200_OK, data=UserSerializer(request.user).data
)
to this :
#action(detail=False)
def me(self, request: Request):
return Response(
status=status.HTTP_200_OK,
data=UserSerializer(request.user, context={"request": request}).data,
)

Django - how to use reversion

I'm working at my project degree and I need to do an application like a Document Management System. I manage to do something till now but I need also to have version controll for documents(when someone wants to edit a document, first is required to dowload the document,then update it and uploaded as a new version of the existing one) .I read about Django reversion but I did not understand how to integrate it with my app outside admin.My code is available here: https://github.com/rasmim/DMSLic
Could someone help me with this?
models.py
import reversion
from django.conf import settings
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser
)
from django.core.mail import send_mail
from django.core.urlresolvers import reverse
from django.db import models
from django.db import models
from django.utils import timezone
from django.utils.http import urlquote
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext_lazy as _
class CustomUserManager(BaseUserManager):
def _create_user(self, email, password, is_staff, is_superuser, **extra_fields):
"""
Creates and saves a User with the given email and password.
"""
now = timezone.now()
if not email:
raise ValueError('The given email must be set')
email = self.normalize_email(email)
user = self.model(email=email,
is_staff=is_staff, is_active=True,
is_superuser=is_superuser, last_login=now,
date_joined=now, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email, password=None, **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 CustomUser(AbstractBaseUser, PermissionsMixin):
first_name = models.CharField(max_length=100, verbose_name=_("First name"))
last_name = models.CharField(max_length=100, verbose_name=_("Last name"))
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
date_of_birth = models.DateField(blank=True, null=True)
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
is_staff = models.BooleanField(_('staff status'), default=False,
help_text=_('Designates whether the user can log into this admin '
'site.'))
is_active = models.BooleanField(_('active'), default=True,
help_text=_('Designates whether this user should be treated as '
'active. Unselect this instead of deleting accounts.'))
objects = CustomUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
def get_full_name(self):
# The user is identified by their email address
return u"%s %s" % (self.first_name, self.last_name)
def get_short_name(self):
# The user is identified by their email address
return self.email
def __unicode__(self): # __unicode__ on Python 2
return u"%s" % self.first_name
class Meta:
verbose_name = _("user")
verbose_name_plural = _("users")
# def has_perm(self, perm, obj=None):
# "Does the user have a specific permission?"
# # Simplest possible answer: Yes, always
# return True
#
# def has_module_perms(self, app_label):
# "Does the user have permissions to view the app `app_label`?"
# # Simplest possible answer: Yes, always
# return True
# #property
# def is_staff(self):
# "Is the user a member of staff?"
# # Simplest possible answer: All admins are staff
# return self.is_admin
#reversion.register
class Document(models.Model):
name = models.CharField(max_length=70)
owner = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True, related_name="created_by")
type = models.CharField(max_length=50)
keywords = models.TextField()
description = models.TextField(default='some description')
user = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True, related_name="working_user")
creation_time = models.DateTimeField(auto_now_add=True)
status = models.CharField(max_length=50)
path = models.FileField(upload_to='media')
folder = models.ForeignKey('Folder', on_delete=models.CASCADE, null=True)
# version = models.ForeignKey('Version', on_delete=models.SET_NULL,null=True, related_name="version_id")
def get_absolute_url(self):
return reverse('DMS:detail', kwargs={'pk': self.pk})
# def files(self):
# return u'<a href="%s%s" target="_blank">' % (settings.MEDIA_URL, self.files)
# def __str__(self):
# return self.name+ '-' + self.type
class Version(models.Model):
document = models.ForeignKey(Document, on_delete=models.SET_NULL, null=True)
time = models.DateTimeField()
user = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True, related_name="active_user")
class Folder(models.Model):
name = models.CharField(max_length=100)
root = models.CharField(max_length=50)
def get_name(self):
return "{}".format(self.name)
# child = models.CharField(max_lenght = 20)
# def get_absolute_url(self):
# return reverse('DMS:folder-details', kwargs={'pk': self.pk})
def get_absolute_url(self):
return reverse('DMS:folder-details', kwargs={'pk': self.pk})
views.py
import reversion
from django.contrib.auth import authenticate, login, logout
from django.db.models import Q
from django.http import HttpResponseRedirect, HttpResponse, request
from django.shortcuts import render, get_object_or_404
from rest_framework import viewsets
from rest_framework import permissions
from .forms import FolderForm, DocumentForm
from .models import Document, Folder
from .serializers import DocumentSerializer
def user_login(request):
# If the request is a HTTP POST, try to pull out the relevant information.
if request.method == 'POST':
# Gather the username and password provided by the user.
# This information is obtained from the login form.
# We use request.POST.get('<variable>') as opposed to request.POST['<variable>'],
# because the request.POST.get('<variable>') returns None, if the value does not exist,
# while the request.POST['<variable>'] will raise key error exception
email = request.POST.get('email')
password = request.POST.get('password')
# Use Django's machinery to attempt to see if the username/password
# combination is valid - a CustomUser object is returned if it is.
user = authenticate(email=email, password=password)
# If we have a CustomUser object, the details are correct.
# If None (Python's way of representing the absence of a value), no user
# with matching credentials was found.
if user:
# Is the account active? It could have been disabled.
if user.is_active:
# If the account is valid and active, we can log the user in.
# We'll send the user back to the homepage.
login(request, user)
return HttpResponseRedirect('/DMS/first/')
else:
# An inactive account was used - no logging in!
return HttpResponse("Your DMS account is disabled.")
else:
# Bad login details were provided. So we can't log the user in.
print("Invalid login details: {0}, {1}".format(email, password))
return HttpResponse("Invalid login details supplied.")
# The request is not a HTTP POST, so display the login form.
# This scenario would most likely be a HTTP GET.
else:
# No context variables to pass to the template system, hence the
# blank dictionary object...
return render(request, 'DMS/login.html', {})
def user_logout(request):
# Since we know the user is logged in, we can now just log them out.
logout(request)
# Take the user back to the homepage.
return HttpResponseRedirect('/DMS/login/')
def index(request):
folder_name = Folder.objects.all()
context = {
'folder_name': folder_name,
}
return render(request, 'DMS/index.html', context)
#
# def remove(request, post_id):
# try:
# folder_id = Folder.objects.get(pk=question_id)
# folder_id.remove()
# except Folder.DoesNotExist:
# raise Http404("Error 404")
# return render(request, 'index.html', {'message': 'Folder was removed'})
def FolderDetail(request, pk):
folder = get_object_or_404(Folder, pk=pk)
folder_name = Folder.objects.all()
# document_list = Document.objects.all()
# query = request.GET.get("q")
# if query:
# document_list = document_list.filter(Q(keywords__icontains=query)).distinct()
# return render(request, 'DMS/folder-details.html', {'document_list': document_list})
context = {
'folder': folder,
'folder_name': folder_name,
# 'document_list': document_list
}
return render(request, "DMS/folder-details.html", context)
# class FolderDetailsView(generic.DetailView):
# model = Folder
# template_name = 'DMS/folder-details.html'
def DocumentView(request):
document_list = Document.objects.all()
query = request.GET.get("q")
if query:
document_list = document_list.filter(Q(keywords__icontains=query)).distinct()
return render(request, 'DMS/documents.html', {'document_list': document_list})
return render(request, 'DMS/documents.html', {'document_list': document_list})
def create_document(request, folder_id):
# form = forms.DocumentForm()
form = DocumentForm(request.POST or None, request.FILES or None)
folder = get_object_or_404(Folder, pk=folder_id)
# foldern = get_object_or_404(Folder,)
folder_name = Folder.objects.all()
if form.is_valid():
folder_document = folder.document_set.all()
for d in folder_document:
if d.name == form.cleaned_data.get("name"):
context = {
'folder': folder,
'form': form,
'folder_name': folder_name,
'error_message': 'You already added that document',
}
# return HttpResponseRedirect('/DMS/folder-details')
return render(request, 'DMS/folder-details.html', context)
document = form.save(commit=False)
document.folder = folder
document.save()
return HttpResponseRedirect('/DMS/' + folder.id)
context = {
'folder': folder,
'form': form,
'folder_name': folder_name
}
return render(request, 'DMS/create_document.html', context)
def create_folder(request):
form = FolderForm(request.POST or None, request.FILES or None)
folder_name = Folder.objects.all()
if form.is_valid():
folder = form.save(commit=False)
folder.save()
return HttpResponseRedirect('/DMS/first')
context = {
"form": form,
"folder_name": folder_name
}
return render(request, 'DMS/create_folder.html', context)
def delete_document(request, folder_id, document_id):
folder = get_object_or_404(Folder, pk=folder_id)
folder_name = Folder.objects.all()
document = Document.objects.get(pk=document_id)
document.delete()
context = {
"folder": folder,
"folder_name": folder_name
}
return render(request, 'DMS/folder-details.html', context)
def delete_folder(request, pk):
folder = Folder.objects.get(pk=pk)
folder_name = Folder.objects.all()
for f in folder_name:
if f.id == folder.id:
if f.root == 'root':
for child in folder_name:
if child.root == folder.name:
child.delete()
folder.delete()
# folder.delete(name= folder)
# if f.root == folder.name:
# folder.delete(root = folder)
else:
folder.delete()
else:
folder.delete()
# for child in folder_name:
# if child.root == f.name:
# child.delete()
# # folder.delete()
return render(request, 'DMS/folder-details.html', {'folder': folder, 'folder_name': folder_name})
class DocumentViewSet(viewsets.ModelViewSet):
queryset = Document.objects.all()
serializer_class = DocumentSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly)
with reversion.create_revision():
obj = Document()
obj.name = "obj v1"
obj.save()
reversion.set_user(request.user)
reversion.set_comment("Created revision 1")
urls.py
from django.conf.urls import url
from rest_framework.urlpatterns import format_suffix_patterns
from . import views
from django.conf.urls import include
app_name = 'DMS'
urlpatterns = [
url(r'^first/$', views.index, name='index'),
# url(r'^document/add/$', views.DocumentCreate.as_view(), name='document-add'),
# url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='detail'),
url(r'^(?P<pk>[0-9]+)/$', views.FolderDetail, name='folder-details'),
# url(r'^folder/add/$', views.FolderCreate.as_view(), name='folder-add'),
url(r'^(?P<folder_id>[0-9]+)/create_document/$', views.create_document, name='create_document'),
url(r'^create_folder/$', views.create_folder, name='create-folder'),
url(r'^login/$', views.user_login, name='user_login'),
url(r'^logout/$', views.user_logout, name='user_logout'),
url(r'^doc/$', views.DocumentView, name='document'),
url(r'^(?P<folder_id>[0-9]+)/delete_document/(?P<document_id>[0-9]+)/$', views.delete_document,
name='delete_document'),
url(r'^(?P<pk>[0-9]+)/delete_folder/$', views.delete_folder, name='delete_folder'),
]
urlpatterns = format_suffix_patterns(urlpatterns)
forms.py
from django import forms
from .models import Folder, Document, CustomUser
class DocumentForm(forms.ModelForm):
EXTENSIONS = (('jpg', 'jpg'),
('pdf', 'pdf'),
('png', 'png'),
('docx', 'docx'),
('pptx', 'pptx'),
('xls', 'xls'),
)
type = forms.ChoiceField(choices=EXTENSIONS)
class Meta:
model = Document
fields = ['name', 'owner', 'type', 'keywords', 'description', 'path']
class FolderForm(forms.ModelForm):
CHOICES = [[x.name, x.name] for x in Folder.objects.all()]
CHOICES.insert(0, ['root', "Root Folder"])
root = forms.ChoiceField(choices=CHOICES)
class Meta:
model = Folder
fields = ['name', 'root']
class UserForm(forms.ModelForm):
class Meta:
model = CustomUser
fields = ['email', 'password']
Outside of admin, django-reversion gives you two options:
Wrapping middleware for any POST/PUT/PATCH request:
MIDDLEWARE += ('reversion.middleware.RevisionMiddleware')
A view decorator/mixin:
from reversion.views import RevisionMixin
class DocumentViewSet(RevisionMixin, viewsets.ModelViewSet):
queryset = Document.objects.all()
serializer_class = DocumentSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly)
Both option would require you to register the models either via a decorated ModelAdmin class or manually:
#reversion.register
class Document(models.Model):
# ... rest of definition
pass

get() returned more than one AccessToken

I am facing 2 issues here.
1) If user has not old token, a new one should be generated and logged in but it is not happening so.
2)A newly created user when logs in gets 'You have multiple authentication backends configured and therefore must provide the backend argument or set the backend attribute on the user.'
3)old user when trying to login gets an error of get() returned more than one AccessToken -- it returned 8!
Expert might understand from my code
class UserLoginAPI(APIView):
permission_classes = [AllowAny]
serializer_class = UserLoginSerializer
def post(self, request, *args, **kwargs):
access_token = request.GET.get('access_token')
data = request.data
print('data',data)
serializer = UserLoginSerializer(data=data)
if serializer.is_valid(raise_exception=True):
new_data = serializer.data
if new_data:
app = Application.objects.get(name="Foodie")
try:
user = User.objects.get(username=data['username'])
print ('user',user)
except ObjectDoesNotExist:
return HttpResponse("Can't find this user")
else:
try:
access_token = AccessToken.objects.get(user=user)
except ObjectDoesNotExist:
return HttpResponse('Have not set any token')
else:
access_token.delete()
new_token = generate_token()
print('new_token',new_token)
AccessToken.objects.create(user=user, application=app, expires=datetime.now() + timedelta(days=365),token=new_token)
print('aceess',AccessToken)
login(request, user)
return Response(new_data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
serializers.py
class UserLoginSerializer(ModelSerializer):
username = CharField()
class Meta:
model = User
fields = ['username', 'password']
class UserCreateSerializer(ModelSerializer):
class Meta:
model = User
extra_kwargs = {"password": {"write_only": True}}
def create(self, validated_data):
user_obj = User(
username = username,
first_name = first_name,
last_name = last_name,
email = email
)
user_obj.set_password(password)
user_obj.save()
if user_obj:
expire_seconds = oauth2_settings.user_settings['ACCESS_TOKEN_EXPIRE_SECONDS']
scopes = oauth2_settings.user_settings['SCOPES']
application = Application.objects.get(name="Foodie")
expires = datetime.now() + timedelta(seconds=expire_seconds)
access_token = AccessToken.objects.create(user=user_obj,
application=application,
token = generate_token(),
expires=expires,
scope=scopes)
return validated_data

Categories

Resources