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>
Related
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>
I have been trying to create a view that lets a user create a "profile" but if the user already has a profile then the user is redirected to page where the user can see other people's profiles(in order to see this other people's profiles, the user has to create a profile as a requirement), for doing this proces I have 2 templates, one that has a form to create the profile and other one that displays other user's profile. The error is that every user is redirected to mates-form.html even the ones that already have a profile. So far I think that the error is on the views.py file.
models.py
class Mates(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='usermates')
users_requests = models.ManyToManyField(User, related_name="users_requests")
req_bio = models.CharField(max_length=400)
req_image = models.ImageField(upload_to='requestmates_pics', null=True, blank=True, default=False)
views.py
def matesmain(request):
contents = Mates.objects.all()
if contents == request.user:
context = {
'contents': contents,
'form_mates': MatesForm(),
}
print("nice3")
return render(request, 'mates.html', context)
else:
return render(request, 'mates-form.html')
def mates(request):
if request.method == 'POST':
form_mates = MatesForm(request.POST, request.FILES)
if form_mates.is_valid():
instance = form_mates.save(commit=False)
instance.user = request.user
instance.save()
return redirect('mates-main')
print('succesfully uploded')
else:
form_mates = MatesForm()
print('didnt upload')
context = {
'form_mates': form_mates,
'contents': Mates.objects.all()
}
return render(request, 'mates-form.html', context)
forms.py
class MatesForm(forms.ModelForm):
class Meta:
model = Mates
fields = ('req_bio', 'req_image',)
exclude = ['user']
mates.html
{% if contents %}
{% for content in contents %}
Here is where the user can see other user's profiles
{% endfor %}
{% endif %}
mates-form.html
<form method="post" enctype="multipart/form-data">
{{ form_mates.as_p }}
</form>
If you have any questions or if you need to see more code please let me know in the comments, also I thought of other way for doing these removing the if statements from matesmain view and just using them on the html but that didnt work.
I suppose the user will have only one profile so Instead of ManyToOneRelation i.e. ForeignKey using OneToOneRelation with the User Model would be better.
class Mates(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='usermates')
Now while creating the profile you can check whether the user profile already exists or not like this:
def mates(request):
if Mates.objects.filter(user=request.user).exists():
return redirect('redirect_to_some_view_you_want')
if request.method == 'POST':
form_mates = MatesForm(request.POST, request.FILES)
I am trying to create a simple login page using python and django. My registration/signup is working fine and I am able to register the user. once the user is registered, while logging in the user using username and password the user is not authenticated. I am not able to find out the exact error, can anyone please guide me through this.
This is my models.py
from django.db import models
from django.contrib.auth.base_user import AbstractBaseUser
# Create your models here.
# create a model for user details with fields username, firstname, lastname,
# emial, password,
class CustomUserInfo(AbstractBaseUser):
'''
model for basic user details
returns username of the user
'''
firstname = models.CharField(max_length=50)
lastname = models.CharField(max_length=50)
username = models.CharField(max_length=50, unique=True)
email = models.EmailField()
password = models.CharField(max_length=15)
dob = models.DateField()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['firstname','lastname','username','email','password','dob']
# return the string form of the object
def __str__(self):
return self.username
This is my views.py file
from django.shortcuts import render
from django.views.generic import TemplateView, DetailView, ListView
from django.contrib.auth import login,logout,authenticate
from django.contrib.auth.decorators import login_required
from django.urls import reverse
from django.http import HttpResponse,HttpResponseRedirect
from custom_login_app.forms import CustomUserInfoForm
from custom_login_app import models
# Create your views here.
# about template view
class AboutView(TemplateView):
template_name = 'about.html'
# user profile detail page
class ProfileDetailView(DetailView):
context_object_name = 'user_detail'
model = models.CustomUserInfo
template_name = 'userinfo_detail.html'
# home page view
def index(request):
return render(request,'index.html')
# logout view
#login_required
def customlogout(request):
logout(request)
return HttpResponseRedirect(reverse('index'))
# registration view
def registration(request):
# bool variable to chcek the user is registered
registered = False
# check the user has poste the data through the form
if request.method == 'POST':
# create a form object
user_form = CustomUserInfoForm(data=request.POST)
# check if the form is valid
if user_form.is_valid():
# save the entered details to the form object
user = user_form.save()
# validate and set the password for hashing
user.set_password(user.password)
# save the details
user.save()
registered = True
else:
print(user_form.errors)
else:
# display the registration form
user_form = CustomUserInfoForm()
return render(request,'registration.html',{'user_form':user_form,
'registered':registered})
# login view
def customlogin(request):
# check if the user has posted the details
if request.method == 'POST':
# Grab the entered username and password
username = request.POST.get('username')
password = request.POST.get('password')
# authenticate the entered details using built in django authenticate method
user = authenticate(username=username, password=password)
# if the user is authenticated, user is available
if user:
# check is the user active
if user.is_active:
# login the user with the entered details using builtin login module
login(request,user)
# Once logged in, redirect to home page
return HttpResponseRedirect(reverse('index'))
# if user account is not active, resturn a simple HttpResponse
else:
return HttpResponse('Your account is not active')
else:
# if the user is invalid or has entered invalid details
print("Someone tried to login with invalid details")
print("Username:{}, Password:{}".format(username,password))
return HttpResponse("Invalid Credentials, Please try again!")
else:
# if the user has not entered the login details
return render(request,'login.html',{})
My login.html is
{% extends 'base.html' %}
{% block content %}
<div class="login">
<p class="logintext">Please Login</p>
<form class="form-group loginform" action="{% url 'user_login' %}" method="POST">
{% csrf_token %}
<div class="usr">
<label class="usr_label" for="username">Username</label>
<input class="usr_input" type="text" name="username" placeholder="Enter Username"><br/>
</div>
<div class="passwd">
<label class="passwd_label" for="password">Password</label>
<input class="passwrd_input" type="password" name="password" placeholder="Enter Password"<br/>
</div>
<div class="buttons">
<input class="btn btn-dark login-btn" type="submit" value="Login">
<a class="btn btn-dark register-btn" href="{% url 'registration' %}">New User?</a>
</div>
</form>
</div>
{% endblock %}
Any answers will be appreciated.
Thanks in advance
I think you're setting the password incorrectly when you create the user. Assuming the field name is password, it should be:
user.set_password(form.cleaned_data['password'])
I'm not sure what user.is_active defaults to but, since I don't see it being set in the code you provided, it could be that you never reach the login function because user.is_active is False
I am trying to save users IP address in my extended profile model. The goal is to make this a hidden field. Currently, I can debug by printing the IP address to the console. The issue arises when I try and save the info.
views.py
def index(request):
#request.session.flush()
if request.user.is_authenticated:
return redirect('ve:dashboard')
elif request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
user.refresh_from_db() # Load the profile instance created by the Signal
user.profile.birth_date = form.cleaned_data.get('birth_date')
user.ipaddress = get_ip(request)
print(user.ipaddress)
user.save()
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=user.username, password=raw_password)
login(request, user)
return redirect('ve:dashboard')
else:
form = RegistrationForm()
return render(request, 'index.html', {'form': form})
forms.py
class RegistrationForm(UserCreationForm):
# birth_date = forms.DateField(help_text='Required. Format: YYYY-MM-DD')
birth_date = forms.DateField(widget=SelectDateWidget(years=range(1999, 1910, -1)))
#ipaddress = forms.IntegerField(widget=forms.HiddenInput(), required=False)
class Meta:
model = User
fields = ('username', 'email', 'birth_date', 'password1', 'password2',)
exclude = ['ipaddress',]
index.html
<form method="post">
{% csrf_token %}
{% for field in form %}
<p class="text-left">
{{ field.label_tag }}<br>
{{ field }}
{% for error in field.errors %}
<p style="color: red">{{ error }}</p>
{% endfor %}
</p>
{% endfor %}
<button type="submit">Sign up</button>
</form>
models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
...
ipaddress = models.CharField(default="0.0.0.0", max_length=30)
This form was working fine before I tried adding the ipaddress field. I've been trying several versions and sometimes the form creates a new user but the ipaddress is not saved..
The current code above gives me there error on POST:
DoesNotExist at / User matching query does not exist. Due to this line "user.refresh_from_db() # Load the profile instance created by the Signal"
From the docs:
This save() method accepts an optional commit keyword argument, which accepts either True or False. If you call save() with commit=False, then it will return an object that hasn’t yet been saved to the database.
So since you're passing commit in as False you're getting an unsaved instance back. Attempting to call refresh_from_db on an object that doesn't actually exist in the database will fail, as it is clearly doing. If the instance to a model has no id then refresh_from_db will fail when called on it.
As for the continuing inability to save IP address, I noticed that your form meta has the model set to the User object. The default Django User object has no ip address. I see that in the model file you linked you have a Profile model that does have an IP Address so in that case I think you simply have your form set up wrong. Or you need to handle the request differently.
Form change
Currently your form is attempting to create/modify a Django User model. Unless you've made a custom User model that you didn't show, this user model will not have an ipaddress as a field in the database meaning even if you set user.ipaddress = <address> and then save the user, the ip address won't persist outside of the current scope since all you did was declare a new variable for the user instance.
If you change your form to point at your Profile model you'll be able to save the address using profile.ipaddress = <address> and save it successfully. But you will have to update your template since by default it will only show the fields for your profile and not the user object associated with it.
Change Template/View
You can also change the template and view to accommodate it. Apparently your view is able to produce an IP Address using the get_ip function so for the time being I'll assume your template is fine as is so the only changes that need to be made are to your view.
Currently your view is getting an unsaved User instance back when it calls form.save. This means you need to save the user and then create a Profile model that references it with your ip address attached.
def index(request):
#request.session.flush()
if request.user.is_authenticated:
return redirect('ve:dashboard')
elif request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
# do anything you need to the unsaved user here
user.save()
prof = Profile.objects.create(user=user,
ipaddress=get_ip(request),
date=form.cleaned_data.get('birth_date')
# no need to save prof since we called objects.create
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=user.username, password=raw_password)
login(request, user)
return redirect('ve:dashboard')
else:
form = RegistrationForm()
return render(request, 'index.html', {'form': form})
I am trying to display my users information but I am getting anonymous user as my output;
Anonymous User
My code in my views.py is as follows;
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
return redirect('/account')
else:
form = RegistrationForm()
args = {'form' : form}
return render(request, 'accounts/register.html', args)
def view_profile(request):
args = {'user': request.user}
return render (request, 'accounts/profile.html',args)
I am over-riding the UserCreationForm, my code in forms.py is;
class RegistrationForm(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(RegistrationForm,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
My profile.html where I want my profile information to be displayed is;
{% block head %}
<title> User Profile </title>
{% endblock %}
{% block body %}
<div class="container">
<p>
<h1> {{user}}</h1>
<h3>First Name: {{user.first_name}}</h3>
<h3>Last Name: {{user.last_name}}</h3>
<h3>Email: {{user.email}}</h3>
</p>
</div>
{% endblock %}
Really not sure where I am going wrong any help is greatly appreciated.
you must decorate your def view_profile(request): with #login_required, otherwise Django will serve this request also to Anonymous users.
Also note that if you have (or add) django.core.context_processors.request to your settings.TEMPLATE_CONTEXT_PROCESSORS
(or settings.TEMPLATES['OPTIONS']['context_processors'] depending your django version) you can use {{request.user}} in your template without create specific entry in context.