I am creating a donation app that allows donors to create listings. This data is stored in a Django Model and is going to be displayed on a page. I want to save the user's username to the Django model and display it on the page. My code is down below
Models.py
class Donation(models.Model):
title = models.CharField(max_length=30)
phonenumber = models.CharField(max_length=12)
category = models.CharField(max_length=20)
image = models.CharField(max_length=1000000)
deliveryorpickup = models.CharField(max_length=8)
description = models.TextField()
Views.py
from django.contrib.auth.models import User
from django.http.request import RAISE_ERROR
from django.http.response import HttpResponseRedirect
from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.forms import forms, inlineformset_factory
from django.contrib.auth.forms import UserCreationForm, UsernameField
from .forms import CreateUserForm
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from home.models import Donation
# Create your views here.
def index(request,*args, **kwargs):
return render(request, "index.html", {} )
#login_required(login_url='/login/')
def dashboard(request,*args, **kwargs):
return render(request, "dashboard.html", {} )
def register(request, ):
if request.user.is_authenticated:
return redirect('/dashboard/')
else:
form = CreateUserForm()
if request.method == "POST":
form = CreateUserForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
messages.success(request, f'Your account has been successfully created, {username} ')
return redirect('loginpage')
context = {'form': form}
return render(request, "register.html", context )
def loginpage(request):
if request.user.is_authenticated:
return redirect('/dashboard/')
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('/dashboard')
else:
messages.error(request, 'Username OR password is incorrect')
context = {}
return render(request, 'login.html', context)
def logoutuser(request):
logout(request)
return HttpResponseRedirect('/login/')
#login_required(login_url='/login/')
def donate(request):
if request.method == "POST":
title = request.POST['donationtitle']
phonenumber = request.POST['phonenumber']
category = request.POST['category']
image = request.POST['imagelink']
deliveryorpickup = request.POST['deliveryorpickup']
description = request.POST['description']
ins = Donation(title = title, phonenumber = phonenumber, category = category, image = image, deliveryorpickup = deliveryorpickup, description = description )
ins.save()
return render(request,'donate.html')
Forms.py (This is where the user is created)
class CreateUserForm(UserCreationForm):
username = forms.CharField(required=True, max_length=30, )
email = forms.EmailField(required=True)
first_name = forms.CharField(required=True, max_length=50)
last_name = forms.CharField(required=True, max_length=50)
class Meta:
model = User
fields = ['username', 'email', 'first_name', 'last_name', 'password1', 'password2',]
#function to display errors
def clean(self):
cleaned_data=super().clean()
password1 = self.cleaned_data.get('password1')
password2 = self.cleaned_data.get('password2')
if User.objects.filter(username=cleaned_data["username"]).exists():
raise ValidationError("This username is taken, please try another one")
elif password1 != password2:
raise forms.ValidationError("2 password fields do not match")
elif len(password1) < 8 or len(password2) < 8:
raise forms.ValidationError("Passwords must be at least 8 characters long")
To associate the user with the Donation model, you should first add a ForeignKey field to the model class:
from django.conf import settings
class Donation(models.Model):
... # your other donation fields
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
blank=True,
null=True,
)
Once you've made this change, and run the migrations, in your views.py you'll pass the currently signed in user to the Donation model creation:
#login_required(login_url='/login/')
def donate(request):
if request.method == "POST":
ins = Donation(
title=request.POST["title"],
... # all of the other fields
user=request.user, # 👈 This adds the user
)
ins.save()
return render(request,'donate.html')
Notes
Using settings.AUTH_USER_MODEL allows your class to use a custom user model, or django's default user model, based on your project's settings.
To understand what on_delete=models.CASCADE does, you should read django's documentation about it.
Also, instead of manually passing all of the request.POST[...] values to the Donation model, I recommend that you use a ModelForm. It will handle errors and validation for you, as well as generate the HTML displayed in the template. Using a model form here would make your view code change to this:
from django.forms import ModelForm
class DonationForm(ModelForm):
class Meta:
model = Donation
exclude = ["user"]
#login_required(login_url="/login/")
def donate(request):
if request.method == "POST":
form = DonationForm(request.POST)
if form.is_valid():
donation = form.save(commit=False)
donation.user = request.user
donation.save()
# Use a redirect to prevent duplicate submissions
# https://docs.djangoproject.com/en/3.2/topics/http/shortcuts/#redirect
return redirect(request, ...)
else:
form = DonationForm()
return render(request, "donate.html", {"form": form})
Related
i am making an ecom app for Django but when i use a diffrent user i get this error. i think it has something to do with assigning a Customer to a User, as when i manually create a Customer with a User.
Exception Type: RelatedObjectDoesNotExist
Exception Value:
User has no customer.
Exception Location: L:\Django\Website\lib\site-packages\django\db\models\fields\related_descriptors.py in __get__, line 420
Python Executable: L:\Django\Website\Scripts\python.exe
Python Version: 3.8.3
here is my views.py
from django.shortcuts import render
from .models import *
from django.http import JsonResponse
import json
import datetime
from django.contrib.auth.models import User
def store(request):
if request.user.is_authenticated:
customer = request.user.customer
order, created = Order.objects.get_or_create(customer=customer, complete=False)
items = order.orderitem_set.all()
cartItems = order.get_cart_items
else:
items = []
order = {'get_cart_total':0,'get_cart_items':0, 'shipping':False}
cartItems = order['get_cart_items']
search = request.GET.get('search')
products = Product.objects.all()
if search != '' and search is not None:
products = products.filter(name__icontains=search)
context= {'products': products, 'cartItems':cartItems}
return render(request, 'store/store.html', context)
...unrelated...
here is my models.py
from django.db import models
from django.contrib.auth.models import User
class Customer(models.Model):
user = models.OneToOneField(User, null=True, blank=True, on_delete=models.CASCADE)
name = models.CharField(max_length=200, null=True)
email = models.CharField(max_length=200)
def __str__(self):
return self.name
...unrelated...
========================
when i use the method in the code block it doesn't save the extra fields
forms.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from .models import Profile
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(required=True)
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
class meta:
model = User
fields = ['username', 'first_name', 'last_name', 'email', 'password1', 'password2']
views.py
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST, request.FILES)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
messages.success(request, f'Your account has been created! You are now able to login')
return redirect('login')
else:
form = UserRegisterForm()
return render(request, 'users/register.html', {'form': form})
but when i try this it saves everything except the passwords
forms.py
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(required=True)
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
class meta:
model = User
fields = ['username', 'first_name', 'last_name', 'email', 'password1', 'password2']
def save(self, **kwargs):
user = super(UserCreationForm, self).save(commit=False)
user.email = self.cleaned_data["email"]
user.first_name = self.cleaned_data["first_name"]
user.last_name = self.cleaned_data["last_name"]
user.save()
return user
views.py is the same.
I'd suggest to use the Customer model as what you refer to as the user throughout the app. Therefore I would keep the save method for the user as default and add the extra fields to the Customer model.
This makes it also easier to later add extra data of the user when registering. The Customer would be created on registering the user. For example:
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(required=True)
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
def save(self, **kwargs):
user = super().save()
customer = Customer.objects.create(user=user, first_name=self.cleaned_data.get('first_name'),
last_name=self.cleaned_data.get('last_name'), email=self.cleaned_data.get('email'))
return user
The Customer model will need a first_name and last_name field instead of name now.
Your current code (store view) will then work as well.
how can I put condition if an email doesn't exist don't send this email to my own email
I'm trying that here when I put (exists) method but I see as if it doesn't work.
in both cases, shows me an email successful message
how can I stops that ?
if there is a mistake in my code becomes error I wish to get advice to process that
sorry, I'm not fluent in English
views.py
from .forms import SignUp, ResetPassword, EditForm
from website import settings
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from django.contrib.auth.views import PasswordResetView, PasswordResetDoneView
from django.views.generic.edit import FormView
from django.urls import reverse_lazy
from django.core.mail import send_mail
from django.contrib.auth.models import User
class PasswordReset(PasswordResetView, FormView):
template_name = 'account/password_reset_view.html'
success_url = reverse_lazy('account:password_reset_done')
email_template_name = 'account/reset_password_email.html'
subject_template_name = 'account/password_reset_subject.txt'
form_class = ResetPassword
class PasswordResetDone(PasswordResetDoneView):
template_name = 'account/password_reset_done.html'
# Reset Your Password By G-mail Account
def send_mail(self, request, **kwargs):
subject = "Complete the modification of the password form"
message = "please check here"
if request.method == "POST":
user = User.objects.filter(email=str(request.POST['email']))
if user.exists():
recipient = str(request.POST.get(kwargs['Email']))
if subject and message and recipient:
send_mail(subject=subject,
message=message,
from_email=settings.EMAIL_HOST,
auth_user=request.user.email,
auth_password=request.user.password,
recipient_list=[recipient],
fail_silently=False)
return render(request, self.template_name)
else:
return redirect('account:password-reset')
def register(request):
template_name = 'account/register.html'
if request.method == 'POST':
form = SignUp(request.POST)
if form.is_valid():
# save in database
form.save()
return redirect('account:login')
return render(request, template_name, {'form': form})
else:
form = SignUp()
return render(request, template_name, {'form': form})
#login_required
def view_profile(request):
return render(request, 'account/profile.html', {'user': request.user})
#login_required
def edit_profile(request):
template_name = 'account/edit_profile.html'
if request.method == "POST":
form = EditForm(request.POST)
if form.is_valid():
form.save()
return redirect('account:view_profile')
return render(request, template_name, {'form': form})
else:
form = EditForm()
return render(request, template_name, {'form': form})
forms.py
from django.contrib.auth.forms import UserCreationForm, UserChangeForm, PasswordResetForm
from django import forms
from django.contrib.auth.models import User
class SignUp(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'password1', 'password2', 'email')
def save(self, commit=True):
user = super(SignUp, 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']
user.set_password(self.cleaned_data['password1'])
# Save this session without saving in database
if commit:
user.save()
return user
class ResetPassword(PasswordResetForm):
email = forms.EmailField(required=True, widget=forms.TextInput(attrs={'placeholder': 'Type Email'}))
class Meta:
model = User
fields = ('email',)
class EditForm(UserChangeForm):
password = None
class Meta:
model = User
fields = ('first_name', 'last_name', 'email')
def edit(self, fields):
user = super(EditForm, self).save(commit=False)
if user.commit:
user.save()
return user
settings.py
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
# sending an email
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'medoabdin#gmail.com'
EMAIL_HOST_PASSWORD = 'medo_rko96'
EMAIL_USE_TLS = True
EMAIL_USE_SSL = False
models.py
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
overview = models.TextField(editable=True, help_text="This field is important to make the viewers know you and your experience")
city = models.CharField(max_length=20)
phone = models.IntegerField(default=0)
logo = models.ImageField()
def __str__(self):
return self.user.username
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile = UserProfile.objects.create(user=kwargs['instance'])
post_save.connect(receiver=create_profile, sender=User)
the format of the database as following
user Use try catch in your method send_mail and change filter with get such as below line
user = User.objects.get(email=str(request.POST['email']))
Get method will try to find the user if not found in the DB then it will raise user.DoesNotExist exception you can catch it and do whatever you want.
Like :-
def send_mail(self, request, **kwargs):
subject = "Complete the modification of the password form"
message = "please check here"
if request.method == "POST":
try:
user = User.objects.get(email=str(request.POST['email']))
recipient = str(request.POST.get(kwargs['Email']))
if user.is_active and subject and message and recipient:
send_mail(subject=subject,
message=message,
from_email=settings.EMAIL_HOST,
auth_user=request.user.email,
auth_password=request.user.password,
recipient_list=[recipient],
fail_silently=False)
return render(request, self.template_name)
except user.DoesNotExist:
return redirect('account:password-reset')
I am very much a beginner to Django and just Python overall, but I am trying to create a relatively simple web app and I seem to be running into some obstacles.
I would like to add custom fields to my Django UserCreationForm like first name, last name, email and ID number? Should I create a separate Profile model and if so how should I do that, or is there some other way to achieve this?
Like I said, I am a beginner so I would appreciate as much detail as possible!
For first name, last name and email fields you won't need to do anything. But for ID I suggest you create a separate model, that's really simple actually!
models.py
from django.contrib.auth.models import User
class IdNumber(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
id_number = models.TextField(max_length=9)
forms.py
from django.contrib.auth.models import User
class SignUpForm(forms.ModelForm):
id_number = forms.CharField(max_length=9, required=True)
password = forms.CharField(max_length=15, required=True)
password_confirm = forms.CharField(max_length=15, required=True)
class Meta:
model = User
fields = ['first_name', 'last_name', 'email', 'username', 'password']
def clean(self):
cleaned_data = super(SignUpForm, self).clean()
password = cleaned_data.get('password')
password_confirm = cleaned_data.get('password_confirm')
if password != password_confirm:
raise forms.ValidationError('Passwords do not match!')
views.py
from .models import IdNumber
from .forms import SignUpForm
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
username = form.cleaned_data['username']
password = form.cleaned_data['password']
id_number = form.cleaned_data['id_number']
user.set_password(password)
id_model = IdNumber(user.id)
id_model.user = user
id_model.id_number = id_number
id_model.save()
form.save()
return HttpResponseRedirect('some_url')
else:
return render(request, 'your_app/your_template.html', {'form': form})
else:
form = SignUpForm()
return render(request, 'your_app/your_template.html', {'form': form}
this is the forms page
from django import forms
from django.contrib.auth.models import User
from .models import Profile
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput, required=False)
class Meta():
model = User
fields = ['username', 'email', 'password']
class ProfileForm(forms.ModelForm):
class Meta():
model = Profile
fields = ['pic']
& this is the views page
from django.shortcuts import render
from .forms import UserForm, ProfileForm
def register(request):
if(request.method == 'POST'):
userform = UserForm(request.POST)
profileform = ProfileForm(request.POST)
if(userform.is_valid() and profileform.is_valid()):
user = userform.save()
user.set_password(user.password)
user.save()
profile = profileform.save(commit=False)
profile.user = user
if('pic' in request.FILES):
profile.pic = request.FILES['pic']
profile.save()
else:
print(userform.errors, profileform.errors)
else:
userform = UserForm()
profileform = ProfileForm()
return render(request, 'register.html', {'userform':userform,
'profileform':profileform})
when I submit the password or the picture it doesn't save the user to the admin area and says that password is required and the picture is not uploaded
You should use commit=False when saving password from the form and not like in ordinary form with using set().
from django import forms
from django.contrib.auth.models import User
from .models import Profile
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput, required=False)
class Meta:
model = Users
fields =['email', 'password', 'username']
class ProfileForm(forms.ModelForm):
class Meta():
model = Profile
fields = ['pic']
from django.shortcuts import render
from .forms import UserForm, ProfileForm
def register(request):
if(request.method == 'POST'):
form = UserForm(request.POST or None)
profileform = ProfileForm(request.POST or None)
if(userform.is_valid() and profileform.is_valid()):
userform = form.save(commit=False)
userform.password = make_password(form.cleaned_data['password'])
userform.save()
profile = profileform.save(commit=False)
profile.user = user
if('pic' in request.FILES):
profile.pic = request.FILES['pic']
profile.save()
else:
print(userform.errors, profileform.errors)
else:
userform = UserForm()
profileform = ProfileForm()
return render(request, 'register.html', {'userform':userform,
'profileform':profileform})
Look at this link also.
I am using python and django to develop an web application where I have built a CustomUser model extending the user model and also built a sign up form. But problem is that each time I am registering a new user when I go back to login page and enter the user name and password, it keeps giving the message "Username and Password does not match".
I am pasting the codes here:
forms.py
import re
from django.utils.translation import ugettext_lazy as _
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from models import CustomUser
import pdb
class RegistrationForm(UserCreationForm):
"""A form for creating new users. Includes all the required
fields, plus a repeated password."""
first_name = forms.RegexField(regex=r'^\w+$', widget=forms.TextInput(attrs=dict(required=True, max_length=30)), label=_("First name"), error_messages={ 'invalid': _("This value must contain only letters") })
last_name = forms.RegexField(regex=r'^\w+$', widget=forms.TextInput(attrs=dict(required=True, max_length=30)), label=_("Last name"), error_messages={ 'invalid': _("This value must contain only letters") })
password1 = forms.CharField(widget=forms.PasswordInput(attrs=dict(required=True, max_length=30, render_value=False)), label=_("Password"))
password2 = forms.CharField(widget=forms.PasswordInput(attrs=dict(required=True, max_length=30, render_value=False)), label=_("Password (again)"))
date_of_birth = forms.DateField(widget=forms.TextInput(attrs= {'class':'datepicker'}))
sex = forms.ChoiceField(choices=(('M', 'MALE'), ('F', 'FEMALE')), label=_("Sex"))
voter_id = forms.CharField(widget=forms.TextInput(attrs=dict(required=True, max_length=30)), label=_("Voter Id"))
is_election_staff = forms.BooleanField(initial=False, required=False)
class Meta:
model = CustomUser
fields = ['first_name', 'last_name', 'voter_id', 'date_of_birth', 'sex', 'is_election_staff']
def clean_username(self):
try:
user = User.objects.get(voter_id__iexact=self.cleaned_data['voter_id'])
except User.DoesNotExist:
return self.cleaned_data['voter_id']
raise forms.ValidationError(_("The user with given voter id already exists. Please try another one."))
def clean(self):
if 'password1' in self.cleaned_data and 'password2' in self.cleaned_data:
if self.cleaned_data['password1'] != self.cleaned_data['password2']:
raise forms.ValidationError(_("The two password fields did not match."))
return self.cleaned_data
def save(self, commit=True):
# Save the provided password in hashed format
user = super(RegistrationForm, self).save(commit=False)
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.date_of_birth = self.cleaned_data['date_of_birth']
user.sex = self.cleaned_data['sex']
user.voter_id = self.cleaned_data['voter_id']
user.is_election_staff = self.cleaned_data['is_election_staff']
user.username = user.voter_id
user.set_password(self.cleaned_data['password1'])
if commit:
user.save()
return user
models.py
from __future__ import unicode_literals
from django.db import models
from django.contrib.auth.models import (
AbstractBaseUser)
class Party(models.Model):
name = models.CharField(max_length=200)
num_seats_won = models.IntegerField(default=0)
SEX = (('M', 'MALE'), ('F', 'FEMALE'))
class CustomUser(AbstractBaseUser):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
date_of_birth = models.DateField()
sex = models.CharField(choices=SEX, max_length=10)
is_election_staff = models.BooleanField(default=True)
voter_id = models.CharField(max_length=40, unique=True)
USERNAME_FIELD = 'voter_id'
def __str__(self):
return "%s %s" % (self.first_name, self.last_name)
voting/urls.py: (Here voting is my application name)
urlpatterns = [
# url(r'^$', views.index, name='index'),
url(r'^$', 'django.contrib.auth.views.login'),
url(r'^logout/$', logout_page),
url(r'^register/$', register),
url(r'^register/success/$', register_success),
url(r'^home/$', home),
]
views.py
from .forms import *
from django.contrib.auth.decorators import login_required
from django.contrib.auth import logout
from django.views.decorators.csrf import csrf_protect
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
from django.template import RequestContext
import pdb
#csrf_protect
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
print "In register request = "+ str(request.POST)
form.save()
return HttpResponseRedirect('/voting/register/success/')
else:
form = RegistrationForm()
variables = RequestContext(request, {
'form': form
})
return render_to_response(
'registration/register.html',
variables,
)
def register_success(request):
print "In success request = "+ str(request)
return render_to_response(
'registration/success.html',
)
def logout_page(request):
logout(request)
return HttpResponseRedirect('/voting/')
#login_required
def home(request):
return render_to_response(
'home.html',
{ 'user': request.user }
)
Can anyone please suggest me the mistake that I am doing here? Thanks in advance.
Your Override the user model but have make change in backend.py which is use to check when user try to login in this file i think django checking username and password from user model.