How do I save PhoneNumberField data to database? - django

My forms.py file
class CreateUserForm(UserCreationForm):
phone=PhoneNumberField()
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2', 'phone']
widgets={
'username':forms.TextInput(attrs={'placeholder':"Username"}),
'email':forms.TextInput(attrs={'placeholder':"Email Address"}),
'password1': forms.PasswordInput(attrs={'placeholder': 'Your Password'}),
'password2': forms.PasswordInput(attrs={'placeholder': 'Confirm Password'}),
'phone':PhoneNumberField(),
}
My models.py file
class CustomerReg(models.Model):
user=models.OneToOneField(User, null=True, blank=True, on_delete=models.CASCADE)
name=models.CharField(max_length=200, null=True)
email=models.EmailField(max_length=254)
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile=CustomerReg.objects.create(user=kwargs['instance'])
post_save.connect(create_profile, sender=User)
My views.py file
def registerPage(request):
if request.user.is_authenticated:
return redirect('form')
else:
form=CreateUserForm()
if request.method == 'POST':
form = CreateUserForm(request.POST)
if(form.is_valid()):
form.save()
user=form.cleaned_data.get['username']
user=User.objects.get(username=user)
phone=form.cleaned_data.get['phone']
user.phone_number=phone
user.save()
return redirect('login')
context = {'form': form}
return render(request, 'customer/register.html', context)
Upon clicking the register page an error is displayed
AttributeError at /register/
'str' object has no attribute 'User'
So is there no way I can save the data from my form and hence I would have to make new Custom User Model to save phone number of a user on register page?
My admin.py
from django.contrib import admin
from .models import *
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from .forms import UserChangeForm,UserCreationForm
# Register your models here.
admin.site.register(Customer)
class UserAdmin(BaseUserAdmin):
form = UserChangeForm
add_form = UserCreationForm
list_display = ('email', 'phone')
admin.site.register(User, UserAdmin)

If your model is created correctly, the mistake you are making is your variable user is not a User object. The error informs you that user variable represents a string (from the form's input), which does not have User as its attribute. In this case, you might have to do something like
user = User.objects.get(username=user)
in order to assign the User object to variable user.
Now that user is a User object, then, you can do
user.phone_number = phone
user.save()

Please try this:
def registerPage(request):
if request.user.is_authenticated:
return redirect('form')
else:
form=CreateUserForm()
if request.method == 'POST':
form = CreateUserForm(request.POST)
if form.is_valid():
form.save()
username=form.cleaned_data['username']
user=User.objects.get(username=username)
phone=form.cleaned_data['phone']
user.phone=phone
user.save()
return redirect('login')
context = {'form': form}
return render(request, 'customer/register.html', context)
Are you display phone field for admin then,
admin.py
from .forms import UserChangeForm,UserCreationForm
from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
class UserAdmin(BaseUserAdmin):
form = UserChangeForm
add_form = UserCreationForm
list_display = ('email', 'phone') # You can add field to display field here..
list_filter = ('name')
fieldsets = (
(None, {'fields': ('email')}),
('Personal info', {'fields': ('name','phone')}),
('Permissions', {'fields': ('name',)}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('name' ,'user','email','email', 'phone')
}),
)
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ()
admin.site.register(User, UserAdmin)

Related

Any change to the customized Django User Model is completely ignored in the Admin

I customized the User model by extending AbstractUser, not AbstractBaseUser, because I don't need to remove the username, I just need to authenticate users by email and I still want to use the authentication system that comes with Django. Therefore I just defined the email address as the username and I extended AbstractUser before any migration.
But the Admin doesn't recognize this and completely ignores what I specify in admin.py, except the register instruction. Here's the content of my admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from .models import User as CustomUser
from .forms import UserChangeForm, UserCreationForm
# from django.utils.translation import ugettext_lazy as _
# I obviously tried by extending UserAdmin too, no result
class CustomUserAdmin(admin.ModelAdmin):
add_form = UserCreationForm
form = UserChangeForm
model = CustomUser
fields = ('email')
# commenting or uncommenting the following doesn't change anything
"""
list_display = ('email', 'is_staff', 'is_active',)
list_filter = ('email', 'is_staff', 'is_active',)
exclude = ('first_name',)
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Permissions', {'fields': ('is_staff', 'is_active')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'password1', 'password2', 'is_staff', 'is_active')}
),
)
search_fields = ('email',)
ordering = ('email',)
"""
admin.site.register(CustomUser, BaseUserAdmin)
I tried everything and nothing works. I can't add the email field in the Add User form, and I can't remove the first and last_name from http://127.0.0.1:8000/admin/users/user/
It seems that the Django built-in Admin ignores any change made in any class extending AbstractUser
Obviously everything is correct in settings.py:
INSTALLED_APPS = [
'users',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
# this is necessary for the custom user model and must to be taken into account before any migration will occur.
AUTH_USER_MODEL = 'users.User'
models.py:
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.contrib.auth.base_user import BaseUserManager
from django.utils.translation import ugettext_lazy as _
class CustomUserManager(BaseUserManager):
"""
Custom user model manager where email is the unique identifier for
authentication instead of username.
Between the username field (email) and password, you must put all
the required fields. extra_fields must contain all the optional
fields.
"""
def create_user(self, email, username, password, **extra_fields):
"""
Create and save a User with the given email and password.
"""
if not email:
raise ValueError(_('The Email must be set'))
if not username:
raise ValueError("Users must have an Username")
user = self.model(
email = self.normalize_email(email),
username=username,
)
user.set_password(password)
user.save()
return user
def create_superuser(self, email, username, password):
user = self.create_user(
email=email,
username=username,
password=password
)
user.is_admin = True
user.is_staff=True
user.is_superuser=True
user.save(using=self._db)
return user
"""
This model behaves identically to the default user model, but you’ll be able to customize it in the future if the need arises. This is the recommended behavior
"""
class User(AbstractUser):
email = models.EmailField(_('email address'), unique=True)
USERNAME_FIELD = 'email'
"""
The REQUIRED_FIELDS = ['username'] must be present, otherwise the following error will arise:
TypeError: create_superuser() missing 1 required positional argument: 'username'
"""
REQUIRED_FIELDS = ['username']
objects = CustomUserManager()
def getEmailField(self):
return self.email
def __str__(self):
return self.email
forms.py:
class UserChangeForm(auth_forms.UserChangeForm):
class Meta(auth_forms.UserChangeForm.Meta):
model = CustomUser
fields = '__all__'
class UserCreationForm(auth_forms.UserCreationForm):
class Meta(auth_forms.UserCreationForm.Meta):
model = CustomUser
fields = '__all__'
Obviously I tried with several things in fields = 'whatever' but any and every change I try, is happily ignored, the Admin will always display the data and the forms in the same way as the default.
My views.py...........
from django.shortcuts import render, redirect
from django.urls import reverse
from django.contrib.auth import login
from users.forms import CustomUserCreationForm
from django.template import RequestContext
def dashboard(request):
return render(request, "users/dashboard.html")
def register(request):
if request.method == "GET":
return render(
request, "users/register.html",
{"form": CustomUserCreationForm}
)
elif request.method == "POST":
form = CustomUserCreationForm(request.POST)
if form.is_valid():
# the form.cleaned_data must be used after calling
# the form.is_valid method.
# if(email_matches(form.cleaned_data["email"], form.cleaned_data["email2"])):
user = form.save()
login(request, user)
return redirect(reverse("dashboard"))
context = {
"form": form,
}
return render(request, "users/register.html", context)
def home_page(request):
return render(request, "home_page.html")
I read somewhere that it is not possible to override anything from the AbstractUser class and to do this, I must extend the AbstractBaseUser class directly.
Is this also valid with the Admin forms? After all, I'm not overriding anything, I just trying to display the email address in the Admin Add User form.
But supposing I can't really customize anything coming from the AbstractUser. Why are things like that? This is not a today problem. I have been trying to understand this behavior for over a week now and neither the documentation nor the internet is of any help.
It seems you are using the wrong admin:
admin.site.register(CustomUser, CustomUserAdmin)
Instead of extending admin.ModelAdmin for CustomUserAdmin, you should do something like this-
class CustomUserAdmin(BaseUserAdmin):
...
...
And then please correct your model registration line like this-
admin.site.register(CustomUser, CustomUserAdmin)
P.S. Do not forget to uncomment the lines you have commented.

Custom Fields in Django not displayed in admin panel

I am using UserCreationForm for registration of the user. Added one address filed as mandatory in the code. however whenever the user is registering on the html page the address input is present.In the admin panel for users the address is not present.
form.py
class RegistrationForm(UserCreationForm):
email=forms.EmailField(required=True)
address=forms.CharField(max_length=250,required=True)
class Meta:
model=User
fields=(
'username',
'first_name',
'last_name',
'email',
'address',
'password1',
'password2'
)
def save(self,commit=True):
user=super(RegistrationForm,self).save(commit=False)
user.first_name=self.cleaned_data['first_name']
user.last_name=self.cleaned_data['last_name']
user.email=self.cleaned_data['email']
if commit:
user.save()
return user
views.py
def register(request):
print("inside views")
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
return redirect('./login.html')
else:
form = RegistrationForm()
args = {'form': form}
return render(request,'./reg_form.html',args)
else:
form = RegistrationForm()
args = {'form': form}
return render(request,'./reg_form.html',args)
In the user model all the fields are seen in the admin page,just address is not present. However while registering the user, address input is accepted.
I think you need to add this code in your models.py this field you input is required, they are added by default.
Email & Password & last_name & first_name are required by default.
REQUIRED_FIELDS = ['Address', 'SomethingElse']
and then in your admin.py
admin.py
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from .forms import UserAdminCreationForm, UserAdminChangeForm
from .models import User
name of your class and your Object you want to add in admin page.
class UserAdmin(BaseUserAdmin):
# The forms to add and change user instances
form = UserAdminChangeForm
add_form = UserAdminCreationForm
# The fields to be used in displaying the User model.
# These override the definitions on the base UserAdmin
# that reference specific fields on auth.User.
list_display = ('email', 'admin', 'first_name', 'address')
list_filter = ('admin', 'staff', 'active')
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Personal info', {'fields': ('first_name', 'address')}),
('Permissions', {'fields': ('admin', 'staff', 'active')}),
)
# add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
# overrides get_fieldsets to use this attribute when creating a user.
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'password1', 'password2', 'first_name', 'address', 'active', 'staff', 'admin')}
),
)
search_fields = ('email')
ordering = ('email',)
filter_horizontal = ()
admin.site.register(User, UserAdmin)
# Remove Group Model from admin. We're not using it.
admin.site.unregister(Group)
finally, you can check how I add address field into my project
by this link in Viva-ecommerce-models.py and Follow the Class Address

Registration form django that inherits form UserCreationForm

I am following a tutorial that has created the following registration form:
from django.contrib.auth.forms import UserCreationForm
class RegistrationForm(UserCreationForm):
email = forms.EmailField(required = True)
class Meta:
model = User
fields = (
'username',
'first_name',
'last_name',
'email',
'password1',
'password2'
)
def save(self, commit = True):
user = super(RegistrationForm, self).save(commit= False)
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.email = self.cleaned_data['email']
if commit:
user.save()
return User
Why isemail = forms.EmailField(required = True) the only field mentioned outside of class Meta, what is the purpose of this?
email field on the contrib.auth.AbstractUser (which is subclassed by User) has:
email = models.EmailField(_('email address'), blank=True)
which means that it is allowed to be blank.
Because we want it to be required in the form (for the purposes of the tutorial I assume), we must declare it explicitly.
If you want to create user registration system in django you can create forms.py file paste within it :
from django import forms
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
class RegisterUserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'input'}))
password2 = forms.CharField(label="Repeat password", widget=forms.PasswordInput(attrs={'class': 'input'}))
class Meta:
model = User
fields = ['username', 'email']
widgets = {
'username': forms.TextInput(attrs={'class': 'input'}),
'email': forms.EmailInput(attrs={'class': 'input'})
}
# Validating password
def clean_password2(self):
cd = self.cleaned_data
if cd['password2'] != cd['password']:
raise ValidationError("Password don't match")
return cd['password2']
And in views.py
-*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.http import HttpResponseForbidden, HttpResponse
from django.shortcuts import render
# Create your views here.
from django.views.generic import CreateView
from account.forms import RegisterUserForm
class RegisterUserView(CreateView):
form_class = RegisterUserForm
template_name = "account/register.html"
def dispatch(self, request, *args, **kwargs):
if request.user.is_authenticated():
return HttpResponseForbidden()
return super(RegisterUserView, self).dispatch(request, *args, **kwargs)
def form_valid(self, form):
user = form.save(commit=False)
user.set_password(form.cleaned_data['password'])
user.save()
return HttpResponse('User registered')
We override the dispath() method to make sure that the user can access the form if and only if he's not authenticated .
And for form_valid method we encrypt the password using set_password() method and then we commit to the database.
You probably will redirect the user if success rather than returning HttpResponse() as i did .
Because the default UserCreationForm doesn't have the EmailField which represents the email. But it has the other fields and there's no need to add them.
If you added a special field that is not included in the UserCreationForm like the EmailField you have to add it there.

Manually register user with FormWizard and django-registration

I have a UserModel and a UserProfile Model and I would like to use FormWizard from the formtools to both register the user and setup a userprofile with necessary inputs from the user.
I am struggling with some concepts and trying to patch this together with no success so far.
I get the error message:
AttributeError at /accounts/register/
'MyRegistrationView' object has no attribute 'request'
forms.py
class UserForm(forms.ModelForm):
password1 = forms.CharField(widget=forms.PasswordInput())
password2 = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ('username', 'email', 'password1', 'password2', 'first_name', 'last_name')
class UserProfileForm(forms.ModelForm):
course_accid = CourseModelChoiceField(Course.objects.all(), empty_label=None)
class Meta:
model = UserProfile
fields = ('picture','reg_completed')
url.py
urlpatterns = solid_i18n_patterns ('',
url(r'^accounts/register/$', RegistrationWizard.as_view([UserForm, UserProfileForm]), name='registration_register'),
url(r'^accounts/', include('registration.backends.simple.urls')),
views.py
from formtools.wizard.views import SessionWizardView
from registration.signals import *
from django.core.files.storage import FileSystemStorage
from django.conf import settings
class MyRegistrationView(RegistrationView):
def get_success_url(self, user):
return '/index/'
TEMPLATES = {"0": "registration/registration_form_wiz.html",
"1": "registration/registration_form_wiz.html",
}
class RegistrationWizard(SessionWizardView):
form_list = [UserForm, UserProfileForm]
file_storage = FileSystemStorage(location=settings.MEDIA_ROOT + '/photos')
def get_template_names(self):
return [TEMPLATES[self.steps.current]]
def done(self, form_list, **kwargs):
userreg = MyRegistrationView()
for form in form_list:
if isinstance(form, UserForm):
userreg.register(form)
elif isinstance(form, UserProfileForm):
userprofile = form.save(commit=False)
user = self.request.user
userprofile.user = user
userprofile.save()
return HttpResponseRedirect('/index/')
Any help for what is wrong or if another approach would be better, is very welcome.
Thanks!

Why is django throwing a system error?

I am building a custom user that uses an email as a username.
When I run the server to create a custom admin, I get this error
class 'user.admin.UserAdmin'>: (admin.E116) The value of
'list_filter[0]' refers to 'is_staff', which does not refer to a
Field.
Here is my code for the admin.py
from django import forms
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from .models import BaseUser
class UserCreationForm(forms.ModelForm):
"""
A form for creating new users. Includes all the required
fields, plus a repeated password.
"""
password1 = forms.CharField(
label='Password',
widget=forms.PasswordInput
)
password2 = forms.CharField(
label='Password confirmation',
widget=forms.PasswordInput
)
class Meta:
model = BaseUser
fields = ('email',)
def clean_password2(self):
#Check that the two password entries match
password1 = self.cleaned_data.get('password1')
password2 = self.cleaned_data.get('password2')
if password1 and password2 != password2:
raise forms.ValidationError('Password do not match')
return password2
def save(self, commit=True):
user = super(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data['password1'])
if commit:
user.save()
return user
class UserChangeForm(forms.ModelForm):
"""
A form for updating users. Includes all the fields on
the user, but replaces the password field with admin's
password hash display field.
"""
password = ReadOnlyPasswordHashField()
class Meta:
model = BaseUser
fields = (
'email',
'password',
'user_first_name',
'user_last_name',
'user_mobile',
'is_a_student',
)
def clean_password(self):
return self.initial["password"]
class UserAdmin(UserAdmin):
#Forms to add and change user instances
form = UserChangeForm
add_form = UserCreationForm
#The fields to be used in displaying User model.
#These overried the definitions on the base UserAdmin
#That reference specific fields on auth.User
list_display = (
'email',
)
list_filter = ('is_staff',)
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Personal info', {'fields': (
'user_first_name',
'user_last_name',
'user_mobile',
)}),
('Permission', {'fields': (
'is_a_student',
)})
)
# add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
# overrides get_fieldsets to use this attribute when creating a user.
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': (
'email',
'password1',
'password2',
'user_first_name',
'user_last_name',
'user_mobile',
'is_a_student',
)}
),
)
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ()
#Register the new UserAdmin
admin.site.register(BaseUser, UserAdmin)
admin.site.unregister(Group)
Here is the models.py
from django.db import models
from django.core.validators import RegexValidator
from django.core.urlresolvers import reverse
from django.utils import timezone
from django.core.mail import send_mail
from django.utils.http import urlquote
from django.utils.translation import ugettext_lazy as _
from django.core.mail import send_mail
from django.core.files.storage import FileSystemStorage
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser, PermissionsMixin
)
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=email,
password=password,
)
user.is_superuser = user.is_staff = True
user.save(using=self._db)
return user
class BaseUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(
verbose_name='email',
max_length=255,
unique=True,
)
user_first_name = models.CharField(max_length=30)
user_last_name = models.CharField(max_length=50)
mobile_regex = RegexValidator(regex=r'^\+?1\d{9,15}$', message="Please enter a max of 10 digits :)")
user_mobile = models.CharField(validators=[mobile_regex], blank=True, max_length=10)
is_a_student = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(auto_now_add=True)
objects = MyUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
class Meta:
verbose_name = 'User'
verbose_name_plural = 'Users'
def get_full_name(self):
return self.email
def get_short_name(self):
return self.email
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
"""
Does the user have a specific permission?
"""
return True
def is_student(self):
return self.is_a_student
#property
def is_staff(self):
"""
Is the user a member of staff?
"""
return self.is_staff
def emai_user(self, subject, message, from_email=None):
send_mail(subject, message, from_email, [self.email])
Options done
- I already took out all of the is_staff attribute in admin.py and still got an error.
- Refactored it many times to check if the problem is in different areas of my code.
At this point I am stuck. Could someone please help debug this?
#list_filter = ('is_staff',)
list_filter = ('is_admin',)
You have to add this line which will filter your data in django-admin I had the same issue I resloved it by doing this in my admin.py file or for more brief information you can check out this wonderful tutorial:
Custom Django User Admin
`list_filter = ('admin', 'staff', or anything which you want to add in filter list)`
#property
def is_staff(self):
"""
Is the user a member of staff?
"""
return self.is_staff
The above code creates a recursive execution which caused the error.
#property
def is_admin(self):
"""
Is the user a member of staff?
"""
return self.is_staff
As Django "talks" about field i would check the model in a first review
i couldn't find any password or password1 nor password2 field in the model for example.