I'm new in Django. I tried to make a registration with a custom user and I'm struggling with errors.
views.py
from django.shortcuts import render
from django.urls import reverse
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse,HttpResponseRedirect
from django.contrib.auth import authenticate,login,logout
from django.views.generic import FormView,TemplateView,ListView
from .forms import RegisterForm
from .models import User
# Create your views here.
#user-login view
def register(request):
registred=False
if request.method=="POST":
user_register=RegisterForm(data=request.POST)
if user_register.is_valid():
user=User.save()
user.set_password(user.password)
user.save()
registred=True
return HttpResponseRedirect(reverse('index'))
else:
return HttpResponse('there is a problem')
else:
return render(request,'register.html',{'registred':registred,'user_register':RegisterForm})
def user_login(request):
if request.method=='POST':
email=request.POST.get('email')
password=request.POST.get('password')
user=authenticate(email=email,password=password)
if user is not None:
return HttpResponseRedirect(reverse('index'))
else:
return HttpResponse("Account not found")
else:
return render(request,'login.html')
#user-logout view
#login_required
def user_logout(request):
logout(request)
return HttpResponseRedirect(reverse('index'))
#registration view
models.py
# accounts.models.py
from django.db import models
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser
)
# accounts.models.py
class UserManager(BaseUserManager):
def create_user(self, email, password=None):
"""
Creates and saves a User with the given email and password.
"""
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email=self.normalize_email(email),
)
user.set_password(password)
user.save(using=self._db)
return user
def create_staffuser(self, email, password):
"""
Creates and saves a staff user with the given email and password.
"""
user = self.create_user(
email,
password=password,
)
user.staff = True
user.save(using=self._db)
return user
def create_superuser(self, email, password):
"""
Creates and saves a superuser with the given email and password.
"""
user = self.create_user(
email,
password=password,
)
user.staff = True
user.admin = True
user.save(using=self._db)
return user
# hook in the New Manager to our Model
class User(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
username=models.CharField(default='',unique=True,max_length=50)
full_name=models.CharField(default='',max_length=50)
short_name=models.CharField(default='',max_length=50)
active = models.BooleanField(default=True)
staff = models.BooleanField(default=False) # a admin user; non super-user
admin = models.BooleanField(default=False) # a superuser
# notice the absence of a "Password field", that is built in.
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = [] # Email & Password are required by default.
def get_full_name(self):
# The user is identified by their email address
return self.full_name
def get_short_name(self):
# The user is identified by their email address
return self.short_name
def __str__(self): # __unicode__ on Python 2
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?"
return self.staff
#property
def is_admin(self):
"Is the user a admin member?"
return self.admin
#property
def is_active(self):
"Is the user active?"
return self.active
objects = UserManager()
the error :
TypeError at /register/
save() missing 1 required positional argument: 'self'
From views.py, remove user=User.save(), which is invalid not having an instance (that self which is missing)
user_register=RegisterForm(data=request.POST)
if user_register.is_valid():
user = User()
user.set_password(user.password)
user.save()
registred=True
Related
i have made a custom user model. using that model i have made a login form, signup form. but sign up form and logout works fine. but whenever i try to submit login form it does not authenticate. where is the problem? there is two authentication one is in for login in forms.py other is in views.py for login
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from diabetes.models import UserSignupModel
from django.contrib.auth import login,authenticate,logout
class UserSignupForm(UserCreationForm):
email=forms.EmailField(max_length=60,help_text="add a valid email address",required=True)
name=forms.CharField(max_length=15,help_text="add a valid name")
age=forms.CharField(max_length=15)
class Meta:
model=UserSignupModel
fields=('email','name',"username",'age',"password1","password2")
class UserLoginForm(forms.ModelForm):
password=forms.CharField(label="password",widget=forms.PasswordInput)
class Meta:
model=UserSignupModel
fields=("email","password")
def clean(self):
if self.is_valid():
email=self.cleaned_data['email']
password=self.cleaned_data['password']
if not authenticate(email=email,password=password,backend='django.contrib.auth.backends.ModelBackend'):
raise forms.ValidationError("Invalid LOGIN")
models.py
from django.db import models
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
class SignUpManager(BaseUserManager):
def create_user(self, email,age,name, username, password=None):
#if not email:
#raise ValueError("insert user")
if not username:
raise ValueError("insert username")
if not name:
raise ValueError("insert name")
if not age:
raise ValueError("insert age")
user = self.model(
email=self.normalize_email(email),
username=username,
age=age,
name=name,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self,email,name,age,username, password):
user = self.create_user(
email=self.normalize_email(email),
username=username,
password=password,
age=age,
name=name,
)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class UserSignupModel(AbstractBaseUser):
email = models.EmailField(verbose_name="email", max_length=60,unique=True)
age = models.CharField(max_length=15)
name = models.CharField(max_length=15)
username = models.CharField(max_length=15, unique=True)
date_joined = models.DateTimeField(verbose_name="date joined", auto_now_add=True)
last_login = models.DateTimeField(verbose_name="last login", auto_now=True)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
USERNAME_FIELD = "username"
REQUIRED_FIELDS = ['email','name','age']
objects = SignUpManager()
def __str__(self):
return self.name
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return True
#migrate --run-syncdb in case no work
views.py
from django.shortcuts import render,redirect
from django.contrib.auth import login,authenticate,logout
from diabetes.forms import UserSignupForm,UserLoginForm
# Create your views here.
def home(request):
return render(request,'diabetes/home.html')
def signupuser(request):
context={}
if request.POST:
form=UserSignupForm(request.POST)
if form.is_valid():
form.save()
email=form.cleaned_data.get('email')
raw_password=form.cleaned_data.get('password1')
name=form.cleaned_data.get('name')
age=form.cleaned_data.get('age')
username=form.cleaned_data.get('username')
account=authenticate(email=email,password=raw_password,name=name,age=age,username=username)
login(request,account)
return redirect('home')
else:
context["reg_form"]=form
else:
form = UserSignupForm()
context["reg_form"] = form
return render (request,'diabetes/signupuser.html',context)
def logoutuser(request):
logout(request)
return redirect('home')
def loginuser(request):
context={}
user=request.user
if user.is_authenticated:
return redirect('home')
if request.method=="POST":
form=UserLoginForm(request.POST)
if form.is_valid():
email=request.POST['email']
password=request.POST['password']
user=authenticate(password=password,email=email,backend='django.contrib.auth.backends.ModelBackend')
if user:
login(request,user)
return redirect("home")
else:
form=UserLoginForm()
context['form']=form
return render(request,"diabetes/loginuser.html",context)
the code below is a simple register for an account now when I submit this form it redirects me to the home page and this means that my form is valid and works but when I check my Admin page I see that account is not registered and I get no error. therefor I can understand here that my code is already working but it hasn't been saved.
so, how can I save member through FormView?
thanks in advance
views.py
from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.views.generic import TemplateView, View
from django.views.generic.edit import FormView, CreateView
from .forms import UserForm
from .models import User
from django.urls import reverse_lazy
class IndexView(TemplateView):
template_name = "accounts/index.html"
class ProfileView(CreateView):
template_name = 'accounts/register.html'
success_url = reverse_lazy('accounts:index')
form_class = UserForm
forms.py
from django import forms
from .models import User
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
password2 = forms.CharField(label="Confirm Password", widget=forms.PasswordInput)
class Meta:
model = User
fields = '__all__'
exclude = ('staff', 'active', 'admin', 'last_login')
def clean_password2(self):
password = self.cleaned_data['password']
password2 = self.cleaned_data['password2']
if password and password2 and password != password2:
raise forms.ValidationError("Passwords don't match")
return password2
def clean_email(self):
email = self.cleaned_data['email']
qs = User.objects.filter(email=email)
if qs.exists():
raise forms.ValidationError("email is taken")
return email
def save(self, commit=True):
user = super().save(commit=False)
user.set_password(self.cleaned_data['password'])
if commit:
user.save()
return user
models.py
from django.db import models
from django.contrib.auth.models import (AbstractBaseUser, BaseUserManager)
from django.db.models.signals import post_save
from django.dispatch import receiver
class UserManager(BaseUserManager):
def create_user(self, email, password, username, is_staff=True, is_admin=True, is_active=True):
if not email:
raise ValueError("This email is invalid")
if not password:
raise ValueError("This Password is invalid")
if not username:
raise ValueError("This Username is invalid")
user = self.model(
email=self.normalize_email(email)
)
user.staff = is_staff
user.admin = is_admin
user.active = is_active
user.set_password(password)
user.username = username
user.save(using=self._db)
return user
def create_staffuser(self, email, password, username):
user = self.create_user(
email,
password=password,
username=username,
is_staff=True,
)
return user
def create_superuser(self, email, password, username):
user = self.create_user(
email=email,
password=password,
username=username,
is_staff=True,
is_admin=True,
)
return user
class User(AbstractBaseUser):
email = models.EmailField(max_length=255, unique=True, verbose_name="Email")
first_name = models.CharField(max_length=255, verbose_name="First Name")
last_name = models.CharField(max_length=255, verbose_name="Last Name")
username = models.CharField(max_length=50, unique=True, verbose_name="Username")
active = models.BooleanField(default=True, verbose_name="Active")
staff = models.BooleanField(default=False, verbose_name="Staff")
admin = models.BooleanField(default=False, verbose_name="Admin")
timestamp = models.DateTimeField(auto_now_add=True, verbose_name="Time Stamp")
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["username"]
objects = UserManager()
def __str__(self):
return self.username
def get_short_name(self):
return self.username
def get_full_name(self):
return self.username
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
#property
def is_staff(self):
return self.staff
#property
def is_admin(self):
return self.admin
#property
def is_active(self):
return self.active
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
article = models.TextField(blank=True, max_length=500, verbose_name="Article")
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile = User.objects.create(user=kwargs['instance'])
post_save.connect(receiver=create_profile, sender=User)
Because a FormView doesn't save() the form. It's meant to be used with any form, not just ModelForms. Not every Form has a save() method.
The only thing the FormView does in form_valid() is redirect to the success url. You have to tell it yourself what you it to do after the form was verified to be valid:
def form_valid(self, form):
form.save()
return super().form_valid(form)
You can see the inner workings of FormView here.
You could use a CreateView instead of a FormView. That would do the saving for you.
i currently try the implement my very own user model. Therefor i created a new app "accounts". But each time when i try to create anew user i get the following error:
AttributeError: 'AnonymousUser' object has no attribute '_meta'
accounts - models.py:
from django.db import models
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser
)
#User Model Manager
class UserManager(BaseUserManager):
def create_user(self, username, password=None):
"""
Creates and saves a User with the given username and password.
"""
if not username:
raise ValueError('Error: The User you want to create must have an username, try again')
user = self.model(
user=self.normalize_username(username),
)
user.set_password(password)
user.save(using=self._db)
return user
def create_staffuser(self, username, password):
"""
Creates and saves a staff user with the given username and password.
"""
user = self.create_user(
username,
password=password,
)
user.staff = True
user.save(using=self._db)
return user
def create_superuser(self, username, password):
"""
Creates and saves a superuser with the given username and password.
"""
user = self.create_user(
username,
password=password,
)
user.staff = True
user.admin = True
user.save(using=self._db)
return user
class User(AbstractBaseUser):
#User fields
user = models.CharField(verbose_name='username',max_length=30,unique=True)
bio = models.TextField(max_length=5000, blank=True, null=True)
pubpgp = models.TextField(blank=True, null=True)
#Account typs
active = models.BooleanField(default=True)
staff = models.BooleanField(default=False) # a admin user; non super-user
admin = models.BooleanField(default=False) # a superuser
# notice the absence of a "Password field", that's built in.
USERNAME_FIELD = 'user'
REQUIRED_FIELDS = [] # Username & Password are required by default.
def get_full_name(self):
# The user is identified by their Username ;)
return self.user
def get_short_name(self):
# The user is identified by their Username address
return self.user
def __str__(self):
return self.user
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?"""
return self.staff
#property
def is_admin(self):
"""Is the user a admin member?"""
return self.admin
#property
def is_active(self):
"""Is the user active?"""
return self.active
objects = UserManager()
After that i jumpt back to settings.py and added the custom user model to my acctual blog application:
AUTH_USER_MODEL = 'accounts.User'
and i also added
INSTALLED_APPS = [
...
'accounts',
...
]
All this user model/django stuff is a bit new to me and i have no idea what the error "AttributeError: 'Manager' object has no attribute 'get_by_natural_key'" means.
Thanks :D
Edit: AttributeError: 'UserManager' object has no attribute 'normalize_username'
normalize_username belongs to AbstractBaseUser, you can try the code below.
In signup view, when you save the form you already get the user (form.save()). Because the reason from authentication is to verify a set of credentials and getting the user (but we already have the user)
In this line: user = authenticate(username=username, password=raw_password), the authenticate method takes request as the first argument, so it should be: user = authenticate(request, username=username, password=raw_password), therefore you got the Error 'AnonymousUser' object has no attribute '_meta'.
Try:
def signup(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
user = form.save()
login(request, user)
return redirect('post_list')
Edit UserManager:
Reaname all created users to some other name (ex. my_user) because you have tow varibales with the same name (the USERNAME_FIELD and the user created)
Here is the signature of create_user and create_superuser
create_user(*username_field*, password=None, **other_fields)
create_superuser(*username_field*, password, **other_fields)
They take the USERNAME_FIELD as the first argument, and yours is user
class UserManager(BaseUserManager):
def create_user(self, user, password=None):
"""
Creates and saves a User with the given username and password.
"""
if not user:
raise ValueError('Error: The User you want to create must have an username, try again')
my_user = self.model(
user=self.model.normalize_username(user),
)
my_user.set_password(password)
my_user.save(using=self._db)
return my_user
def create_staffuser(self, user, password):
"""
Creates and saves a staff user with the given username and password.
"""
my_user = self.create_user(
user,
password=password,
)
my_user.staff = True
my_user.save(using=self._db)
return my_user
def create_superuser(self, user, password):
"""
Creates and saves a superuser with the given username and password.
"""
my_user = self.create_user(
user,
password=password,
)
my_user.staff = True
my_user.admin = True
my_user.save(using=self._db)
return my_user
I hope this will help.
What was done
I have a custom User model called MyUser as it is described in an full example for an custom user model on the docs and a so called UserProfile that is connected to MyUser by an One-to-one relationship like it's described in the Django documentation about how to extend an existing user model.
In the documentation for Customizing authentication is an example for how to connect a post_save signal with the existing User model.
By following this, I put an testing receiver in a signals.py that is loaded by my apps.py file, like it's described in this SO answer.
Configuration
signal.py
def post_save_receiver(sender, instance, created, **kwargs):
send_mail('Testing', "Just testing...", 'hell#earth.tld', ['admin#heaven.tld'], fail_silently=False)
post_save.connect(post_save_receiver, sender=settings.AUTH_USER_MODEL)
models.py
class MyUserManager(BaseUserManager):
def create_user(self, email, password=None):
"""
Creates and saves a User with the given email and password.
"""
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email=self.normalize_email(email),
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password):
"""
Creates and saves a superuser with the given email and password.
"""
user = self.create_user(email,
password=password,
)
user.is_admin = True
user.save(using=self._db)
return user
class MyUser(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = MyUserManager()
USERNAME_FIELD = 'email'
def get_full_name(self):
# The user is identified by their email address
return self.email
def get_short_name(self):
# The user is identified by their email address
return self.email
def __str__(self): # __unicode__ on Python 2
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
def UserLogin(request):
if request.user.is_authenticated():
return HttpResponseRedirect("http://www.heaven.tld/account")
else:
if request.method == 'POST':
form = UserLoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user = authenticate(username=username, password=password)
if user is not None and user.is_active:
login(request, user)
return HttpResponseRedirect("http://www.heaven.tld/account")
else:
error_msg = 'Please try again!'
return render(request, "development",
{'form':form,
'error_msg':error_msg,
})
else:
error_msg = "Please try again!"
return render(request, "development",
{'form':form,
'error_msg':error_msg,
})
else:
form = UserLoginForm()
return render(request, "development", {'form': form})
The Problem
Now if I log in I always get this mail, but I want it only if a user was created.
Logging in causes the last_login timestamp to be updated, which triggers a save.
As others have stated, you just need to use the created parameter, which your signal receives but you currently ignore.
try:
def post_save_receiver(sender, instance, created, **kwargs):
if created:
send_mail('Testing', "Just testing...", 'hell#earth.tld', ['admin#heaven.tld'], fail_silently=False)
post_save.connect(post_save_receiver, sender=settings.AUTH_USER_MODEL)
I can't understand what will be saved when you login. You can use ipdb to trace it. By the way, if you set the created condition before send_mail function, the problem should be resolved.
if created:
send_mail(...)
I use django 1.5 with custom model MyUser. I want to make users profile page, where he can modify only one field - 'about'.
I tried something like that:
forms.py:
class UserSettingsForm(forms.ModelForm):
class Meta:
model = get_user_model()
fields = ('about')
view.py:
class UserSettings(UpdateView):
form_class = UserSettingsForm
template_name = "user/settings.html"
def get_object(self, queryset=None):
return self.request.user
def get_success_url(self):
return reverse('user_detail', args=[self.request.user.username])
urls:
url(r'^settings/$', UserSettings.as_view(), name='user_settings')
model:
class MyUserManager(BaseUserManager):
def create_user(self, email, password=None):
"""
Creates and saves a User with the given email, date of
birth and password.
"""
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email=MyUserManager.normalize_email(email),
# date_of_birth=date_of_birth,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password):
"""
Creates and saves a superuser with the given email, date of
birth and password.
"""
user = self.create_user(email,
password=password,
#date_of_birth=date_of_birth
)
user.is_admin = True
user.save(using=self._db)
return user
class MyUser(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
db_index=True,
)
last_name=models.CharField(max_length=30)
first_name=models.CharField(max_length=30)
about=models.TextField(blank=True)
objects = MyUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['last_name','first_name','about']
def get_full_name(self):
# The user is identified by their email address
return self.email
def get_short_name(self):
# The user is identified by their email address
return self.email
def __unicode__(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
But I got error: django.core.exceptions.ImproperlyConfigured: AUTH_USER_MODEL refers to model 'app.MyUser' that has not been installed
How can I make users profile in django 1.5? Thx!
MyUser class should be under the application named 'app' in your settings file in order for the auth framework to pick it.