I am having trouble registering a user as a PetOwner. I'm not sure what I am suppose to code in my signup view. I can signup a user and that user does not have admin or staff status which is great because they should not have these privileges. Problem is that I do not just want them to be a user but I want them to be a PetOwner. Currently, they are only a User not a PetOwner. What am I doing wrong here or what do I have to add.
in models.py
from django.db import models
from django.urls import reverse
from django.contrib.auth.models import User
class PetOwner(models.Model):
"""Model representing a pet owner."""
user = models.OneToOneField(User, on_delete=models.CASCADE)
first_name = models.CharField(max_length=50, help_text="Enter owner's first name")
last_name = models.CharField(max_length=50, help_text="Enter owner's last name")
email = models.EmailField(
max_length=50, blank=True, unique=True, help_text="Enter owner's email"
)
phone_number = models.CharField(
max_length=15, blank=True, unique=True, help_text="Enter owner's phone number"
)
address = models.ForeignKey(
"Address", on_delete=models.SET_NULL, null=True, blank=True
)
class Meta:
"""Controls default ordering of records when querying the Model type."""
ordering = ["first_name", "last_name"]
def __str__(self):
"""String for representing the Model object."""
return self.first_name
def get_absolute_url(self):
"""Returns the url to access a detail record of this pet owner."""
return reverse("petowner_detail", args=[str(self.id)])
in views.py
from django.shortcuts import render, redirect
from django.views import generic
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.contrib.auth.forms import AuthenticationForm, UserCreationForm
from django.contrib.auth.mixins import LoginRequiredMixin
from .models import PetOwner, Pet, Breed, Address
def signup(request):
if request.method == "POST":
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get("username")
password = form.cleaned_data.get("password1")
user = authenticate(username=username, password=password)
login(request, user)
return redirect("/")
else:
return render(request, "signup.html", {"form": form})
else:
form = UserCreationForm()
return render(request, "signup.html", {"form": form})
in urls.py
path("signup/", views.signup, name="signup"),
in signup.html
{% extends 'base.html' %}
<h1>Sign Up Page</h1>
{% block content %}
<form method="post">
{% csrf_token %} {{ form.as_p }}
<button type="submit">Register</button>
</form>
{% endblock content %}
You need save the related PetOwner after the user.
if form.is_valid():
user = form.save()
# Create the related data here...
petOwner = PetOwner(
user=user,
first_name=user.first_name,
last_name=user.last_name
)
petOwner.save()
login(request, user)
return redirect("/")
you should use Foreign key instate of one to one field to pet owner and give them roll as pet owner example is below
from django.db import models
from django.urls import reverse
from django.contrib.auth.models import User
roll={petowner, roll1, roll2}
user = models.OneToOneField(User, on_delete=models.CASCADE, add roll here)
in views.py just check roll and create pet owner object in pet owner model
also you can do this without roll just write logic for if user created then when user will be added it should create a pet owner object automatically
for example
if user:
classrooms = Classroom.objects.filter(id=id, is_active=True)
if users.exists():
user = users.first()
is_user = (user.user==request.user)
if not pet_owner:
pet_owner.objects.create(user=user, user=request.user).save()
this is just an example names and model can be changed
Related
As a newbie to Django, all things are still not clear to me. I'm having some issues while working on my project. Whenever I register as a new student, it lets me to login. But I cannot upload profile picture. It throws me an error:
ValueError at /account_settings/
The 'profile_pic' attribute has no file associated with it.
When I login as an admin and want to see the new student, I just see a blank space, not the new student. Here is the screenshot of my admin view:
If I see from admin page, there is also a blank space. Here is admin page view:
I have to manually create a student and an user from admin page, and make relationship between them. Please anyone explain me what actually happens behind the scenario. I'm a noob, I'll be grateful if anyone kindly makes it clear for me. Thanks in advance.
Here is my models.py:
from django.db import models
from django.contrib.auth.models import User
class Student(models.Model):
user = models.OneToOneField(User, null=True, blank=True, on_delete=models.CASCADE)
name = models.CharField(max_length=200)
phone = models.CharField(max_length=200, null=True)
email = models.CharField(max_length=200, null=True)
profile_pic = models.ImageField(default= 'default-picture.jpg', null= True, blank= True)
date_created = models.DateTimeField(auto_now_add=True, null=True)
def __str__(self):
return str(self.name)
class Tag(models.Model):
name = models.CharField(max_length=200, null=True)
def __str__(self):
return self.name
class Books(models.Model):
CATEGORY = (
('Physics', 'Physics'),
('Chemistry', 'Chemistry'),
('Mathematics', 'Mathematics'),
)
name = models.CharField(max_length=200)
author = models.CharField(max_length=200, null=True)
price = models.FloatField(null=True)
category = models.CharField(max_length=200, null=True, choices=CATEGORY)
description = models.CharField(max_length=200, null=True, blank=True)
date_created = models.DateTimeField(auto_now_add=True, null=True)
tags = models.ManyToManyField(Tag)
def __str__(self):
return self.name
class Issue(models.Model):
STATUS = (
('Pending', 'Pending'),
('Out for delivery', 'Out for delivery'),
('Delivered', 'Delivered'),
)
student = models.ForeignKey(Student, null=True, on_delete= models.SET_NULL)
book = models.ForeignKey(Books, null=True, on_delete= models.SET_NULL)
date_created = models.DateTimeField(auto_now_add=True, null=True)
status = models.CharField(max_length=200, null=True, choices=STATUS)
def __str__(self):
return self.book.name
Here is my forms.py:
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from django.forms import ModelForm
from .models import Issue
from .models import Student
class IssueForm(ModelForm):
class Meta:
model = Issue
fields = '__all__'
class CreateUserForm(UserCreationForm):
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
class StudentForm(ModelForm):
class Meta:
model = Student
fields = '__all__'
exclude = ['user']
It's my decorators.py file:
from django.http import HttpResponse
from django.shortcuts import redirect
def unauthenticated_user(func):
def wrapper(request, *args, **kwargs):
if request.user.is_authenticated:
return redirect('home')
else:
return func(request, *args, **kwargs)
return wrapper
def allowed_user(allowed_roles=[]):
def decorator(func):
def wrapper(request, *args, **kwargs):
group = None
if request.user.groups.exists():
group = request.user.groups.all()[0].name
if group in allowed_roles:
return func(request, *args, **kwargs)
else:
return HttpResponse('You are not authorized to view this page.')
return wrapper
return decorator
def admin_only(func):
def wrapper(request, *args, **kwargs):
group = None
if request.user.groups.exists():
group = request.user.groups.all()[0].name
if group == 'Student':
return redirect ('user_page')
else:
return func(request, *args, **kwargs)
return wrapper
It's my registration, login and account_setting method in views.py file:
from django.shortcuts import render, redirect
from django.http import HttpResponse, HttpResponseRedirect
from django.forms import inlineformset_factory
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import Group
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.urls import reverse
from .models import *
from .forms import IssueForm, CreateUserForm, StudentForm
from .filters import IssueFilter
from .decorators import unauthenticated_user, allowed_user, admin_only
#unauthenticated_user
def registerPage(request):
form = CreateUserForm()
if request.method == "POST":
form = CreateUserForm(request.POST)
if form.is_valid():
user =form.save()
username = form.cleaned_data.get('username')
group = Group.objects.get(name = 'Student')
user.groups.add(group)
Student.objects.create(
user = user
)
messages.success(request, 'Account successfully created for ' + username)
return redirect ('login')
context = {'form': form}
return render(request, 'accounts/register.html', context)
#unauthenticated_user
def loginPage(request):
if request.user.is_authenticated:
return redirect('home')
else:
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return redirect ('home')
else:
messages.info(request, 'Username or Password is incorrect')
return render(request, 'accounts/login.html')
#login_required(login_url='login')
#allowed_user(allowed_roles=['Student'])
def accountSettings(request):
user = request.user.student
form = StudentForm(instance=user)
if request.method == 'POST':
form = StudentForm(request.POST, request.FILES, instance=user)
if form.is_valid():
form.save()
context = {'form': form}
return render(request, 'accounts/account_settings.html', context)
And my account_seetings.html template:
{% extends 'accounts/main.html' %}
{% load static %}
{% block content%}
<style>
.profile-pic{
max-width: 300px;
max-height: 300px;
margin: 0 auto;
border-radius: 70%;
}
</style>
<br>
<div class="row">
<div class="col-md-3">
<div class="card card-body">
<a class="btn btn-warning" href="{% url 'home' %}"> ← Back to Profile</a>
<hr>
<img class="profile-pic" src="{{request.user.student.profile_pic.url}}">
</div>
</div>
<div class="col-md-9">
<div class="card card-body">
<form method="POST" action="" enctype="multipart/form-data">
{% csrf_token %}
{{form.as_p}}
<input class="btn btn-primary" type="submit" name="Update Information">
</form>
</div>
</div>
</div>
{% endblock %}
It should be noted that I have two groups in admin page. These are Student and Admin.
When I create a user with my custom user model I cannot sign in. It just keeps telling me Please enter a correct email and password. Note that both fields may be case-sensitive. I thought I should check if I can see my test user in the db. I know only staff accounts can login to the admin but I'm using a different login form.
If I'm not mistaken it looks like there aren't any users in my database.
myproject=# \dt accounts_user
List of relations
Schema | Name | Type | Owner
--------+---------------+-------+------------------
public | accounts_user | table | myprojectuser
(1 row)
Here's my user model:
from django.db import models
from django.contrib.auth.models import (
AbstractBaseUser,
BaseUserManager,
PermissionsMixin,
)
# Create your models here.
class UserManager(BaseUserManager):
def create_user(self, email, first_name, last_name, company, phone, is_active=True, is_admin=False, is_staff=False, is_dealer=False, password=None):
if not email:
raise ValueError("Users must have an email address")
if not password:
raise ValueError("Users must have a password")
if not first_name:
raise ValueError("Users must have a first name")
if not last_name:
raise ValueError("Users must have a last name")
if not company:
raise ValueError("Users must have a company")
if not phone:
raise ValueError("Users must have a phone number")
user_obj = self.model(
email = self.normalize_email(email)
)
user_obj.set_password(password)
user_obj.first_name = first_name
user_obj.last_name = last_name
user_obj.company = company
user_obj.phone = phone
user_obj.admin = is_admin
user_obj.staff = is_staff
user_obj.dealer = is_dealer
user_obj.active = is_active
user_obj.save(using=self._db)
return user_obj
def create_superuser(self, email, first_name, last_name, company, phone, password=None):
user = self.create_user(
email,
first_name,
last_name,
company,
phone,
password=password,
is_admin=True,
is_staff=True
)
return user
Perhaps there's something wrong in my admin.py?
from django.contrib import admin
from django.contrib.auth import get_user_model
# Register your models here.
User = get_user_model()
admin.site.register(User)
Hopefully someone can help me as I'm really stuck here.
I'm not 100% sure why your issue arises (considered you enterer it in the correct format), but this should give you a basic working solution to build upon:
forms.py
from django.forms import ModelForm
from django.contrib.auth.forms import UserCreationForm
from django import forms
from django.contrib.auth.models import User
# Adjusting the default UserCreationForm
class CreateUserForm(UserCreationForm):
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2', # etc.]
admin.py
from django.contrib import admin
from .models import User
admin.site.register(User)
models.py
from django.contrib.auth.models import PermissionsMixin
from django.contrib.auth.base_user import AbstractBaseUser
# Inherit from AbstractBaseUser to extend User Model
class User(AbstractBaseUser):
email = models.EmailField(max_length=255, unique=True)
first_name = models.CharField(max_length=255, blank=True, null=True)
last_name = models.CharField(max_length=255, blank=True, null=True)
company = models.CharField(max_length=255, blank=True, null=True)
phone = models.CharField(max_length=255, blank=True, null=True)
active = models.BooleanField(default=True) # can login
online = models.BooleanField(default=False)
admin = models.BooleanField(default=False)
staff = models.BooleanField(default=False)
dealer = models.BooleanField(default=False)
timestamp = models.DateTimeField(auto_now_add=True)
Also I am not sure which tutorial (this?) you followed, but personally I don't have models both in models.py and admin.py.
Login extension - views.py
# function for login logic
def loginPage(request):
if request.method == 'POST':
# get input values
username = request.POST.get('username')
password = request.POST.get('password')
# check if user has account in db
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return redirect('render_calculator')
context = {}
return render(request, 'login.html', context)
def registerPage(request):
# define the form, in this case Djangos default UserCreation
form = CreateUserForm()
# check if form inputs are valid after submitting, the save 'post' user
if request.method == 'POST':
form = CreateUserForm(request.POST)
if form.is_valid():
# Save User to db
form.save()
# get input values
username = request.POST.get('username')
password = request.POST.get('password')
email = request.POST.get('email')
return redirect('render_login')
context = {'form': form}
return render(request, 'register.html', context)
login.html
<form method="post" action="">
{% csrf_token %}
<div class="formFieldLoginContainer">
<input type="text" name="username" placeholder="username">
<input type="password" name="password" placeholder="password">
</div>
<input type="submit" id="loginSubmitButton" name="Login User" value="Login">
<div id="noAccountDiv"> Don't have an account yet?
Sign Up
</div>
</form>
register.html
<form method="post" action="">
{% csrf_token %}
<!-- loop form object and create div for each form field included -->
{% for field in form %}
<div class="formFieldContainer">
<div class="registerLabel">{{field.label}}</div>
<div class="registerField">{{field}}</div>
</div>
{% endfor %}
<!-- render possible input form errors -->
{{form.errors}}
<input type="submit" id="submitButton" name="Create User" value="Register">
<div id="alreadyAccountDiv"> Already have an account?
Login
</div>
</form>
ulrs.py
urlpatterns = [
path('login/', views.loginPage, name='render_login'),
path('logout/', views.logout_view),
path('email/', include(mail_urls)),
path('password/', views.change_password, name='change_password'),
]
I have created a Customer model in my models and registered it on admin.py. Then I made a login form and took field values using get method.Now I want to iterate through all the objects of customer created and find the one with those two matching fields.I have made a login function in the views.py. This is my model:class Customer(models.Model):
FirstName = models.CharField(max_length=100, default="")
LastName = models.CharField(max_length=100, default="")
address = models.CharField(max_length=500, default="")
EmailId = models.CharField(max_length=120, default="")
PhoneNo = models.CharField(max_length=12, default="")
Password = models.CharField(max_length=120, default="")
And this is my function:
def login(request):
if request.method=="POST":
FirstName= request.POST.get('FirstName', '')
Password = request.POST.get('Password', '')
for customer in Customer.objects.all():
if FirstName==customer.FirstName and Password==customer.Password:
return redirect ( 'customer-home')
return render(request, 'customer/login.html')
I'm not getting the desired results.
I suggest instead of using the for loop to check every object you can use the Queryset check (https://docs.djangoproject.com/en/3.0/ref/models/querysets/) provided by Django like below
customer = Customer.objects.get(firstname=firstname, password=password)
if customer is not None:
redirect ( 'customer-home')
Make a form.py file which has django forms imported in it like this which would be helpful.
forms.py
from django.forms import ModelForm
from .models import *
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.forms import User
from django import forms
class CreateUserForm(UserCreationForm):
class Meta:
model=User
fields=['Firstname','Lastname','EmailId','Address',Password','PhoneNo']
Then in views add
from .forms import *
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password =request.POST.get('password')
customer = authenticate(request, username=username, password=password)
if customer is not None:
login(request, customer)
return redirect('/')
else:
messages.info(request, 'Username OR password is incorrect')
return render(request, 'customer/login.html')
Hope you have made a register page as it is necessary for authentication.Tell me if you need help in that
I am trying to make a simple signup/login page through django.
I have used UserCreationForm and used a model UserProfile to extend the user model.
I want to retrieve the data posted from form i.e department at my home page after user logged in.
I am new to django so brief explanation would be appreciated.
Thanks in advance
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from mysite.core.models import UserProfile
from django.db import models
class SignUpForm(UserCreationForm):
first_name = forms.CharField(max_length=30, required=False, help_text='Optional.')
department = forms.CharField(max_length=30)
last_name = forms.CharField(max_length=30, required=False, help_text='Optional.')
email = forms.EmailField(max_length=254, help_text='Required. Inform a valid email address.')
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email','password1', 'password2', 'department',)
def save(self, commit=True):
# Save the provided password in hashed format
user = super(SignUpForm, self).save(commit=False)
user_profile = UserProfile(user=user, department=self.cleaned_data['department'])
user.save()
user_profile.save()
return user, user_profile
views.py
from django.contrib.auth.decorators import login_required
from django.contrib.auth import login, authenticate
from django.shortcuts import render, redirect
from mysite.core.forms import SignUpForm
#login_required
def home(request):
return render(request, 'home.html')
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
user,user_profile = form.save(commit=False)
username = user.cleaned_data.get('username')
raw_password = user.cleaned_data.get('password1')
user = authenticate(username=username, password=raw_password)
login(request, user)
return redirect('home')
else:
form = SignUpForm()
return render(request, 'signup.html', {'form': form})
models.py
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE,unique=True)
department = models.CharField(max_length=500, blank=True)
home.html in templates:
{% extends 'base.html' %}
{% block content %}
<h2>Welcome, <small>{{ user.username }}</small>!</h2>
<p>Your email address: {{ user.email }}</p>
<p>Department: {{ user_profile.department }}</p>
{% endblock %}
I am able to print username and email but department is coming empty.
Firstly, you have the wrong relationship. There is a one-to-one relationship between User and UserProfile; a user can only have one profile, and a profile can only belong to one user. The way you have it now, a user can have many profiles, which doesn't make sense.
You should replace the ForeignKey with a OneToOneField.
Once you have done that, you will be able to access the profile data via the relationship: user.userprofile.department, and so on.
Please i need help .I have a problem in extending userprofile.At first everything seems to be working good until now .Please i need help in resolving this bellow is my code .
Model.py
class UserProfile(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE,related_name="userprofile")
date =models.DateField(blank=False,null= True)
bio = models.TextField(max_length=500,blank=False)
picture = models.ImageField(upload_to="profile_image",null=True,blank=True)
company = models.CharField(max_length=500,null=True)
def __str__(self):
return self.user.username
#receiver(post_save,sender=User)
def create_profile(sender,instance,created,**kwargs):
if created:
UserProfile.objects.create(user=instance)
#receiver(post_save,sender=User)
def save_user_profile(sender,instance,**kwargs):
instance.UserProfile.save()
views.py
def update_profile(request):
if request.method == 'POST':
profile_form = ProfileForm(request.POST,request.FILES,instance=request.user.userprofile)
if profile_form.is_valid():
profile_form.save()
messages.success(request,'Your Profile has been Updated')
return redirect('success:profile_account')
else:
messages.error(request,'fill out the fields correctly')
else:
profile_form = ProfileForm(instance=request.user.userprofile)
return render(request,"success/user_account/edit_profile.html",{'profile_form':profile_form})
html.form
<form action='{{ action_url }}' method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ profile_form.bio}}{{profile_form.bio.error}}
{{ profile_form.picture}}{{profile_form.picture.error}}
<div class="pc"><label>Company Name:</label>{{ profile_form.company}}{{profile_form.company.error}}
{{ profile_form.date}}{{profile_form.date.error}}
<button type="submit">Save changes</button>
Error I get
Forbidden (403)
CSRF verification failed. Request aborted. Help
Reason given for failure:
CSRF token missing or incorrect.
In general, this can occur when there is a genuine Cross Site Request
Forgery, or when Django's CSRF mechanism has not been used correctly.
For POST forms, you need to ensure:
Your browser is accepting cookies.
The view function passes a request to the template's render method.
In the template, there is a {% csrf_token %} template tag inside each POST form that targets an internal URL.
If you are not using CsrfViewMiddleware, then you must use csrf_protect on any views that use the csrf_token template tag, as
well as those that accept the POST data.
The form has a valid CSRF token. After logging in in another browser tab or hitting the back button after a login, you may need to
reload the page with the form, because the token is rotated after a
login.
You're seeing the help section of this page because you have DEBUG =
True in your Django settings file. Change that to False, and only the
initial error message will be displayed.
You can customize this page using the CSRF_FAILURE_VIEW setting.
this is the best way to extend user model profile
from django.contrib.auth.models import AbstractBaseUser
from django.db import models
from django.contrib.auth.models import BaseUserManager
class AccountManager(BaseUserManager):
def create_user(self, username, password=None, **kwargs):
if not username:
raise ValueError('Users must have a valid email username.')
if not kwargs.get('email'):
raise ValueError('Users must have a valid email.')
email = kwargs.get('email')
account = self.model(
username=username, email=self.normalize_email(email)
)
account.set_password(password)
account.save()
return account
def create_superuser(self, username, password, **kwargs):
account = self.create_user(username, password, **kwargs)
account.is_admin = True
account.save()
return account
class Account(AbstractBaseUser):
username = models.CharField(max_length=40, unique=True)
email = models.EmailField(unique=True)
first_name = models.CharField(max_length=40, blank=True)
last_name = models.CharField(max_length=40, blank=True)
is_admin = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = AccountManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email', 'first_name', 'last_name']
def __unicode__(self):
return self.email
def get_full_name(self):
return ' '.join([self.first_name, self.last_name])
def get_short_name(self):
return self.first_name
modify this example and then in forms.py just import you model user profile