Django extending user with userprofile (error: User has no profile.) - python

someone can told me, why this code don't working?
I'm trying to create a registration form for users.
I'm getting an error
"RelatedObjectDoesNotExist at /signup/client/2/ User has no profile."
views.py
if request.POST:
user_form = UserCreationForm(request.POST)
profile_form = ProfileForm(request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
user.profile.city="WW"
user.profile.phone="32323"
user.profile.save()
forms.py
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ('first_name', 'last_name', 'email')
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = ( 'city', 'phone')
html file
<h2>Sign up</h2>
<form method="post">
{% csrf_token %}
{{ user_form.as_p }}
{{ profile_form.as_p }}
<button type="submit">Sign up</button>
models.py
from __future__ import unicode_literals
from django.contrib.auth.models import User
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
city = models.TextField(max_length = 50)
phone = models.TextField(max_length = 12)

You need to create a profile, it does not get created when you save user_form
user_form = UserCreationForm(request.POST)
profile_form = ProfileForm(request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
Profile.objects.create(**{
'city':"WW", 'phone': '32323', 'user': user
})
# ^^^^^^

You should add the following line to the script:
profile = Profile.objects.create(user=request.user)

I believe this code is referred from 'Django by Examples'. If so, Go to your application admin Site and add a profile manually under profile account and run the server again. This will solve the issue.

The best and easiest thing to do here while in the development is:
in the terminal create another superuser -$ python manage.py createsuperuser
login in the admin page with the new credentials
Delete the old admin or any user that may have been created before the userprofile
models were created

Related

Django - After Register, Data Should Go To 2 Different Tables (Customer & User)

I am creating an e-commerce website where people can choose to login or not but still the can order and checkout (even if you are an AnonymousUser or Guest user). Now, I am making a login and register form in my website. The login form works and looks good but the register form wasn't working and throwing an error that said "RelatedObjectDoesNotExist at / User has no customer."
I think the reason is that when I register, it only makes a User in database but didn't register anything in the Customer table (which consists Name and Email). How can I register a Customer and User at the same time when I hit the "Submit" button? And how can I make that specific User have "Staff status" only and cannot make changes in the Admin site?
Also, I want to add new fields in the Register form for Name and Email that will go directly to the Customer table. I tried to do this one but it doesn't work and throwed and error that says "django.core.exceptions.FieldError: Unknown field(s) (name) specified for User".
Here's what I did:
from django.forms import ModelForm
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from .models import *
class CustomUserCreationForm(UserCreationForm):
name = models.CharField(max_length=200, null=True)
email = models.CharField(max_length=200)
class Meta:
model = User
fields = ['username', 'name', 'email', 'password1', 'password2']
SUMMARY:
I want to add extra fields in the Register form called Name and Email. Then after clicking the Register form, I want create User and Customer at the same time. But the User should only have "Staff status" and cannot make changes in the Admin site. And the Name and Email field should go to Customer Table with the User I've created.
Here's the screenshot of my Register form:
Here's my forms.py file:
from django.forms import ModelForm
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class CustomUserCreationForm(UserCreationForm):
class Meta:
model = User
fields = ['username', 'password1', 'password2']
def __init__(self, *args, **kwargs):
super(CustomUserCreationForm, self).__init__(*args, **kwargs)
self.fields['username'].widget.attrs.update({'class':'form-control','placeholder':'Enter Username'})
self.fields['password1'].widget.attrs.update({'class':'form-control','placeholder':'Enter Password'})
self.fields['password2'].widget.attrs.update({'class':'form-control','placeholder':'Confirm Password'})
Here's my views.py file:
def loginUser(request):
page = 'login'
if request.method == "POST":
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
print('USER:', user)
if user is not None:
login(request, user)
return redirect('/')
return render(request, 'store/login_register.html', {'page': page})
def logoutUser(request):
logout(request)
return redirect('/')
def registerUser(request):
page = 'register'
form = CustomUserCreationForm()
if request.method == "POST":
form = CustomUserCreationForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
user.save()
user = authenticate(request, username=user.username, password=request.POST['password1'])
if user is not None:
login(request, user)
return redirect('/')
context = {'form': form, 'page': page}
return render(request, 'store/login_register.html', context)
Here's my models.py file:
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Customer(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True)
name = models.CharField(max_length=200, null=True)
email = models.CharField(max_length=200)
def __str__(self):
return self.name
Here's my register.html file:
<form class="form" method="POST">
{% csrf_token %}
<h2> REGISTER </h2>
<h4> Create your account now! </h4>
<br />
{% for field in form %}
<div class="mb-3">
<label for="exampleInputPassword1" class="form-label">{{field.label}}:</label>
{{field}}
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">Submit</button>
<br />
<p> Already have an account? Login here </p>
</form>

Why does this work?? Class Meta, model = User

Can someone please explain this?? I'm in the process of trying my first post-tutorial project.
I've made a model called Profile with 4 attributes (given_name, surname, bio, image). I've made a form called ProfileForm which inherits from UserCreationForm and i've added the 4 attributes of my model into the form as form attributes.
MY Question is:
Why does it only work like this
class Meta:
model = User
This is my models.py file
class Profile(models.Model):
given_name = models.CharField(max_length=255)
surname = models.CharField(max_length=255)
bio = models.TextField(blank=True, null=True)
image = models.ImageField(upload_to='uploads/', blank=True, null=True)
def __str__(self):
return self.given_name
class Meta:
ordering = ['given_name']
This is my forms.py file
class ProfileForm(UserCreationForm):
firstName = forms.CharField(max_length=255)
lastName = forms.CharField(max_length=255)
bio = forms.CharField(widget=forms.Textarea)
image = forms.ImageField()
class Meta:
model = User
fields = ['firstName', 'lastName', 'username', 'password1', 'password2', 'bio', 'image']
This is my views.py file
def sign_up_view(request):
if request.method == "POST":
form = ProfileForm(request.POST, request.FILES)
if form.is_valid():
user = form.save()
login(request, user)
profile = Profile.objects.create(
given_name=form.cleaned_data['firstName'],
surname = form.cleaned_data['lastName'],
bio = form.cleaned_data['bio'],
image = form.cleaned_data['image'])
return redirect('home')
else:
form = ProfileForm()
return render(request, 'core/sign_up.html', {"form": form})
This is my admin page for a profile.
This is my admin page for a User
Note : I'm able to achieve my desired outcome, but I'm having trouble in understanding how its working.
**Also if i wanted to link the Profile model with the User such that, if the User is deleted in admin then the respective profile would also get deleted??
It only works with model = User, because your fields, like username, etc. are fields of the User model, not of the Profile model.
What you can do is process the view with two forms. We thus make a form for the Profile model, and use the UserCreationForm for the User.
Furthermore the Profile needs to link to the user model, such that it is clear what Profile belongs to what user. We thus add a ForeignKey with:
from django.conf import settings
class Profile(models.Model):
# &vellip;
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
editable=False
)
# &vellip;
then we can define a Profile form with:
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = '__all__'
then we can work with two forms, the view looks like:
from django.contrib.auth.forms import UserCreationForm
def sign_up_view(request):
if request.method == 'POST':
user_form = UserCreationForm(request.POST, request.FILES)
profile_form = ProfileForm(request.POST, request.FILES, prefix='profile')
if user_form.is_valid() and profile_form.is_valid():
user = form.save()
profile_form.instance.user = user
profile_form.save()
login(request, user)
return redirect('home')
else:
user_form = UserCreationForm()
profile_form = ProfileForm(prefix='profile')
context = {'user_form': user_form, 'profile_form': profile_form}
return render(request, 'core/sign_up.html', context)
and in the template render it with:
<form action="{% url 'name-of-the-signup-view' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ user_form }}
{{ profile_form }}
</form>
we thus use two Django forms in the same HTML form, and prefix the ProfileForm with profile for the input fields.

Is there way to confirm user email when user change his email inside his profile - django

I have an option that allows a user to change email in his profile but without confirming a new email so when he enters a new email I want activate the email to save it in his profile, how to add confirm
I am using UserCreationForm
is there 3rd party app i can use it ? (my django version is 2.2)
models.py :
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
email_confirmed = models.BooleanField(default=False)
#receiver(post_save, sender=User)
def update_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
instance.profile.save()
my code | forms.py :
# Profile Form
class EmailChangeForm(forms.ModelForm):
email = forms.EmailField(required=True,label='Email',widget=forms.EmailInput(attrs={'class': 'form-control center container','style': 'width:85%;text-align: center;background-color:#f6f6f6','placeholder':' Enter Your New E-mail '}) )
class Meta:
model = User
fields = [
'email',
]
def clean_email(self):
email = self.cleaned_data.get('email')
if email and User.objects.filter(email=email).count(): raise forms.ValidationError('Email is already in use, please check the email or use another email')
return email
views.py :
# Edit Profile View
class EmailChange(UpdateView):
model = User
form_class = EmailChangeForm
success_url = reverse_lazy('home')
template_name = 'user/commons/EmailChange.html'
def get_object(self, queryset=None):
return self.request.user
urls.py :
from django.urls import path
from blog_app.views import SignUpView, ProfileView, ActivateAccount,EmailChange
urlpatterns = [
path('profile/change-email/me/', EmailChange.as_view(), name='emailchange'),
]
html page :
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" class="fadeIn fourth" style="background-color:#7952b3" value=" change ">
</form>
what is the next step will be to add activation when the user adds a new email?

Create a staff user in django

I want to create a signup system with django .
and I create a user with a class that is on forms.py and extends UserCreationForm .
and I run server and fill the form and user is created but I cannot login with this user on the login page of django and it says me the user is not a staff user
how to make my user staff ???
forms.py :
class ModelNameForm(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 (ModelNameForm , 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):
form = ModelNameForm (request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/thanks')
else:
form = ModelNameForm()
args = {'form' : form }
return render(request , 'signup.html' , args)
you can do that by adding
user.is_staff = True in your the model form save method
You can add user.is_staff = True in your ModelForm save method. But this is not safe because all new users will became staff users and they will have access to your admin page.
More safe way is create superuser and give access to another users manually in your admin. You can create superuser by this:
python manage.py createsuperuser
And after this you can to login with your superuser credentials to your django admin page. If need to give staff rights to users you have to open your admin page with superuser account, then click Users and find user. Open this user and click checkbox is staff.
I added user.is_staff = True in a separate form for creating staff users and I used another form for creating regular users. So that I am able to prevent all new users from becoming staff users.
I am using custom user model.
Following is the code for creating staff users:
forms.py
class StaffCreationForm(forms.ModelForm):
"""
A Custom form for creating new staffs.
"""
class Meta:
model = get_user_model()
fields = ['name','phone']
views.py
def register_staff(request):
if request.user.is_superuser: # giving access to superuser only.
form = StaffCreationForm()
if request.method == 'POST':
form = StaffCreationForm(request.POST)
if form.is_valid():
phone = form.cleaned_data.get('phone') # obtaining data from fields.
name = form.cleaned_data.get('name')
user = User.objects.create_user(phone = phone, name = name) # assigning obtained data to model variables and save user as staff.
user.is_staff=True
user.save()
message = ('%(name)s is added as a staff.') % {'name': name} # flash message for successful registration.
messages.success(request, message)
return redirect('staff')
context = {'form':form}
return render(request, 'registration/add_staff.html', context)
else:
return render(request, 'error-404.html')
urls.py
urlpatterns = [
path('add_staff', register_staff, name = 'staff'),
]
add_staff.html
<form method="POST">
{% csrf_token %}
{% for message in messages %}
{% if message.tags %}
<div class="alert alert-{{message.tags}}">
{{message}}
</div>
{% endif %}
{% endfor %}
{{ form|crispy }}
<input type="submit" class="btn btn-primary" value="Add Staff">
</form>

login form keeps telling my username already exists django

So I am trying to make a login form for a django website using a forms.py file to generate a form in my html. I have already made a registration form using the same methods and that works fine but for some reason my login form keeps working like a registration form and saying that my username already exists. i assume it is just a litle mistake but I can't figure out what it is exactly.
forms.py
from django.contrib.auth.models import User
from django import forms
class LoginForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = User
fields = ['username', 'password']
models.py
class LoginFormView(View):
form_class = LoginForm
template_name = 'intranet/login_form.html'
def get(self, request):
form = self.form_class(None)
return render(request,self.template_name,{'form': form})
def post(self,request):
form = self.form_class(request.POST)
if form.is_valid():
username = request.POST.get['username']
password = request.POST.get['password']
user = authenticate(username=username,password=password)
if user is not None:
if user.is_active:
login(request,user)
return redirect('werknemers_list')
return render(request, self.template_name, {'form': form})
login_form.html
<h1>Log in</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="log in" />
</form>
urls.py
from django.conf.urls import url
from intranet import views
urlpatterns = [
url(r'^$', views.LoginFormView.as_view(), name='login'),
url(r'^registreer$', views.UserFormView.as_view(), name='registreer')]
You shouldn't use a ModelForm for this. That will always call the model validation, which in this case checks for username uniqueness.
Use a standard Form class instead.

Categories