Django require user when creating password, don't require when editing - django

my ModelForm definition looks like this:
class UserForm(ModelForm):
password = forms.CharField(required=True, label="Password", widget=forms.PasswordInput)
So password is required when I'm creating a new user. However I'd like to NOT require it when editing the user. My edit/add is handled in views.py in the following way
#user_passes_test(lambda u: u.is_superuser)
def add(request):
if request.method == 'POST':
form = UserForm(request.POST)
if form.is_valid():
new_user = User.objects.create_user(form.cleaned_data['username'], form.cleaned_data['email'], form.cleaned_data['password'])
new_user.save()
messages.success(request, "User '%s' created" % new_user.username)
return HttpResponseRedirect('/user')
else:
form = UserForm()
return render(request, 'user/add.html', {"form": form})
#user_passes_test(lambda u: u.is_superuser)
def edit(request, id):
user = User.objects.get(id=id)
if request.method == 'POST':
f = UserForm(request.POST, instance=user)
if f.is_valid():
f.save()
messages.success(request, "User '%s' altered" % user.username)
return HttpResponseRedirect('/user')
else:
form = UserForm(instance=user)
return render(request, 'user/edit.html', {"form": form, "user": user})
Thanks for the answer.
Michal

This is what I would do:
class UserForm(ModelForm):
def __init__(self, *args, **kwargs):
is_edit = kwargs.get('is_edit', False)
if 'is_edit' in kwargs:
del kwargs['is_edit']
super(UserForm, self).__init__(*args, **kwargs)
if is_edit:
self.fields['password'].required = False
Then, in your edit() function:
f = UserForm(request.POST, instance=user, is_edit=True)
I use this type of thing fairly regularly in our codebase.

Related

Django form-wizard form save

I would like to save the form and log in in a session wizard I used to do it using requests how would I use it like so>? Within the done function.
class UserWizard(SessionWizardView):
template_name = "registration/signup.html"
form_list = [SignUpForm]
def done(self, form_list, **kwargs):
process_data(form_list)
return redirect('home')
""" def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
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('home')
else:
form = SignUpForm()
return render(request, 'registration/signup.html', {'form': form}) """
class UserWizard(SessionWizardView):
template_name = "registration/signup.html"
form_list = [SignUpForm]
def done(self, form_list, **kwargs):
#process_data(form_list)
form_list[0].save()
userCreate = form_list[0]
username = userCreate.cleaned_data.get('username')
raw_password = userCreate.cleaned_data.get('password1')
user = authenticate(username=username, password=raw_password)
if user:
auth_login(self.request, user)
return redirect('home')
Just create a user by saving the form and then use auth_login.

Displaying Django Models data in html file

I want to display data taken from my Django models in my html file. So in the code bellow instead of a 0 I want the donation model data. Can someone please help? Thank you! also if anyone knows a easier way please tell me. i can update my question again if anyone needs more details.
Views.py
from django.forms import ModelForm
# Create your views here.
def index(request,*args, **kwargs):
return render(request, "index.html", {} )
#login_required(login_url='/login/')
def myview(request,id):
data= userdetails.objects.get(id=id)
return render(request,'dashboard.html',{'data':data}
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']
quantity = request.POST['quantity']
location = request.POST['location']
description = request.POST['description']
ins = Donation(title = title, phonenumber = phonenumber, category = category, quantity = quantity, location = location, description = description, user=request.user, )
ins.save()
return render(request,'donate.html')
Error:
File "C:\Users\jbtai\coding\GoodDeedWeb\home\views.py", line 30
def register(request ):
^
You need a view that handle that:
def myview(request):
id = request.user.id
data= userderails.objects.get(id=id)
return render(request,'dashboard.html',{'data':data}
Then in your template 'dashboard.html' you could show details:
{{data.donations}}
{{data.points}}
use this url for that view instead of the old one
path('dashboard/',views.myview, name = 'dashboard' ),

Django form creating new record instead of updating

I'm creating a user update form in my app. but every time when the form is submitted , it creates a new record and if you try submitting again will return Integrity Error(duplicate username that both are null).
ERROR message: django.db.utils.IntegrityError: UNIQUE constraint failed: auth_user.username
forms.py:
class UserChangeForm(forms.ModelForm):
class Meta:
model = User
fields = ['email', 'first_name', 'last_name']
def __init__(self, username, *args, **kwargs):
super(UserChangeForm, self).__init__(*args, **kwargs)
self.username = username
views.py:
def profile(request):
user = request.user
if request.method == 'POST':
user_form = UserChangeForm(user, request.POST)
if user_form.is_valid():
user_form.save()
messages.success(request, f'Your account has been updated!')
return redirect('users:profile')
else:
email = request.user.email
first_name = request.user.first_name
last_name = request.user.last_name
user_form = UserChangeForm(user, initial={
'email': email,
'first_name': first_name,
'last_name': last_name
})
context = {
'user_form': user_form,
}
return render(request, 'users/profile.html', context)
you need to pass the user as instance in the if condition and in else too like this
def profile(request):
if request.method == 'POST':
user_form = UserChangeForm(request.POST , instance = request.user)
if user_form.is_valid():
user_form.save()
messages.success(request, f'Your account has been updated!')
return redirect('users:profile')
else:
user_form = UserChangeForm(instance=request.user)
context = {
'user_form': user_form,
}
return render(request, 'users/profile.html', context)

django : 'LoginForm' object has no attribute 'cleaned_data'

I'm trying to make a Login but it doesn't work.
the error is
form.is_valid() return False and
'LoginForm' object has no attribute 'cleaned_data'
I can't figure out out is the problem.
user/forms.py
class LoginForm(forms.Form):
email = forms.EmailField(widget=forms.EmailInput(
attrs={'style': 'width:100%; height:100%;'}))
password = forms.CharField(widget=forms.PasswordInput(
attrs={'style': 'width:100%; height:100%;'}))
def __init__(self, request=None, *args, **kwargs):
self.request = request
super(LoginForm, self).__init__(*args, **kwargs)
self.fields['email'].label = "이메일"
self.fields['password'].label = "비밀번호"
def clean(self):
super().clean()
email = self.cleaned_data.get("email")
password = self.cleaned_data.get("password")
try:
user = models.User.objects.get(email=email)
if user.check_password(password):
return self.cleaned_data
else:
self.add_error("password", forms.ValidationError(
"비밀번호가 틀렸습니다."))
except models.User.DoesNotExist:
self.add_error("email", forms.ValidationError(
"존재하지 않는 계정입니다."))
users/views.py
class LoginView(mixins.LoggedOutOnlyView, View):
def get(self, request):
form = forms.LoginForm(request.POST)
return render(request, "users/login.html", {"form": form})
def post(self, request):
form = forms.LoginForm(request.POST or None)
print(form.is_valid())
if form.is_valid():
email = form.cleaned_data.get("email")
password = form.cleaned_data.get("password")
get_user_name = user_models.User.objects.get(email=email)
user = authenticate(
request, username=get_user_name, password=password)
if user is not None:
login(request, user)
return redirect(reverse("cores:home"))
else:
return render(request, "users/login.html", {"form": form})
You need to set a local variable with the return value of the super() call. In your fields you'd no longer call the self.cleaned_data variant but the local variable cleaned_data. Also return the cleaned_data at the end of the def clean() method - even if errors occurred.
def clean(self):
cleaned_data = super().clean()
email = cleaned_data.get("email")
password = cleaned_data.get("password")
...
# Don't forget to return the cleaned_data after everything
return cleaned_data
This is documented in the django docs:
https://docs.djangoproject.com/en/3.0/ref/forms/validation/#cleaning-and-validating-fields-that-depend-on-each-other

create help text for a field dynamically

I have my response form and view like this
class ResponseForm(ModelForm):
class Meta:
model = ResponseModel
exclude = ('author', 'title','submit_count')
# help_texts = {
# 'ans1': user.q1.value,
# }
#login_required
def ResponseFormView(request):
if request.method == "POST":
form = ResponseForm(request.POST)
if form.is_valid():
submission = form.save(commit=False)
submission.author = request.user
submission.save()
return render(request, 'thanks.html', {})
else:
form = ResponseForm()
return render(request, 'response_tem.html', {'form': form})
I want the help text for 'ans1' field to be the value of q1 field of request.user. How do I do it?
You can do it like this:
class ResponseForm(ModelForm):
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None) # popping user from known arguments
super(ResponseForm, self).__init__(*args, **kwargs)
if user:
self.fields['ans1'].help_text = "Help Text for {}".format(user.username)
class Meta:
model = ResponseModel
exclude = ('author', 'title','submit_count')
#login_required
def ResponseFormView(request):
if request.method == "POST":
form = ResponseForm(request.POST)
if form.is_valid():
submission = form.save(commit=False)
submission.author = request.user
submission.save()
return render(request, 'thanks.html', {})
else:
form = ResponseForm(user=request.user) # passing user as known argument
return render(request, 'response_tem.html', {'form': form})
Here, in the view I am passing the request.user as known argument when I am initiating Form Class's Object (marked with comment). Then in the Form, I am catching the user sent from view and updating the field's help text.