Following this :
https://simpleisbetterthancomplex.com/tutorial/2016/07/22/how-to-extend-django-user-model.html#onetoone
I am having some trouble with this call:
#receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
In their example I am guessing this works as is on the signup of a new account because the Profile in their example has all fields that can be blank and null. In my case my profile I am trying to maintain here is called:
class APOUser(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
institution = models.ForeignKey("mainpage.InstitutionMember", on_delete=models.PROTECT)
gender = models.ForeignKey("mainpage.GenderTable", on_delete=models.PROTECT)
on_site_status = models.ForeignKey("mainpage.SiteStatus", on_delete=models.PROTECT)
refer_to_as = models.TextField(max_length = 30, blank=True) #if the above is custom
room_preference = models.ForeignKey("housing.Room", on_delete=models.PROTECT)
Which has references to ultimately what will be drop downs to select form a form (populated by another table with defaults). So do I remove the #reciever and then just have the users fill out the profile separately somehow after they signup and confirm their account?
I tried to mix my signup form with the profile form... but kept getting an anonmyous user object had no attribute object apouser in the views.py when I try to mix the signup forms and profile forms:
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
profile_form = ProfileForm(request.POST, instance=request.user.apouser)
if form.is_valid() and profile_form.is_valid():
user = form.save(commit=False)
user.is_active = False
user.save()
profile_form.save()
current_site = get_current_site(request)
mail_subject = 'Activate your APO account.'
message = render_to_string('acc_active_email.html', {
'user': user,
'domain': current_site.domain,
'uid':urlsafe_base64_encode(force_bytes(user.pk)),
'token':account_activation_token.make_token(user),
})
to_email = form.cleaned_data.get('email')
email = EmailMessage(
mail_subject, message, to=[to_email]
)
email.send()
return redirect('plsactivate')
#return HttpResponse('Please confirm your email address to complete the registration')
#form.save()
#username = form.cleaned_data.get('username')
#raw_password = form.cleaned_data.get('password1')
#user = authenticate(username=username, password=raw_password)
#login(request, user)
#return redirect('/')
else:
form = SignUpForm()
profile_form = ProfileForm(instance=request.user.apouser) #<-- error here
return render(request, 'signup.html', {'form': form, 'profile_form': profile_form})
#return render(request, 'signup.html', {'form': form})
So not sure the proper way to go about what I need. I have my regular user default with the basic stuff the default django signup comes up with. THen I have the APOUser with extra stuff (usually filled out in a profile) but not sure where/how to get users to fill that out.
On signup gives me the anonymous user error
After signup doesn't let the #reciever work because none of the APOUuser stuff is filled out?
Yes, remove the receiver - although it's not the cause of this specific problem, it will cause issues as soon as you fix that
The reason for your error is as it says: since you don't have a logged in user yet, you don't have a profile either. But you don't need one; there is no need to pass an instance argument there.
What you do need to do is to set the user on the result of saving the profile form - in just the she way as you set is_active on the result of saving the user form.
So:
if request.method == 'POST':
form = SignUpForm(request.POST)
profile_form = ProfileForm(request.POST,)
if form.is_valid() and profile_form.is_valid():
user = form.save(commit=False)
user.is_active = False
user.save()
profile = profile_form.save(commit=False)
profile.user = user
profile.save()
...
else:
form = SignUpForm()
profile_form = ProfileForm()
...
Related
Here's my forms.py,
class RegistrationForm(UserCreationForm):
class Meta:
model = User
fields = [ 'username', 'first_name', 'password1', 'password2']
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
user.first_name = self.cleaned_data['first_name']
if commit:
user.save()
return user
In views.py,
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
username = request.POST.get('username')
password = request.POST.get('password1')
user = authenticate(username=username, password=password)
login(request, user)
return redirect(reverse('accounts:profile'))
else:
form = RegistrationForm()
return render(request, 'accounts/reg_form.html', {'form': form})
Right now if i'm using the same username it's raising an error which says "The view accounts.views.register didn't return an HttpResponse object. It returned None instead." How can I fix this issue?
Thank You :)
Django form by default does this for you.
You don't need specific for this.
Beacuse, default User Model provided by django doesn't take duplicate username.
May be some indentation problem
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
. . . .
else:
form = RegistrationForm()
return render(request, 'accounts/reg_form.html', {'form': form})
#^^^^^Indentation here take return statement outside else
There were a couple of other similar questions with answer but none of them fixed my problem. I am getting 'You have multiple authentication backends configured and therefore must provide the backend argument or set the backend attribute on the user' every time I try to create a new user using by sign up in Django. Here is my view:
def signupUser(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
form.save(commit=False)
username = form.cleaned_data.get('username')
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=username, password=raw_password)
form.save()
user.backend = 'django.contrib.auth.backends.ModelBackend'
login(request, user)
return redirect('home')
else:
form = SignUpForm()
return render(request, 'signup.html', {'form': form})
I had added user.backend = 'django.contrib.auth.backends.ModelBackend' in hopes of fixing the problem, but it did nothing.
My forms.py:
class SignUpForm(UserCreationForm):
email = forms.EmailField(max_length=254, help_text='Required. Inform a valid email address.')
password1=forms.CharField(help_text='Your password cant be too similar to your other personal information. Your password must contain at least 8 characters. Your password cant be a commonly used password. Your password cant be entirely numeric.', widget=forms.PasswordInput)
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
By the way, in my AUTHENTICATION_BACKENDS are 'django.contrib.auth.backends.ModelBackend' and 'allauth.account.auth_backends.AuthenticationBackend',
There are a few errors in your view function. I don't know how this worked out for you, but for the sake of clarity, I'd like to point out some of it.
Primarily, I am re-writing your view to a more suitable way,
def signupUser(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
form.save(commit=False)
username = form.cleaned_data.get('username')
raw_password = form.cleaned_data.get('password1')
form.save()
user = authenticate(username=username, password=raw_password)
if user is not None:
login(request, user)
return redirect('home')
else:
form = SignUpForm()
return render(request, 'signup.html', {'form': form})
Here, the view is meant to be for creating new users. So, you may need to call form.save() method before calling authenticate() function. Before committing to the database you are trying to authenticate the user which is not created yet. Check if your view does actually logs in any user. Then, authenticate() function returns None, if there is any mismatch in the credentials, so, check that too. Or else, Django would raise an AttributeError, when calling login() function.
I seriously doubt that your view logs in any user, because you are redirecting to same page regardless of the success of logging in. Its quite counter-intuitive, makes it harder to debug. Simply redirect to the home page when login is successful and to the login page if its not.
I realized that a user was still being created even though this error was showing up, so I guess it gets the job done. But to get rid of this error, I changed my view to this:
def signupUser(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
form.save(commit=False)
username = form.cleaned_data.get('username')
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=username, password=raw_password)
form.save()
try:
login(request, user)
except ValueError:
return redirect('home')
return redirect('home')
else:
form = SignUpForm()
return render(request, 'signup.html', {'form': form})
This strangely(at least strangely to me) worked out. A user was created and it can be properly logged into. I don't think this has any bad side effects, but I will wait to mark my solution correct just in case that there is a better solution.
I am trying to create a portable auth system that can be plugged in apps, and each different app I reimplement it in has the same issues.
1-Sometimes the user that recently logged in gets their sn in the email address field when a new user tries to register, as below
2- Sometimes a new user registers and logs out but the form will put the old user's email address and password in the appropriate fields, when of course I want the form to be blank if the user has logged out
3- always the last password used is filled in upon reload
I just want the form to completely clear itself when reloaded
How to clear form fields after a submit in Django
I have tried all 3 solutions from a similar question, I reinstantiated the from after saving the valid one, made a copy of request.POST and used that instead, and I was already redirecting to begin with. Here is my form
from django.contrib.auth.models import User
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ('username', 'email', 'password')
in views.py
def register(request):
context = RequestContext(request)
registered = False
user_form = UserForm()
if request.method == 'POST':
pDict = request.POST.copy()
form = UserForm(pDict)
if form.is_valid():
user = form.save()
user.set_password(user.password)
user.save()
user_form = UserForm()
registered = True
username = pDict['username']
password = pDict['password']
user = authenticate(username=username, password=password)
login(request, user)
#locals isn't working? won't print user
return HttpResponseRedirect('/url/')
else:
print user_form.errors
template_name = 'accounts/register.html'
user_form = UserForm()
response = TemplateResponse(request, 'accounts/register.html', locals())
return response
thank you
I'm using django built in user creation form which I extended like this
class RegistrationForm(UserCreationForm):
email = forms.EmailField(required=True, widget=forms.TextInput(attrs={'placeholder': 'E-mail address'}))
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
class Meta:
model = User
fields = ('first_name', 'last_name', 'email', 'username', 'password1', 'password2')
def clean_email(self):
email = self.cleaned_data["email"]
try:
User._default_manager.get(email=email)
except User.DoesNotExist:
return email
#raise forms.ValidationError(self.error_messages['duplicate_email'])
raise forms.ValidationError('duplicate_email')
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
user.email = self.cleaned_data['email']
if commit:
user.save()
return user
As you see I've added email validation to check if there is already user with that email (what I don't accept).
The problem is that neither that of those errors are displaying in my template and I don't know why. I've tried with {{form.field.errors}} and even with {{form.errors.values.[i]}} but nothing helps
I looked in auth.forms to check class UserCreationForm and I see that it pass errors to error_messages but I couldn't find the way to display them.
Although all validations (username check, password check, email check) work fine I'd still like to display error above field with error so that user understands why he couldn't create his account.
UPDATE
views.py
def register_user(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/accounts/register_success')
args = {}
args.update(csrf(request))
args['form'] = RegistrationForm()
return render_to_response('user_profile/register.html', args, context_instance=RequestContext(request))
I hope somebody can help me with that.
Thanks
This will work:
def register_user(request):
args = {}
args.update(csrf(request))
if request.method == 'POST':
form = RegistrationForm(request.POST)
args['form'] = form
if form.is_valid():
form.save()
return HttpResponseRedirect('/accounts/register_success')
else:
args['form'] = RegistrationForm()
return render_to_response('user_profile/register.html', args, context_instance=RequestContext(request))
The problem with your code was that you was passing an unbound form instance to your template all the time, so you was just overwriting any occured errors.
Look here for a reference: docs
If you are looking at more efficient solution then you should try my below code in views.py file.
Your forms.py code will be same. But it is leakage of validation of password.
# to register auth user
class register_user(View):
template1 = "app_name/register.html" # define templates
template2 = "app_name/login.html"
def get(self, request): # get method
form = RegistrationForm()
return render(request, self.template1, locals())
def post(self, request): # post method
form = RegistrationForm(request.POST) # create form object
if form.is_valid():
print "Form is validated"
user_data = form.save(commit=False)
user_data.save()
return render(request, self.template2, locals())
else:
print "with error"
return render(request, self.template1, locals())
I hope this will help. I'm still working on good practice of Django.
Ok, I know this is a silly question but I am blocked and I can't figure out what to do.
I have searched on google and stackoverflow but did not found any answer :
I tried this :
Adding custom fields to users in django
Django - Create user profile on user creation
https://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users
My model is the following :
class UserProfile(models.Model):
user = models.OneToOneField(User)
quota = models.IntegerField(null = True)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
post_save.connect(create_user_profile, sender=User)
And my view for user registration is the following :
def register(request):
if request.method == 'POST': # If the form has been submitted...
form = RegistrationForm(request.POST) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
# Process the data in form.cleaned_data
cd = form.cleaned_data
#Then we create the user
user = User.objects.create_user(cd['username'],cd["email"],cd["password1"])
user.get_profil().quota = 20
user.save()
return HttpResponseRedirect('')
else:
form = RegistrationForm() # An unbound form
return render(request, 'registration_form.html', {'form': form,})
The line that launches an InternalError is :
user = User.objects.create_user(cd['username'],cd["email"],cd["password1"])
And the error is :
InternalError at /register/
current transaction is aborted, commands ignored until end of transaction block
Thank you for your help
user = User.objects.create_user(username=form.cleaned_data['username'],
password=form.cleaned_data['password'],
email=form.cleaned_data['email'])
user.is_active = True
user.save()