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
Related
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")
I am creating a donation app that allows donors to create listings. This data is stored in a Django Model and is going to be displayed on a page. I want to save the user's username to the Django model and display it on the page. My code is down below
Models.py
class Donation(models.Model):
title = models.CharField(max_length=30)
phonenumber = models.CharField(max_length=12)
category = models.CharField(max_length=20)
image = models.CharField(max_length=1000000)
deliveryorpickup = models.CharField(max_length=8)
description = models.TextField()
Views.py
from django.contrib.auth.models import User
from django.http.request import RAISE_ERROR
from django.http.response import HttpResponseRedirect
from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.forms import forms, inlineformset_factory
from django.contrib.auth.forms import UserCreationForm, UsernameField
from .forms import CreateUserForm
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from home.models import Donation
# Create your views here.
def index(request,*args, **kwargs):
return render(request, "index.html", {} )
#login_required(login_url='/login/')
def dashboard(request,*args, **kwargs):
return render(request, "dashboard.html", {} )
def register(request, ):
if request.user.is_authenticated:
return redirect('/dashboard/')
else:
form = CreateUserForm()
if request.method == "POST":
form = CreateUserForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
messages.success(request, f'Your account has been successfully created, {username} ')
return redirect('loginpage')
context = {'form': form}
return render(request, "register.html", context )
def loginpage(request):
if request.user.is_authenticated:
return redirect('/dashboard/')
else:
if request.method == 'POST':
username = request.POST.get('username')
password =request.POST.get('password')
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return redirect('/dashboard')
else:
messages.error(request, 'Username OR password is incorrect')
context = {}
return render(request, 'login.html', context)
def logoutuser(request):
logout(request)
return HttpResponseRedirect('/login/')
#login_required(login_url='/login/')
def donate(request):
if request.method == "POST":
title = request.POST['donationtitle']
phonenumber = request.POST['phonenumber']
category = request.POST['category']
image = request.POST['imagelink']
deliveryorpickup = request.POST['deliveryorpickup']
description = request.POST['description']
ins = Donation(title = title, phonenumber = phonenumber, category = category, image = image, deliveryorpickup = deliveryorpickup, description = description )
ins.save()
return render(request,'donate.html')
Forms.py (This is where the user is created)
class CreateUserForm(UserCreationForm):
username = forms.CharField(required=True, max_length=30, )
email = forms.EmailField(required=True)
first_name = forms.CharField(required=True, max_length=50)
last_name = forms.CharField(required=True, max_length=50)
class Meta:
model = User
fields = ['username', 'email', 'first_name', 'last_name', 'password1', 'password2',]
#function to display errors
def clean(self):
cleaned_data=super().clean()
password1 = self.cleaned_data.get('password1')
password2 = self.cleaned_data.get('password2')
if User.objects.filter(username=cleaned_data["username"]).exists():
raise ValidationError("This username is taken, please try another one")
elif password1 != password2:
raise forms.ValidationError("2 password fields do not match")
elif len(password1) < 8 or len(password2) < 8:
raise forms.ValidationError("Passwords must be at least 8 characters long")
To associate the user with the Donation model, you should first add a ForeignKey field to the model class:
from django.conf import settings
class Donation(models.Model):
... # your other donation fields
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
blank=True,
null=True,
)
Once you've made this change, and run the migrations, in your views.py you'll pass the currently signed in user to the Donation model creation:
#login_required(login_url='/login/')
def donate(request):
if request.method == "POST":
ins = Donation(
title=request.POST["title"],
... # all of the other fields
user=request.user, # 👈 This adds the user
)
ins.save()
return render(request,'donate.html')
Notes
Using settings.AUTH_USER_MODEL allows your class to use a custom user model, or django's default user model, based on your project's settings.
To understand what on_delete=models.CASCADE does, you should read django's documentation about it.
Also, instead of manually passing all of the request.POST[...] values to the Donation model, I recommend that you use a ModelForm. It will handle errors and validation for you, as well as generate the HTML displayed in the template. Using a model form here would make your view code change to this:
from django.forms import ModelForm
class DonationForm(ModelForm):
class Meta:
model = Donation
exclude = ["user"]
#login_required(login_url="/login/")
def donate(request):
if request.method == "POST":
form = DonationForm(request.POST)
if form.is_valid():
donation = form.save(commit=False)
donation.user = request.user
donation.save()
# Use a redirect to prevent duplicate submissions
# https://docs.djangoproject.com/en/3.2/topics/http/shortcuts/#redirect
return redirect(request, ...)
else:
form = DonationForm()
return render(request, "donate.html", {"form": form})
I am trying to build multi vendor e-commerce using django rest-framework. I stuck at how to authenticate multi-users like i have customers and sellers . i have successfully created API's for sellers but i am unable to give roles to uses. (Basically we are building mobile app and web)
my models are:
from django.db import models
from django.contrib.auth.models import User
from django.db import models
# Create your models here.
class SellerProfile(models.Model):
user = models.OneToOneField(
User, blank=True, null=True, on_delete=models.SET_DEFAULT, default=None)
mobileNo = models.CharField(max_length=40, default=None)
cnic = models.CharField(max_length=30, default=None)
city = models.CharField(max_length=30, default=None)
address = models.CharField(max_length=30, default=None)
state = models.CharField(max_length=30, default=None)
shop_name = models.CharField(max_length=30, default=None)
def __str__(self):
return self.user.username
class ClientProfile(models.Model):
user = models.OneToOneField(User, models.SET_DEFAULT, default=None)
def __str__(self):
return self.user.username
and my serializers :
from profiles.models import SellerProfile, ClientProfile
from rest_framework import serializers, status
# from models import *
from django.contrib.auth.models import User
from django.contrib.auth.hashers import make_password
class UserSerializer(serializers.ModelSerializer):
password = serializers.CharField(
write_only=True,
required=True,
help_text='password',
style={'input_type': 'password', 'placeholder': 'Password'}
)
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email', 'password')
def create(self, validated_data):
user = super().create(validated_data)
user.set_password(validated_data['password'])
user.save()
return user
# def __str__(self):
# return self.user
class ClientSerializer(serializers.ModelSerializer):
user = UserSerializer(required=True)
class Meta:
model = ClientProfile
fields = ['user']
def create(self, validated_data):
user_data = validated_data.pop('user')
user = UserSerializer.create(
UserSerializer(), validated_data=user_data)
buyer, created = ClientProfile.objects.update_or_create(
user=user,
# mobileNo=validated_data.pop('mobileNo'),
# location=validated_data.pop('location'),
# address=validated_data.pop('address'),
)
return buyer
class SellerSerializer(serializers.ModelSerializer):
user = UserSerializer(required=True)
class Meta:
model = SellerProfile
fields = ('user', 'mobileNo', 'cnic',
'city', 'address', 'state', 'shop_name')
def create(self, validated_data):
user_data = validated_data.pop('user')
user = UserSerializer.create(
UserSerializer(), validated_data=user_data)
seller, created = SellerProfile.objects.update_or_create(user=user,
mobileNo=validated_data.pop(
'mobileNo'),
cnic=validated_data.pop(
'cnic'),
city=validated_data.pop(
'city'),
address=validated_data.pop(
'address'),
shop_name=validated_data.pop(
'shop_name'),
)
return seller
here is my view set :
from .serializers import *
from profiles.models import *
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework import status
class SellerViewSet(viewsets.ModelViewSet):
serializer_class = SellerSerializer
queryset = SellerProfile.objects.all()
def get(self, format=None):
seller = SellerProfile.objects.all()
serializer = SellerSerializer(seller, many=True)
return Response(serializer.data)
def post(self, request):
serializer = SellerSerializer(data=request.data)
if serializer.is_valid(raise_exception=ValueError):
serializer.create(validated_data=request.data)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.error_messages,
status=status.HTTP_400_BAD_REQUEST)
class BuyerViewSet(viewsets.ModelViewSet):
serializer_class = ClientSerializer
queryset = ClientProfile.objects.all()
def get(self, format=None):
seller = ClientProfile.objects.all()
serializer = UserSerializer(seller, many=True)
return Response(serializer.data)
def post(self, request):
serializer = ClientSerializer(data=request.data)
if serializer.is_valid(raise_exception=ValueError):
serializer.create(validated_data=request.data)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.error_messages,
status=status.HTTP_400_BAD_REQUEST)
here is views for web registration:
def registration(request):
if request.method == 'POST':
form = UserForm(request.POST)
sellerFrom = SellerFrom(request.POST)
if form.is_valid() and sellerFrom.is_valid():
user = form.save()
seller = sellerFrom.save()
seller.user = user
seller.save()
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password1')
# user = authentication(username=username, password=password)
# login(request, user)
messages.success(request, 'account was created for' + username)
form = UserForm()
sellerFrom = SellerFrom()
return redirect('login')
else:
form = UserForm()
sellerFrom = SellerFrom()
context = {'form': form, 'sellerForm': sellerFrom}
return render(request, 'gui/signup.html', context)
here is view for login :
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(request, username=username, password=password)
if user is not None:
# if user.role == "seller_profile":
auth_login(request, user)
return redirect('home')
else:
messages.info(request, 'Username or password is incorrect')
context = {}
return render(request, 'gui/login.html', context)
Now what above coding is doing . actually it handling user registration and login but i want to give them role like seller = seller_role and client = client_role. and also want to know how to authenticate user while login whether it is seller or client.
i am looking for answer thank you so much and sorry for my bad english
I have a custom User Model. I can successfully add user to it and want to add the relationship to a related model. It gives me no errors but does not link the user to the related field compusers in the company model. Basically I need it to after creating a user, also add the user to the related compusers field.
This is the code I am trying in the view:
self.object.compusers.add(self.object.id)
The Model
class Company(models.Model):
user = models.ManyToManyField(settings.AUTH_USER_MODEL,related_name='compusers')
name = models.CharField(max_length=265, blank=True)
tel = models.IntegerField(blank=True, null=True)
email = models.EmailField(max_length=265,blank=True)
address = models.TextField(blank=True)
postal = models.TextField(blank=True)
regno = models.CharField(max_length=265,blank=True)
vatno = models.CharField(max_length=265,blank=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('nodisoapp:home')
The View
class AddStaffView(CreateView):
form_class = forms.AddStaffMember
success_url = reverse_lazy('nodisoapp:home')
template_name = "scrty/addstaff.html"
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.password = get_random_string(length=8)
self.object.save()
self.object.compusers.add(self.object.id)
return super(AddStaffView, self).form_valid(form)
The form
Class AddStaffMember(forms.ModelForm):
usrtype = forms.ChoiceField(choices=[('Admin','Admin'),('Manager','Manager'),('Employee','Employee')],label="User Type: See below for descriptions" )
class Meta:
model = get_user_model()
fields = ("firstname","lastname","email","usrtype")
labels = {
"firstname": _("First Name"),
"lastname": _("Last Name"),
"email": _("E-mail"),
}
I recently went through this same process. It's not finalized, but it should help. With this project, I create a user, and that user (customer) has obvious attributes that are required (e.g. first name, last name, phone, email, company, and site). There was a lot of problems in just simply trying to extend the django User model and add relationships that work well, so I went with having my own user model. This model retains the use of Username. I can provide projects that uses email instead of username. This project also uses some styling widgets on the login form. I have other projects that style other parts of auth as well.
main/models.py
from django.contrib.auth.models import (
AbstractBaseUser,
PermissionsMixin,
BaseUserManager,
)
from django.core.mail import send_mail
from django.db import models
from django.utils.translation import ugettext_lazy as _
from customers import models as customers_models
class TravelModel(models.Model):
mileageRate = models.DecimalField(max_digits=4, decimal_places=3)
def __str__(self):
return '%s' % (self.mileageRate)
class Meta:
verbose_name = "Current Federal Milage Rate"
#verbose_name_plural = "Milage"
class UserManager(BaseUserManager):
def create_user(self, username, email, firstName, lastName, company, phone, password=None, **kwargs):
if not email:
raise ValueError('Users must have an email address')
user = self.model(
username = userName,
email=self.normalize_email(email),
firstName = firstName,
lastName = lastName,
company = company,
phone = phone
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, username, email, firstName, lastName, password=None, **kwargs):
user = self.model(
username = username,
email = self.normalize_email(email),
firstName = firstName,
lastName = lastName,
)
user.set_password(password)
user.is_superuser = True
user.is_admin = True
user.save(using=self._db)
return user
class MyUser(AbstractBaseUser, PermissionsMixin):
username = models.CharField(_('Username'), max_length=150, unique=True, null=False, blank=False)
email = models.EmailField(_('E-mail Address'), max_length=255, unique=True)
firstName = models.CharField(_('First Name'),max_length=50, blank=False, null=False)
lastName = models.CharField(_('Last Name'),max_length=50, blank=False, null=False)
company = models.ForeignKey(customers_models.CompanyModel, on_delete=models.PROTECT, null=False)
phone = models.ForeignKey(customers_models.PhoneModel, on_delete=models.PROTECT, null=False)
is_admin = 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 = UserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email','firstName', 'lastName']
class Meta(object):
ordering = ['firstName']
verbose_name = _('Contact')
verbose_name_plural = _('Contacts')
def __str__(self):
return '%s - %s %s - %s - %s' % (self.company, self.firstName, self.lastName, self.email, self.phone)
def get_full_name(self):
return self.email
def get_short_name(self):
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
def email_user(self, subject, message, from_email=None, **kwargs):
send_mail(subject, message, from_email, [self.email], **kwargs)
#property
def is_staff(self):
return self.is_admin
main/views.py
from django.shortcuts import render, redirect
from django.http import HttpResponseRedirect
from django.contrib import messages
from django.contrib.auth import logout, login, authenticate, update_session_auth_hash
from django.contrib.auth.decorators import login_required, permission_required
from django.contrib.auth.forms import PasswordChangeForm
from django.core.mail import send_mail
from .models import MyUser
from .forms import RegistrationForm, LoginForm, ResetPasswordForm
def IndexView(request):
return render(request, 'main/index.html')
def ContactView(request):
return render(request, 'main/contact.html')
def LoginView(request):
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
return redirect('home')
else:
form = LoginForm()
args={ 'form': form }
return render(request, 'main/login.html', args)
def LogoutView(request):
logout(request)
#login_required
def PasswordChangeView(request):
if request.method == 'POST':
form = PasswordChangeForm(request.user, request.POST)
if form.is_valid():
user = form.save()
update_session_auth_hash(request, form.user) # Important!
messages.success(request, 'Your password was successfully updated!')
return redirect('change_password_done')
else:
messages.error(request, 'Please correct the error below.')
else:
form = PasswordChangeForm(request.user)
return render(request, 'main/change_password_form.html', {
'form': form
})
#permission_required(['auth.add_customuser', 'auth.change_customuser'], raise_exception=True)
def RegisterView(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
return redirect('main')
else:
form = RegistrationForm()
args = {'form': form}
return render(request, 'main/register.html', args)
main/urls.py
from django.conf.urls import url, include
from django.urls import reverse_lazy
from .views import IndexView, RegisterView, ContactView, PasswordChangeView
from .forms import LoginForm
from django.contrib.auth.views import (
LogoutView,
login,
PasswordChangeView,
PasswordChangeDoneView,
PasswordResetView,
PasswordResetDoneView,
PasswordResetConfirmView,
PasswordResetCompleteView,
)
# main app URLS extend from the base url i.e. www.website.com/*
urlpatterns = [
url(r'^$', IndexView, name='main'),
url(r'^register/$', RegisterView, name='register'),
url(r'^contact/$', ContactView, name='contact'),
url(r'^logout/$', LogoutView.as_view(next_page=reverse_lazy('main')),
name='logout'
),
url(r'^service/', include('service.urls')),
url(r'^consultation/', include('consultation.urls')),
# successful logins are redirected to the settings.LOGIN_REDIRECT_URL
url(r'^login/$', login, name='login', kwargs={'template_name':'main/login.html', 'authentication_form':LoginForm},
),
url(r'^change_password/$',
PasswordChangeView.as_view(
template_name='main/change_password_form.html'
),
name='password_change'),
url(r'^change_password/done/$',
PasswordChangeDoneView.as_view(
template_name='main/change_password_done.html'
),
name='password_change_done'),
url(r'^password_reset/$',
PasswordResetView.as_view(template_name='main/reset_password_form.html'),
name='password_reset'),
url(r'^password_reset/done/$',
PasswordResetDoneView.as_view(template_name='main/reset_password_done.html'),
name='password_reset_done'),
url(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
PasswordResetConfirmView.as_view(template_name='main/reset_password_confirm.html'),
name='password_reset_confirm'),
url(r'^reset/done/$',
PasswordResetCompleteView.as_view(template_name='main/reset_password_complete.html'),
name='password_reset_complete'),
]
main/forms.py
from django import forms
from django.contrib.auth.forms import (
AuthenticationForm,
UserCreationForm,
UserChangeForm,
PasswordResetForm,
)
from .models import MyUser
class ResetPasswordForm(PasswordResetForm):
pass
class LoginForm(AuthenticationForm):
username = forms.CharField(label='Username',
widget=forms.TextInput(attrs={'placeholder':'Username'}))
password = forms.CharField(label='Password',
widget=forms.PasswordInput(attrs={'placeholder':'Password'}))
class RegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = MyUser
fields = (
'username',
'firstName',
'lastName',
'email',
'password1',
'password2'
)
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
user.first_name = self.cleaned_data['firstName']
user.last_name = self.cleaned_data['lastName']
user.email = self.cleaned_data['email']
if commit:
user.save()
return user
customers/models.py
from django.db import models
from django.core.validators import RegexValidator
from main import models as main_models
from django.utils.translation import ugettext_lazy as _
class PhoneModel(models.Model):
phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$',
message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed."
)
phone_number = models.CharField(_('Phone Number'),validators=[phone_regex],
max_length=15, blank=True
) # validators should be a list
def __str__(self):
return '%s' % (self.phone_number)
class Meta:
verbose_name = "Phone Number"
#verbose_name_plural = "Phone Numbers"
class CompanyModel(models.Model):
name = models.CharField(_('Company Name'),max_length=255)
since = models.DateField(auto_now_add=True)
def __str__(self):
return '%s - Customer since %s' % (self.name, self.since)
class Meta:
ordering = ['name']
verbose_name = "Company Name"
#verbose_name_plural = "Companies"
class DetailsModel(models.Model):
company = models.OneToOneField(CompanyModel, on_delete=models.CASCADE, primary_key=True)
distance = models.SmallIntegerField(blank=True)
rate = models.DecimalField(max_digits=5, decimal_places=2)
def __str__(self):
return '%s - Distance: %s - Rate: %s' % (self.company, self.distance, self.rate)
class Meta:
ordering = ['company']
verbose_name = "Customer Agreement Information"
#verbose_name_plural = "Details"
class SiteModel(models.Model):
company = models.ForeignKey(CompanyModel, on_delete=models.CASCADE)
#contact = models.ForeignKey(main_models.User.email, on_delete=models.CASCADE)
details = models.ForeignKey(DetailsModel, on_delete=models.CASCADE)
street1 = models.CharField(max_length=255)
street2 = models.CharField(max_length=255, blank=True)
city = models.CharField(max_length=50)
state = models.CharField(max_length=2)
zipcode = models.IntegerField()
country = models.CharField(max_length=50)
def __str__(self):
return '%s - %s, %s' % (self.company, self.city, self.state)
class Meta:
ordering = ['company']
verbose_name = "Customer Site Information"
#verbose_name_plural = "Sites"
class ContactModel(models.Model):
company = models.ForeignKey(CompanyModel, on_delete=models.PROTECT, null=True)
first_name = models.CharField(_('First Name'),max_length=255)
last_name = models.CharField(_('First Name'),max_length=255)
email = models.EmailField(_('E-mail Address'), max_length=255, unique=True)
phone = models.ForeignKey(PhoneModel, on_delete=models.PROTECT, null=True)
def __str__(self):
return '%s %s of %s' % (self.first_name, self.last_name, self.company)
I found the answer, the many to many field needs a company reference, therefore instead of adding a user instance you just add a company instance
I am using python and django to develop an web application where I have built a CustomUser model extending the user model and also built a sign up form. But problem is that each time I am registering a new user when I go back to login page and enter the user name and password, it keeps giving the message "Username and Password does not match".
I am pasting the codes here:
forms.py
import re
from django.utils.translation import ugettext_lazy as _
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from models import CustomUser
import pdb
class RegistrationForm(UserCreationForm):
"""A form for creating new users. Includes all the required
fields, plus a repeated password."""
first_name = forms.RegexField(regex=r'^\w+$', widget=forms.TextInput(attrs=dict(required=True, max_length=30)), label=_("First name"), error_messages={ 'invalid': _("This value must contain only letters") })
last_name = forms.RegexField(regex=r'^\w+$', widget=forms.TextInput(attrs=dict(required=True, max_length=30)), label=_("Last name"), error_messages={ 'invalid': _("This value must contain only letters") })
password1 = forms.CharField(widget=forms.PasswordInput(attrs=dict(required=True, max_length=30, render_value=False)), label=_("Password"))
password2 = forms.CharField(widget=forms.PasswordInput(attrs=dict(required=True, max_length=30, render_value=False)), label=_("Password (again)"))
date_of_birth = forms.DateField(widget=forms.TextInput(attrs= {'class':'datepicker'}))
sex = forms.ChoiceField(choices=(('M', 'MALE'), ('F', 'FEMALE')), label=_("Sex"))
voter_id = forms.CharField(widget=forms.TextInput(attrs=dict(required=True, max_length=30)), label=_("Voter Id"))
is_election_staff = forms.BooleanField(initial=False, required=False)
class Meta:
model = CustomUser
fields = ['first_name', 'last_name', 'voter_id', 'date_of_birth', 'sex', 'is_election_staff']
def clean_username(self):
try:
user = User.objects.get(voter_id__iexact=self.cleaned_data['voter_id'])
except User.DoesNotExist:
return self.cleaned_data['voter_id']
raise forms.ValidationError(_("The user with given voter id already exists. Please try another one."))
def clean(self):
if 'password1' in self.cleaned_data and 'password2' in self.cleaned_data:
if self.cleaned_data['password1'] != self.cleaned_data['password2']:
raise forms.ValidationError(_("The two password fields did not match."))
return self.cleaned_data
def save(self, commit=True):
# Save the provided password in hashed format
user = super(RegistrationForm, self).save(commit=False)
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.date_of_birth = self.cleaned_data['date_of_birth']
user.sex = self.cleaned_data['sex']
user.voter_id = self.cleaned_data['voter_id']
user.is_election_staff = self.cleaned_data['is_election_staff']
user.username = user.voter_id
user.set_password(self.cleaned_data['password1'])
if commit:
user.save()
return user
models.py
from __future__ import unicode_literals
from django.db import models
from django.contrib.auth.models import (
AbstractBaseUser)
class Party(models.Model):
name = models.CharField(max_length=200)
num_seats_won = models.IntegerField(default=0)
SEX = (('M', 'MALE'), ('F', 'FEMALE'))
class CustomUser(AbstractBaseUser):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
date_of_birth = models.DateField()
sex = models.CharField(choices=SEX, max_length=10)
is_election_staff = models.BooleanField(default=True)
voter_id = models.CharField(max_length=40, unique=True)
USERNAME_FIELD = 'voter_id'
def __str__(self):
return "%s %s" % (self.first_name, self.last_name)
voting/urls.py: (Here voting is my application name)
urlpatterns = [
# url(r'^$', views.index, name='index'),
url(r'^$', 'django.contrib.auth.views.login'),
url(r'^logout/$', logout_page),
url(r'^register/$', register),
url(r'^register/success/$', register_success),
url(r'^home/$', home),
]
views.py
from .forms import *
from django.contrib.auth.decorators import login_required
from django.contrib.auth import logout
from django.views.decorators.csrf import csrf_protect
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
from django.template import RequestContext
import pdb
#csrf_protect
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
print "In register request = "+ str(request.POST)
form.save()
return HttpResponseRedirect('/voting/register/success/')
else:
form = RegistrationForm()
variables = RequestContext(request, {
'form': form
})
return render_to_response(
'registration/register.html',
variables,
)
def register_success(request):
print "In success request = "+ str(request)
return render_to_response(
'registration/success.html',
)
def logout_page(request):
logout(request)
return HttpResponseRedirect('/voting/')
#login_required
def home(request):
return render_to_response(
'home.html',
{ 'user': request.user }
)
Can anyone please suggest me the mistake that I am doing here? Thanks in advance.
Your Override the user model but have make change in backend.py which is use to check when user try to login in this file i think django checking username and password from user model.