I want to create a registration page that doesn't ask for an username, since i'm not planning on using it (i only need email and password).
However, i'm not sure how to tell django that username is not mandatory.
I'm having trouble registering users because they all get the same username (blank).
My user model:
class User(AbstractUser):
departments = models.ManyToManyField(Department)
def __str__(self):
return f'{self.first_name} {self.last_name}'
My form for registering:
class UserCreateForm(UserCreationForm):
class Meta():
fields = ('first_name', 'last_name', 'email', 'departments', 'password1', 'password2')
model = get_user_model()
The view:
class SignUpView(CreateView):
form_class = UserCreateForm
success_url = reverse_lazy('loginPage')
template_name = 'accounts/signup.html'
What should i change in order to tell django to ignore the username field for the User model?
Is a random auto-generated username a good idea to avoid this problem? If yes, how do i code it?
#Shahzeb Qureshi, i tried this:
from django.utils.translation import gettext_lazy
class UserCreateForm(UserCreationForm):
class Meta():
fields = ('first_name', 'last_name', 'username', 'departments', 'password1', 'password2')
model = get_user_model()
labels = {
'username':gettext_lazy('E-mail'),
}
A simple solution would be that you enter the email address in your username field instead of leaving it blank.
Just generate the username from email use the code is given below
email = 'punnapavankumar9#gmail.com'
username = email.split('#')[0]
Related
error:Unknown field(s) (password1, password2) specified for User
I have no idea why it doesn't work as documentation says
Documentation:
class UserCreationForm¶
A ModelForm for creating a new user.
It has three fields: username (from the user model), password1, and password2.
It verifies that password1 and password2 match, validates the password using validate_password(),
and sets the user’s password using set_password().
My forms.py
class CreateUserForm(UserCreationForm):
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
my views.py
class CreateUserView(CreateView):
model = User
form = CreateUserForm
template_name = 'registration/register.html'
fields = ['username', 'email', 'password1', 'password2 ]
class UserLoginView(LoginView):
next_page = "home.html"
']
urls.py
urlpatterns = [
path('register/', CreateUserView.as_view(), name='register'),
]
password1 and password2 are not fields of the User. You should remove these:
class CreateUserForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = User
fields = ['username', 'email']
but with this, it makes not much sense to inherit the form anyway.
Furthermore you specify the form class with form_class [Django-doc], not form, so:
class CreateUserView(CreateView):
model = User
form_class = CreateUserForm
template_name = 'registration/register.html'
I made a registration page in django but the problem is that it should not accept one email address for multiple accounts. How to resolve this issue? If you need code then let me know.
models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
def __str__(self):
return f'{self.user.username} Profile'
forms.py
class UserRegisterForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username','email','password1','password2']
No need of entering email in forms , User model already contains a email column
your registration form should look like this
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
class SignUpForm(UserCreationForm):
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email', 'password1', 'password2')
and you can simply use this line in models.py to make email Unique
User._meta.get_field('email')._unique = True
I am currently trying to improve my knowledge in coding only by using class-based views. I am currently using Django 2.0.7 and I got a bit stuck. I was trying to extend the User model in order to create accounts. This was easily done. But I can't make the passwords to get hashed. Also, when I try to type, it will not be hidden even when using PasswordInput widget. Any advice ?
#models.py
class Client(User):
name = models.CharField(max_length=30)
surname = models.CharField(max_length=50)
phone = models.CharField(max_length=15,
validators=[
RegexValidator(
regex='^[0-9+]+',
message='Not a valid phone number.',
),
])
address = models.CharField(max_length=255)
class Meta:
verbose_name = 'Client'
#forms.py
class ClientForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
fields = ('username', 'password', 'email', 'name', 'surname', 'phone', 'address')
model = Client
#views.py
class HomeView(CreateView):
template_name = 'home.html'
model = Client
form = ClientForm
fields = ('username', 'password', 'email', 'name', 'surname', 'phone', 'address')
success_url = reverse_lazy('home')
After you created your own user model without password, use the set_password() method to assign a password to your user object.
Ex: your_object.set_password(<psswd>)
import django.contrib.auth.forms as auth_forms
import models
from django import forms
from notification import models as notification
class UserCreationForm(auth_forms.UserCreationForm):
def clean_username(self):
# Since User.username is unique, this check is redundant,
# but it sets a nicer error message than the ORM. See #13147.
username = self.cleaned_data["username"]
try:
self._meta.model._default_manager.get(username=username)
except models.User.DoesNotExist:
return username
raise forms.ValidationError(
self.error_messages['duplicate_username'],
code='duplicate_username',
)
class Meta:
model = models.User
fields = ('username', 'email', 'role')
class TeacherCreationForm(UserCreationForm):
password1 = forms.CharField(
label='Password',
widget=forms.PasswordInput,
required=False
)
Instead of the above TeacherCreationForm i need something like below:
class TeacherCreationForm(UserCreationForm):
password1 = forms.CharField(
label='Password',
widget=(forms.PasswordInput, forms.HiddenInput),
required=False
)
Because i want to hide the password field, as it will automatically generated.
Try this...
class TeacherCreationForm(UserCreationForm):
class Meta:
exclude = ("password1")
I want Django to send an email to user email-address with Login details once admin adds a new user to admin site.So I tried using Django signals for that but just becoz django user registration is a two step process signals get notified in first step only and called email function without email address(which comes in second step).
My signal code:
def email_new_user(sender, **kwargs):
if kwargs["created"]: # only for new users
new_user = kwargs["instance"]
send_mail('Subject here', 'Here is the message.', 'from#example.com',['to#example.com'], fail_silently=False)
post_save.connect(email_new_user, sender=User)
So what i tried to overcome this problem.I use this code in admin.py
class UserAdmin(admin.ModelAdmin):
list_display = ('username', 'email', 'first_name', 'last_name', 'date_joined', 'last_login')
search_fields = ['username', 'email']
filter_horizontal = ('user_permissions',)
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
This makes all registration process a single step process and my signals start working and sending mail to user_id on new user addition.But the problem came after this were:
1. User password is not converted into hash and is visible while entering into form,that makes user not able to login into admin site.
2.Email field in form is not compulsory which I want to be compulsory.
Please help me :(
[EDIT]
I tried your code But I m still at same place where i was before posting this question.
the code i used in my admin.py is:
from django.contrib import admin
from mysite.naturefarms.models import *
from django.contrib.auth.models import User,Group
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from django import forms
from django.contrib.admin.views.main import *
class MyUserCreationForm(UserCreationForm):
class Meta:
model = User
fields = ('username', 'email',)
class UserAdmin(admin.ModelAdmin):
add_form = MyUserCreationForm
admin.site.unregister(User)
class MyUserAdmin(UserAdmin):
add_form = MyUserCreationForm
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('username', 'email', 'password1', 'password2')}
),
)
admin.site.register(User, MyUserAdmin)
If you look in django.contrib.auth admin.py, you'll see that the UserAdmin class specifies the add_form as UserCreationForm.
UserCreationForm only includes the 'username' field from the User model.
Since you're providing your own UserAdmin, you can just override the add_form to a custom UserCreationForm that includes the fields you need to make your signal work properly.
Hope that helps you out.
[Edit]
Here's the UserCreationForm from contrib.auth forms.py:
class UserCreationForm(forms.ModelForm):
"""
A form that creates a user, with no privileges, from the given username and password.
"""
username = forms.RegexField(label=_("Username"), max_length=30, regex=r'^[\w.#+-]+$',
help_text = _("Required. 30 characters or fewer. Letters, digits and #/./+/-/_ only."),
error_messages = {'invalid': _("This value may contain only letters, numbers and #/./+/-/_ characters.")})
password1 = forms.CharField(label=_("Password"), widget=forms.PasswordInput)
password2 = forms.CharField(label=_("Password confirmation"), widget=forms.PasswordInput,
help_text = _("Enter the same password as above, for verification."))
class Meta:
model = User
fields = ("username",)
def clean_username(self):
username = self.cleaned_data["username"]
try:
User.objects.get(username=username)
except User.DoesNotExist:
return username
raise forms.ValidationError(_("A user with that username already exists."))
def clean_password2(self):
password1 = self.cleaned_data.get("password1", "")
password2 = self.cleaned_data["password2"]
if password1 != password2:
raise forms.ValidationError(_("The two password fields didn't 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
Notice the fields = ("username",) tuple which excludes all other fields on the User model. You need something like:
class MyUserCreationForm(UserCreationForm):
class Meta:
model = User
fields = ('username', 'email',)
then you can use that as the add_form in your custom UserAdmin:
class UserAdmin(admin.ModelAdmin):
add_form = MyUserCreationForm
It's pretty late in my part of the world, but I'll see if I can get a working sample for you tomorrow.
[Edit]
Ok, here's the necessary changes you'll need to make to make this work. I've tested it using Django 1.3:
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from django import forms
admin.site.unregister(User)
class MyUserAdmin(UserAdmin):
add_form = MyUserCreationForm
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('username', 'email', 'password1', 'password2')}
),
)
admin.site.register(User, MyUserAdmin)
I didn't see that the UserAdmin had an add_fieldset property initially. That's why the email field wasn't displaying in the add form.
From this example try defining email in your custom UserCreationForm as required=True:
class MyUserCreationForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = User
fields = ('username', 'email',)