Django having problem in adding user to specific group - python

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)

Related

how to register this offline wallet in sign up?

here is my view.py
from models import Balance
def profile(request):
user = Balance.objects.get(user=request.user)
return render(request,'profile.html',{"balance":user.balance})
and created model here
class Balance(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
balance = models.IntegerField(default=0)
def __str__(self):
return self.user.username
here is my registration and i think i have made mistake here:
#unauthenticated_user
def register(request):
form = CreateUser()
if request.method == 'POST':
form = CreateUser(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
instance = Balance(user=request.user, balance=0)
instance.save()
messages.success(request, "Congrats !!" + username + "now you are member of the society")
return redirect('login')
context = {'form': form}
return render(request, "register.html", context)
I am able fetch the balance of the user in from the database at the time of showing the profile but not able save it into database while registration. As erorr returns:
ValueError at /register/
Cannot assign "<SimpleLazyObject: <django.contrib.auth.models.AnonymousUser object at 0x7f98c64caa60>>": "Balance.user" must be a "User" instance
Your user is not signed in when you write this line:
instance = Balance(user=request.user, balance=0)
I assume your form CreateUser works properly. when a form is saved it returns the created instance so you can use it instead of request.user:
user = form.save()
instance = Balance(user=user, balance=0)
instance.save()

Populate Django username field with generated username

I would like the user name field for my Django registration to populate with the following function -
def generateUsername():
username = firstname[0] + middlename[0] + lastname[0] + randomStringDigits(6) + getDateTimeStr()
return username
I am currently using the UserRegisterForm model from Django and would prefer to find away to integrate into this, however if the best option is to custom my own user model then I am happy to do this also.
views.py -
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
messages.success(request, f'Account created for {username}')
return redirect('login')
else:
form = UserRegisterForm()
return render(request, 'users/register.html', {'form': form})
forms.py -
class UserRegisterForm(UserCreationForm):
email = forms.EmailField()
firstname = forms.CharField(max_length=20)
middlename = forms.CharField(max_length=20)
lastname = forms.CharField(max_length=20)
class Meta:
model = User
fields = ['email', 'firstname', 'middlename', 'lastname']
You can set this to the user object wrapped in the form:
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
if form.is_valid():
data = form.cleaned_data
username = f"{data['firstname'][0]}{data['middlename'][0]}{data['lastname'][0]}{randomStringDigits(6)}"
form.instance.username = username
form.save()
messages.success(request, f'Account created for {username}')
return redirect('login')

How do I make a signal run only if the user created is on a specific group in Django?

I have a model Client which uses a #receiver signal to update its fields whenever a User is created, so it creates a Client profile.
class Client(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
address = models.CharField(max_length=200, verbose_name="Morada")
city = models.CharField(max_length=200, verbose_name="Cidade")
postal = models.CharField(max_length=8, validators=[RegexValidator(r'^\d{4}(-\d{3})?$')], verbose_name="Código Postal")
nif = models.CharField(max_length=9, verbose_name="NIF", validators=[RegexValidator(r'^\d{1,10}$')], unique=True, null=True)
mobile = models.CharField(max_length=9, verbose_name="Telemóvel", validators=[RegexValidator(r'^\d{1,10}$')])
def __str__(self):
return "%s %s" % (self.user.first_name, self.user.last_name)
class Meta:
verbose_name_plural = "Clientes"
#receiver(post_save, sender=User)
def update_user_profile(sender, instance, created, **kwargs):
if created:
Clients.objects.create(user=instance)
instance.clients.save()
Is there a way to only run this if the user created belongs to the Clients group? Because if a user is created in the Employees group, I don't want to create a profile.
This is the view that creates the Client in the Clients group:
#login_required(login_url='./accounts/login/')
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
user = form.save() # this creates the user with first_name, email and last_name as well!
group = Group.objects.get(name='Clients')
user.groups.add(group)
user.refresh_from_db() # load the profile instance created by the signal
user.clients.address = form.cleaned_data.get('address')
user.clients.city = form.cleaned_data.get('city')
user.clients.postal = form.cleaned_data.get('postal')
user.clients.nif = form.cleaned_data.get('nif')
user.clients.mobile = form.cleaned_data.get('mobile')
return redirect('clients')
else:
form = SignUpForm()
return render(request, 'backend/new_client.html', {'form': form})
Doing it in the view (without signal):
#login_required(login_url='./accounts/login/')
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
user = form.save()
group = Group.objects.get(name='Clients')
user.groups.add(group)
client = Client.objects.create(
user=user,
address=form.cleaned_data.get('address')
city=form.cleaned_data.get('city')
postal=form.cleaned_data.get('postal')
nif=form.cleaned_data.get('nif')
mobile=form.cleaned_data.get('mobile')
)
return redirect('clients')
else:
form = SignUpForm()
return render(request, 'backend/new_client.html', {'form': form})
Then you can choose to move all the code under user = form.save() in the form's itself (I assume it's a custom ModelForm):
# forms.py
class SignUpForm(models.Form):
# your existing code here
def save(self):
# NB if you're still using py2 you'll need
# `user = super(SignUpForm, self).save()` instead
user = super().save()
group = Group.objects.get(name='Clients')
user.groups.add(group)
cleaned_data = self.cleaned_data
client = Client.objects.create(
user=user,
address=cleaned_data.get('address')
city=cleaned_data.get('city')
postal=cleaned_data.get('postal')
nif=cleaned_data.get('nif')
mobile=cleaned_data.get('mobile')
)
return user
And your view becomes:
#login_required(login_url='./accounts/login/')
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
form.save()
return redirect('clients')
else:
form = SignUpForm()
return render(request, 'backend/new_client.html', {'form': form})
Both options are correct and functionnaly equivalent, but the second one is IMHO more maintainable - first because a form is easier to test than a view (you don't need to create a request object), and also because it encapsulate the whole domain logic in the same place (the form) instead of scattering it between the form and the view. The only downside is that you loose the ability to pass the commit=False arg to form.save(), but since this form has obviously no other purpose you wouldn't use this feature anyway.

How to add username in admin page who logged in when withdrawing an amount?

I have made a form to give an option for user to withdraw money. That data is saving in admin page but the problem is I have owner variable also, which I want that as the amount data is going to be saved in admin page the owner username should also be saved in admin, which shows who is desiring this amount?
models.py
from django.contrib.auth.models import User
class WithdrawPayment(models.Model):
payment = models.CharField(max_length=100)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
class Meta:
verbose_name_plural = 'Withdraw Payment'
views.py
#login_required
def withdraw(request):
if request.method == 'POST':
form = WithdrawBalance(request.POST, request.FILES)
if form.is_valid():
form.save()
messages.success(request, f'Your request has been submitted.')
return redirect('index')
else:
form = WithdrawBalance()
context = {'form': form}
return render(request, 'nextone/withdraw.html', context)
forms.py
class WithdrawBalance(forms.ModelForm):
class Meta:
model = WithdrawPayment
fields = ['payment']
Something like this:
#login_required
def withdraw(request):
form_class = WithdrawBalanceForm
if request.method == 'POST':
form = form_class(request.POST)
obj = form.save(commit=False)
obj.owner = request.user
obj.save()
messages.success(request, f'Your request has been submitted.')
return redirect('index')
else:
form = form_class()
context = {'form': form}
return render(request, 'nextone/withdraw.html', context)
class WithdrawBalanceForm(forms.ModelForm):
class Meta:
model = WithdrawPayment
fields = ['payment']

How do I control what authenticated users can see in Django?

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

Categories

Resources