Error while providing arguments in django project while testing - python

I am new to django need a bit of help in testing a particular section of the user model.
Heres the error showing while running the test
These are my codes
models.py
from django.utils.translation import ugettext_lazy as _
from django.db import models
from django.utils.crypto import get_random_string
from django.db import models
from django.contrib.auth.models import(
BaseUserManager,
AbstractBaseUser,
PermissionsMixin,
)
def generate_vid():
"""Generates a vid for the users"""
not_unique = True
while not_unique:
vid = get_random_string(10, 'abcdefg0123456789')
if not User.objects.filter(v_id = vid).exists():
not_unique=False
return vid
class UserManager(BaseUserManager):
"""Model for user manager"""
def create_user(self, username, password=None, **params):
"""Create and return a user"""
user = self.model(username=username, **params)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, username, password, **params):
"""Create and return a user"""
params.setdefault('is_staff',True)
params.setdefault('is_superuser',True)
params.setdefault('is_active',True)
if params.get('is_staff') is not True:
raise ValueError(_('Superuser must have is_staff=True.'))
if params.get('is_superuser') is not True:
raise ValueError(_('Superuser must have is_superuser=True.'))
return self.create_user(username, password, **params)
class User(AbstractBaseUser, PermissionsMixin):
"""Models for user"""
v_id = models.CharField(
max_length=10,
default=generate_vid,
primary_key = True,
)
username = models.CharField(max_length=20, unique=True)
email = models.EmailField(blank=True, unique = True)
# parent_id = models.ForeignKey('User', on_delete=models.SET_DEFAULT, default=0)
usertype = models.CharField(max_length=1, choices=[('f', 'family'), ('v', 'veteran')])
REQUIRED_FIELDS = []
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
USERNAME_FIELD = 'username'
objects = UserManager()
def __str__(self):
return self.username
views.py
from base.models import (
User,)
from .serializers import (
UserSerializer,)
from rest_framework import viewsets
class UserViewset(viewsets.ModelViewSet):
"""Views for user model"""
serializer_class = UserSerializer
queryset = User.objects.all()
Serializer
from django.contrib.auth import get_user_model
from base.models import (
User,
)
from rest_framework import serializers
class UserSerializer(serializers.Serializer):
"""Serializer for our models"""
class Meta:
model = get_user_model()
fields = ['username', 'password']
extra_kwargs = {'password': {'write_only': True, 'min_length': 5}}
def create(self, validated_data):
return get_user_model().objects.create_user(**validated_data)
urls.py
"""
URL mappings for the user API
"""
from rest_framework import routers
from django.urls import path, include
from . import views
router = routers.DefaultRouter()
router.register(r'user', views.UserViewset)
app_name='user'
urlpatterns = [
path('', include(router.urls)),
]
The test which I created to check the model manager(i.e. creating a user using User.objects.create() works fine ...
But when i tried creating an api and test the user api , using APIClient the post wasn't working..
test code
from django.urls import reverse
from django.test import TestCase
from rest_framework.test import APIClient
from rest_framework import status
CREATE_USER_URL = reverse('user:user-list')
class PublicUserTests(TestCase):
"""Tests for user API"""
def setUp(self):
self.client = APIClient()
def test_create_user_success(self):
"""Test creating a user is succesful"""
payload = {
'username': 'testusername',
'password': 'testpas123',
}
res = self.client.post(CREATE_USER_URL, payload)
# self.assertEqual(res, status.HTTP_201_CREATED)
self.assertEqual(res.status_code, status.HTTP_201_CREATED)
Kindly help.

Your serializer should be a ModelSerializer instead of a basic serializer.
Only the ModelSerializer will add fields based on the Meta attributes based on the model.
https://www.django-rest-framework.org/api-guide/serializers/

Related

TypeError: User() got an unexpected keyword argument 'is_staff'

I'm newbie with django. I want to create an login, signup API so I find a solution on Internet. But it's not user my own User model, it use django.contrib.auth.models import AbstractUser. I don't need some field of AbtractUser so I give it =none.
Here is my models code:
from django.db import models
from django.contrib.postgres.fields import ArrayField
from django.contrib.postgres.fields import JSONField
from django.contrib.auth.models import AbstractUser
# Create your models here.
# class User(models.Model):
# name = models.CharField(null=False,blank=False, max_length=512)
# username = models.CharField(null=False,blank=False, max_length=512, unique=True)
# email = models.EmailField(null=False,blank=False, max_length=512, unique=True)
# password = models.CharField(null=False,blank=False, max_length=512)
# status = models.CharField(null=True,blank=True, max_length=512)
# role = models.IntegerField(null=False, blank=False, default=1)
# USERNAME_FIELD = 'username'
# REQUIRED_FIELDS = []
# def __str__(self):
# return self.username
class User(AbstractUser):
last_login = None
is_staff = None
is_superuser = None
first_name = None
last_name = None
name = models.CharField(null=False,blank=False, max_length=512)
username = models.CharField(null=False,blank=False, max_length=512, unique=True)
email = models.EmailField(null=False,blank=False, max_length=512, unique=True)
status = models.CharField(null=True,blank=True, max_length=512)
role = models.IntegerField(null=False, blank=False, default=1)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = []
def __str__(self):
return self.username
class Category(models.Model):
title = models.TextField(null=False, blank=False)
description = models.TextField(null=False, blank=False)
class Question(models.Model):
title = models.TextField(null=False, blank=False)
description = models.TextField(null=False, blank=True)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
choices = models.JSONField(null=False, blank=False)
answer = models.TextField(null=False,blank=False)
level = models.IntegerField(null=True, blank=True)
But I can't login to my Django Admin with my Superuser. I create new superuser but I got an error TypeError: User() got an unexpected keyword argument 'is_staff'
My command to create superuser: python manage.py createsuperuser
I don't understand why my model can affect to my app superuser. Anyone can explain for me and give me some solution.
Here is my code in serializer:
from django.contrib.postgres import fields
from rest_framework import serializers
from app.models import User, Question, Category
class RegistrationSerializer(serializers.ModelSerializer):
email = serializers.EmailField(max_length=50, min_length=6)
username = serializers.CharField(max_length=50, min_length=6)
password = serializers.CharField(max_length=150, write_only=True)
class Meta:
model = User
fields = ['id', 'name','email', 'username', 'password', 'role']
def validate(self, args):
email = args.get('email', None)
username = args.get('username', None)
if User.objects.filter(email=email).exists():
raise serializers.ValidationError({'email': ('Email already exists')})
if User.objects.filter(username=username).exists():
raise serializers.ValidationError({'username': ('Username already exists')})
return super().validate(args)
# def create(self, validated_data):
# return User.objects.create_user(**validated_data)
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ['id', 'name', 'username', 'email', 'role']
class CategorySerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Category
fields = ['id', 'title', 'description']
class QuestionSerializer(serializers.ModelSerializer):
# category = CategorySerializer(read_only=False)
class Meta:
model = Question
fields = ['id', 'description', 'category', 'choices', 'answer', 'level']
Here is my code in views:
from django.db.models import query
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework import generics
from rest_framework import viewsets
from rest_framework import serializers
from rest_framework import permissions
import uuid
from app.models import User, Category, Question
from app.serializers import UserSerializer, QuestionSerializer, CategorySerializer, RegistrationSerializer
from django.shortcuts import get_object_or_404
# Create your views here.
class RegistrationAPIView(generics.GenericAPIView):
serializer_class = RegistrationSerializer
permission_classes = (permissions.IsAuthenticated,)
def post(self, request):
serializer = self.get_serializer(data = request.data)
if(serializer.is_valid()):
serializer.save()
return Response({
"RequestId": str(uuid.uuid4()),
"Message": "User created successfully",
"User": serializer.data}, status=status.HTTP_201_CREATED
)
return Response({"Errors": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
class ListUsersAPIView(APIView):
permission_classes = (permissions.IsAuthenticated,)
def get(self, request):
listUser = User.objects.all()
info = UserSerializer(listUser, many = True)
return Response(data = info.data, status = status.HTTP_200_OK)
# def post(self, request, format=None):
# serializer = UserSerializer(data=request.data)
# if serializer.is_valid():
# serializer.save()
# return Response(serializer.data, status=status.HTTP_201_CREATED)
# return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class DetailUsersAPIView(APIView):
permission_classes = (permissions.IsAuthenticated,)
def get(self,request, id):
try:
user = get_object_or_404(User, pk=id)
data = UserSerializer(user).data
return Response(data, status = status.HTTP_200_OK)
except:
return Response("Error",status = status.HTTP_404_NOT_FOUND)
def patch(self, request, id):
user = get_object_or_404(Users, pk=id)
serializer = UserSerializer(user, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class CategoryViewSet(viewsets.ModelViewSet):
permission_classes = (permissions.IsAuthenticated,)
serializer_class = CategorySerializer
queryset = Category.objects.all()
class QuestionViewSet(viewsets.ModelViewSet):
permission_classes = (permissions.IsAuthenticated,)
serializer_class = QuestionSerializer
queryset = Question.objects.all()
Thanks very much.
You will need to define your own UserManager [Django-doc] to register the user without making use of is_staff, is_superuser, etc. This manager is used to create user objects. Since you have set fields like is_staff, is_superuser, etc. to None, these are no longer model fields.
Therefore you should implement your own user manager that will no longer try to set these fields in the user model. So this means it looks like:
from django.contrib.auth.models import UserManager
class CustomUserManager(UserManager):
def create_user(self, username, email=None, password=None, **extra_fields):
return self._create_user(username, email, password, **extra_fields)
def create_superuser(self, username, email=None, password=None, **extra_fields):
return self._create_user(username, email, password, **extra_fields)
This UserManager will not add is_staff and/or is_superuser to the fields that are used. You thus assign the CutomUserManager as objects manager to the user model:
class User(AbstractUser):
# ⋮
objects = CustomUserModel()

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

table services_parceiros has no column named user_id, DJANGO

thanks for your time.
i've been trying to set a model to his creator user. although i'm getting this error and would like to know if am'i doing anything wrong before try a AbstractUser. i'did my user app just in the forms.py i don't know if thats the reason.
Error:
table services_parceiros has no column named user_id
accounts/forms.py:
from django import forms
from django.contrib.auth import get_user_model, authenticate
User = get_user_model()
class LoginForm(forms.Form):
username = forms.CharField()
password = forms.CharField(widget=forms.PasswordInput())
def clean (self, *args, **kwargs):
username = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
if username and password:
user = authenticate(username=username, password=password)
if not user:
raise forms.ValidationError('usuario não encontrado')
if not user.check_password(password):
raise forms.ValidationError('senha incorreta')
if not user.is_active:
raise forms.ValidationError('usuario desativado')
return super(LoginForm, self).clean(*args, **kwargs)
class RegisterForm(forms.ModelForm):
first_name = forms.CharField(max_length=100)
last_name = forms.CharField(max_length=100)
email = forms.EmailField(label='Email address')
email2 = forms.EmailField(label='Confirm Email')
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = User
fields = [
'first_name',
'last_name',
'username',
'email',
'email2',
'password'
]
def clean(self, *args, **kwargs):
email = self.cleaned_data.get('email')
email2 = self.cleaned_data.get('email2')
if email != email2:
raise forms.ValidationError("Emails must match")
email_qs = User.objects.filter(email=email)
if email_qs.exists():
raise forms.ValidationError(
"This email has already been registered")
return super(RegisterForm, self).clean(*args, **kwargs)
services/models.py:
from django.db import models
from phone_field import PhoneField
from datetime import datetime
from django.contrib.auth import get_user_model
from django.template.defaultfilters import slugify
from accounts.forms import User
get_user_model = User
class Parceiros (models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
nome = models.CharField(max_length=200)
endereco = models.TextField(max_length=400, blank=True)
responsavel = models.CharField(max_length=100)
tel = PhoneField(max_length=12)
created_at = models.DateTimeField(auto_now=True)
updated_at = models.DateTimeField(auto_now_add=True, blank=True)
ativo = models.BooleanField(default=False)
def __str__(self):
return '%s %s' % (self.user, self.nome)
and services/views.py:
from django.shortcuts import render, redirect
from .models import Servicos, Parceiros, Imagens
from django.views.generic import UpdateView, DetailView, ListView
from .forms import ParceirosForm, ServicosForm, ImagensForm
from django.contrib.auth.decorators import login_required
from django.contrib.auth.context_processors import auth
def home_view(request):
serv = Servicos.objects.all()
context = {'serv': serv }
return render (request, 'home.html', context)
#login_required
def parceiros_create(request):
if request.method == 'POST':
form = ParceirosForm(request.POST)
if form.is_valid():
parceiro = form.save(commit=False)
parceiro.user = request.user # assuming user is a FK field on Parceiros#
parceiro.save()
return redirect('home2')
else:
form = ParceirosForm()
context = {
'form': form,
}
return render (request, 'parceiroform.html', context)
def get_queryset(self):
return super().get_queryset().filter(parceiro__user=self.request.user)
services/forms.py:
if i specify the user on fields of my ParceirosForm i'll get the field displayed and still gets the same error when submit.
from django import forms
from .models import Servicos, Imagens, Parceiros
from phone_field import PhoneField
class ParceirosForm(forms.ModelForm):
nome = forms.CharField(max_length=200)
endereco = forms.TextInput()
responsavel = forms.CharField(max_length=100)
tel = PhoneField(max_length=12)
class Meta:
prefix = 'parceiro'
model = Parceiros
fields = ['nome', 'endereco', 'responsavel', 'tel']
0001_initial.py:
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import phone_field.models
import services.models
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Parceiros',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('nome', models.CharField(max_length=200)),
('endereco', models.TextField(blank=True, max_length=400)),
('responsavel', models.CharField(max_length=100)),
('tel', phone_field.models.PhoneField(max_length=12)),
('created_at', models.DateTimeField(auto_now=True)),
('updated_at', models.DateTimeField(auto_now_add=True)),
('ativo', models.BooleanField(default=False)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),

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

Categories

Resources