Trying to hide a view to create a restaurant from anyone other than a restaurant Owner.
Used examples shown using groups and testing whether a user is in that group or not but nothing seems to work.
views.py
def is_owner(user):
if user.objects.filter(name="Owner").exists():
return True
class CreateRestaurantView(generic.CreateView):
form_class = CreateRestaurantForm
success_url = reverse_lazy('home')
template_name = 'signup.html'
#login_required
def create_restaurant(request):
if is_owner == True:
if request.method == "POST":
form = CreateRestaurantForm(request.POST)
if form.is_valid():
restaurant = form.save(commit=False)
restaurant.Restaurant_Owner = request.user
restaurant.save()
return redirect('restaurant_list')
else:
form = CreateRestaurantForm()
return render(request, 'create_restaurant.html', {'form': form})
else:
return render(request, 'home.html')
forms.py
signup form for Owners
class OwnerCreationForm(forms.ModelForm):
error_messages = {
'password_mismatch': _("The two password fields didn't match."),
}
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_password2(self):
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError(
self.error_messages['password_mismatch'],
code='password_mismatch',
)
return password2
def save(self, commit=True):
user = super(OwnerCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
group = Group.objects.get(name='Owner')
user.groups.add(group)
return user
I'm trying to get the view to show the create_restaurant form when a user belongs to the "Owner" group but the function to test (is_owner) does not work and is always false.
First of all, you are defined is_owner as function, so, you should call it as is_owner(any_user_object)
Second thing is, to search over the Group, it should be as
user.groups.filter(name="Owner").exists()
code snippet
def is_owner(user):
return user.groups.filter(name="Owner").exists()
#login_required
def create_restaurant(request):
if is_owner(request.user) == True:
if request.method == "POST":
form = CreateRestaurantForm(request.POST)
if form.is_valid():
restaurant = form.save(commit=False)
restaurant.Restaurant_Owner = request.user
restaurant.save()
return redirect('restaurant_list')
else:
form = CreateRestaurantForm()
return render(request, 'create_restaurant.html', {'form': form})
else:
return render(request, 'home.html')
UPDATE-1
change the save() method of OwnerCreationForm as below
class OwnerCreationForm(forms.ModelForm):
# your other code
def save(self, commit=True):
user = super(OwnerCreationForm, self).save(commit=True)
user.set_password(self.cleaned_data["password1"])
if not user.groups.filter(name="Owner").exists():
group = Group.objects.get(name='Owner')
user.groups.add(group)
user.save()
return user
Related
forms.py
class UserForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = User
fields = ('username','email','password1','password2')
def save(self,commit=True):
user = super(UserForm,self).save(commit=False)
user.set_password = self.cleaned_data['password1']
user.email = self.cleaned_data['email']
if commit:
user.save()
views.py
def register_view(request):
form = UserForm()
if request.method == 'POST':
form = UserForm(request.POST)
if form.is_valid():
user = form.save()
customer_group = Group.objects.filter(name='CUSTOMER').exists()
if customer_group:
Group.objects.get(name='CUSTOMER').user_set.add(user)
else:
Group.objects.create(name='CUSTOMER')
Group.objects.get(name='CUSTOMER').user_set.add(user)
messages.success(request,'註冊成功! 請按指示登入!')
return redirect('login')
else:
messages.error(request,'註冊無效! 請再試過!')
context = {'form':form}
return render(request,'customer/register.html',context)
When I try to register a new user, the form can be successfully saved and the group CUSTOMER can be added but I have a problem if I want to add that user to the group so are there any methods in order to add the user to the group automatically after that user had registered a new account along with the User model?
As #Iain Shelvington says, the form.save() method should return the user object. But there is no need to override the save() method: the UserCreationForm already does that.
class UserForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = User
fields = ('username','email')
# no save method
In the view you can simplify the logic to:
def register_view(request):
form = UserForm()
if request.method == 'POST':
form = UserForm(request.POST)
if form.is_valid():
user = form.save()
customer_group, __ = Group.objects.get_or_create(name='CUSTOMER')
customer_group.user_set.add(user)
messages.success(request,'註冊成功! 請按指示登入!')
return redirect('login')
else:
messages.error(request,'註冊無效! 請再試過!')
context = {'form':form}
return render(request,'customer/register.html',context)
Django Version = 2.2.2.
Does it not make sense to take out the def clean(self) method from class LoginForm(form.ModelForm)
class LoginForm(forms.ModelForm):
password = forms.CharField(label='Password', widget=forms.PasswordInput)
class Meta:
model = Account
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):
raise forms.ValidationError('Invalid login')
and put it inside the view function for login:
def login_screen_view(request):
context = {}
if request.POST:
form = LoginForm(request.POST)
if form.is_valid():
email = request.POST['email']
password = request.POST['password']
user = authenticate(email=email, password=password)
if user:
login(request, user)
return redirect('home')
else:
form = LoginForm()
context['login_form'] = form
return render(request, 'account/login.html', context)
So that the above two blocks of code becomes now this:
class LoginForm(forms.ModelForm):
password = forms.CharField(label='Password', widget=forms.PasswordInput)
class Meta:
model = Account
fields = ['email', 'password']
def login_screen_view(request):
context = {}
if request.POST:
form = LoginForm(request.POST)
if form.is_valid():
email = request.POST['email']
password = request.POST['password']
user = authenticate(email=email, password=password)
if user:
login(request, user)
return redirect('home')
else:
raise forms.ValidationError('Invalid login') #i added this line
else:
form = LoginForm()
context['login_form'] = form
return render(request, 'account/login.html', context)
The reason why I say all this is because in the def clean(self) method aren't you basically checking if the form is valid? We also check if the form is valid in the view as well. So why repeat the logic? Then if we cannot authenticate the user we raise a ValidationError which I think can be added in the view definition.
I am doing a basic user creation using the built-in UserCreationForm in Django.
Here is my views.py:
def user_register(request):
if request.method == "POST":
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data['username']
raw_password = form.cleaned_data['password1']
user = User.objects.create_user(username=username)
if raw_password:
user.set_password(raw_password)
else:
user.set_unusable_password()
user.save()
return redirect('home')
else:
form = UserCreationForm()
return render(request, 'registration/register.html', {'form': form})
However, after registering a user and being redirected to home, the number of Users seen in my Admin page has not changed; no User has been created.
Any idea what I am doing wrong here?
Try:
from django.contrib.auth import login, authenticate
from django.contrib.auth.forms import UserCreationForm
from django.shortcuts import render, redirect
from django.contrib.auth.models import User
def user_register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password1']
user=User.objects.create_user(username=username, password=password)
user.save()
#Below 2 lines, if you want user to get logged in
user = authenticate(username=username, password=password)
login(request, user)
return redirect('home')
else:
form = UserCreationForm()
return render(request, 'registration/register.html', {'form': form})
don't know why you can redirected to home with no use create,but you should deal with the situation form is not vaild and remove form.save() from form.is_valid() block like:
form = UserCreationForm(request.POST)
if form.is_valid():
# remove form.save()
....
else:
print(form.errors.as_text())
return render(request, 'registration/register.html', {'form': form})
or override save method for UserCreationForm like i do:
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
the full demo is:
from django.views.generic import *
class RegisterView(FormView):
template_name = 'registration/register.html'
form_class = UserCreationForm
success_url = reverse_lazy('home')
def form_valid(self, form):
form.save()
return HttpResponseRedirect(self.get_success_url())
forms.py
class UserCreationForm(forms.ModelForm):
error_messages = {
'duplicate_username': u"duplicate username",
'password_mismatch': u"password_mismatch",
'duplicate_email': u'duplicate email'
}
username = forms.RegexField(
max_length=30,
regex=r'^[\w.#+-]+$',
error_messages={
'invalid': u"onlay can contaions symbol #/./+/-/_",
'required': u"required"
},
label='username'
)
email = forms.EmailField(
error_messages={
'invalid': u"email invalid",
'required': u'required'},
label='email'
)
password1 = forms.CharField(
widget=forms.PasswordInput,
error_messages={
'required': u"required"
},
label='password1 '
)
password2 = forms.CharField(
widget=forms.PasswordInput,
error_messages={
'required': u"required"
},
label='password2'
)
def __init__(self, *args, **kwargs):
super(UserCreationForm, self).__init__(*args, **kwargs)
self.fields['username'].widget.attrs.update({'class': 'form-control'})
self.fields['email'].widget.attrs.update({'class': 'form-control'})
self.fields['password1'].widget.attrs.update({'class': 'form-control'})
self.fields['password2'].widget.attrs.update({'class': 'form-control'})
class Meta:
model = User
fields = ("username", "email")
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:
User.objects.get(username=username)
except User.DoesNotExist:
return username
raise forms.ValidationError(
self.error_messages["duplicate_username"]
)
def clean_password2(self):
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError(
self.error_messages["password_mismatch"]
)
password_validation.validate_password(password2)
return password2
def clean_email(self):
email = self.cleaned_data["email"]
try:
User.objects.get(email=email)
except User.DoesNotExist:
return email
raise forms.ValidationError(
self.error_messages["duplicate_email"]
)
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
I don't know why you are saving the object so many times. As documented here, when calling form.save() in a UserCreationForm instance, Django will create the user, set the password (which comes from the password1 field), save the instance in the database and return the user for you. So User.objects.create_user and user.save() will only save the object again.
Parhaps it's not the solution for your problem but have you tried just like this:
def user_register(request):
form = UserCreationForm()
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
user = form.save()
# if you want to authenticate your user or log any info, do it here
return redirect('home')
# I wouldn't use the else statement here, so if there are errors in the form you probably want the same template to be rendered, in order to show the form errors to your user.
return render(request, 'registration/register.html', {'form': form})
Thanks for everybody that helped me think this through. It seems, of course, the answer was much simpler than I thought. My new user_register view is:
from django.contrib.auth.forms import UserCreationForm
from django.shortcuts import render, redirect
def user_register(request):
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
return redirect('home')
else:
return render(request, 'registration/register.html', {'form': form})
I am able to create a user from shell by importing the custom user model but when I apply the same method after submitting the form, the user is not created.
Below are the codes of my custom user model, UserCreationForm and view.
//model.py
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
I have extended the AbstractBaseUser as suggested in the Django docs to create a custom user model.
//forms.py
class UserCreationForm(forms.ModelForm):
"""A form for creating new users. Includes all the required
fields, plus a repeated password."""
email = forms.EmailField(
label='Email',
widget=forms.EmailInput,
required=True,
)
password1 = forms.CharField(
label='Password',
widget=forms.PasswordInput,
required=True
)
password2 = forms.CharField(
label='Password confirmation',
widget=forms.PasswordInput,
required=True
)
class Meta:
model = MyUser
fields = ('email', 'password1', 'password2')
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 and password1 != password2:
raise forms.ValidationError("Passwords don't match")
return password2
def save(self, commit=True):
# Save the provided password in hashed format
user = super(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
Am I doing incorrect form processing. The form.save() method didn't work out for me. Also the docs don't discuss user registration thoroughly. I don't know why.
//views.py
def login(request):
if request.method == 'POST':
form = AuthenticationForm(data=request.POST)
if form.is_valid():
user = authenticate(email=request.POST['email'],
password=request.POST['password'])
if user is not None:
if user.is_active:
django_login(request, user)
return redirect('/home/', permanent=True)
else:
form = AuthenticationForm()
return render(request, 'buymeauth/login.html', {'form': form})
def register(request):
user = request.user
if request.method == 'POST':
form = UserCreationForm(data=request.POST)
if form.is_valid():
my_user = MyUser(user.email, user.password)
my_user.save()
return redirect('/home/', permanent=True)
else:
form = UserCreationForm()
return render(request, 'buymeauth/register.html', {'form': form})
I am new to Django but not particularly to web development. I have some exposure with MEAN but I am finding Django difficult. I have been stuck with this authentication and authorisation stuff for 5 days now.
def register(request):
# this is the logged-in user
user = request.user
if request.method == 'POST':
# this is the form with the submitted data
form = UserCreationForm(data=request.POST)
if form.is_valid():
# the submitted data is correct
my_user = MyUser(user.email, user.password)
# this is a new user with the same email and password
# than the currently logged-in user. It's not what you want
# and it won't work if you're not logged-in
my_user.save()
return redirect('/home/', permanent=True)
else:
form = UserCreationForm()
return render(request, 'buymeauth/register.html', {'form': form})
Instead you probably want this:
if request.method == 'POST':
form = UserCreationForm(data=request.POST)
if form.is_valid():
user = form.save(commit=False)
user.is_active = True # if you want to skip email validation
user.email = User.objects.normalize_email(user.email)
user.save()
I'm trying to figure out how to allow users to change their profile. I have a Users extended by User Profile (OneToOne).
I was thinking about changing registration view, prefill user's attributes and allow him to change them. But it is not probably the good way.
Could you give me a hint how to do that?
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')
def clean(self):
password1 = self.cleaned_data.get('password1')
password2 = self.cleaned_data.get('password2')
if password1 and password1 != password2:
raise forms.ValidationError("Passwords don't match")
return self.cleaned_data
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('telephone','marital_status','how_do_you_know_about_us')
MODELS.PY
class UserProfile(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
# ATRIBUTY KTORE BUDE MAT KAZDY
telephone = models.CharField(max_length=40,null=True)
HOW_DO_YOU_KNOW_ABOUT_US_CHOICES = (
('coincidence',u'It was coincidence'),
('relative_or_friends','From my relatives or friends'),
)
how_do_you_know_about_us = models.CharField(max_length=40, choices=HOW_DO_YOU_KNOW_ABOUT_US_CHOICES, null=True)
MARITAL_STATUS_CHOICES = (
('single','Single'),
('married','Married'),
('separated','Separated'),
('divorced','Divorced'),
('widowed','Widowed'),
)
marital_status = models.CharField(max_length=40, choices=MARITAL_STATUS_CHOICES, null=True)
# OD KIAL STE SA O NAS DOZVEDELI
# A STAV
def __unicode__(self):
return '{} {}'.format(self.user.first_name,self.user.last_name)
def __str__(self):
return '{} {}'.format(self.user.first_name,self.user.last_name)
REGISTRATION VIEW:
def register(request):
if request.method == 'POST':
user_form = UserForm(request.POST)
profile_form = UserProfileForm(request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
user.set_password(user_form.cleaned_data['password1'])
user.save()
profile = profile_form.save(commit=False)
profile.user = user
profile.save()
return register_success(request)
else:
print user_form.errors, profile_form.errors
else:
user_form = UserForm()
profile_form = UserProfileForm()
return render(request, "auth/registration/register.html",
context={'user_form': user_form, 'profile_form': profile_form})
EDIT:
This is the view I'm trying to create but it does not autofill form:
#login_required
def edit_profile(request):
myUser = request.user
user_form = UserForm(request.POST, instance=myUser)
user_profile_form = UserProfileForm(request.POST, instance=myUser)
context={'user_form': user_form,
'user_profile_form':user_profile_form}
return render(request, 'auth/profiles/my_profile.html', context=context)
In the edit_profile view you added, you're passing your forms a POST request argument. You should only be passing this argument on a POST request. So update your forms to be the following if the request is a GET request:
views.py
user_form = UserForm(instance=myUser)
user_profile_form = UserProfileForm(instance=myUser)
forms.py
# Something like this will only save password if data is entered in one of the password fields
def clean(self):
cleaned_data = super(UserForm, self).clean()
password1 = cleaned_data.get('password1', None)
password2 = cleaned_data.get('password2', None)
old_password = cleaned_data.get('old_password', None)
if password1 or password2:
if password1 != password2:
self._errors['password1'] = 'New Password and Confirm New Password must match.'
self._errors['password2'] = 'New Password and Confirm New Password must match.'
if not self.user.check_password(old_password):
self._errors['old_password'] = 'Your old password was entered incorrectly.'
return cleaned_data
def save(self, request):
user = self.user
if self.cleaned_data.get('password1', None):
user.set_password(self.cleaned_data.get('password1'))
update_session_auth_hash(request, user)
user.save()
return user
For your choices issue, you can specify choices as an argument when specifying widgets for the field.