Having issues with Django forms - python

I just started developing with Django and I'm having a bit of an issue with the use of a form I've created.
Currently I have a model named SignUp which allows users to "sign up" on the site by inputting their first and last names and their email address.
A feature I'm trying to implement deletes a user who is already signed up by the user submitting the email address they signed up with.
I have a form set up that's just a simple email field but I can't seem to figure out how to get my view to match up the form to the user and then successfully delete the user from the database.
Here is the code for the form:
class DeleteUserForm(forms.Form):
email_address = forms.EmailField()
And here is the code for the view:
class DeleteUserView(generic.edit.FormView):
template_name = 'signups/delete_user_form.html'
form_class = DeleteUserForm
success_url = '/users/delete/success/'
def form_valid(self, form):
for user in SignUp.objects.all():
if user.email == form: # The email attribute holds the user's
user.delete() # email address and the form should be
# the address the user submitted to be
# deleted?
return redirect(self.success_url)
return redirect('/users/delete/failure/')
Every time I try to submit an email address, I get no match, no user is deleted, and I just get redirected to my failure directory.
Anybody have an idea of what's going on?
Thanks

Using Kamil's logic, I rewrote the field lookup and this code works:
duplicates = SignUp.objects.filter(email__iexact=form.cleaned_data['email_address'])
if duplicates:
duplicates.delete()
return redirect(self.success_url)
But does anyone know why the code I was using before didn't work?

Simplest solution:
duplicates = SignUp.objects.filter(email=form.cleaned_data['email_address'])
if duplicates:
duplicates.delete()
return redirect(self.success_url)
return redirect('/users/delete/failure/')
Right, fixed the relation lookup.

You can access field values via form.cleaned_data dictionary:
if user.email == form.cleaned_data['email_address']:

Related

how to login in django from custom model

This is my table of register user photo
This is model.py
class SignupUser(models.Model):
name = models.CharField(max_length=100)
username = models.CharField(max_length=20)
email = models.CharField(max_length=100)
password = models.CharField(max_length=20)
def __str__(self):
return self.username
this is my views.py for login my account page through this register user
def login_page(request):
'''
what code i write here ??
'''
context = {'form': SignupForm}
return render(request, 'signup.html', context)
please solve my views.py code on my login_page method .What i write here to login in this user profile ?
from django.contrib.auth import logout, login as auth_login, authenticate
import logging as L
def login_page(request):
post_data = request.POST
user = authenticate(username=post_data['email'], password=post_data['password'])
if user is None:
L.warning('Authentication error wrong credentials')
return HttpResponseRedirect('/')
else:
auth_login(request, user)
L.INFO('Authentication ok')
return HttpResponseRedirect('/')
well there you can use the django build ins for the login and logoout, your code should look sth like that
I'm not sure you are doing this in the correct way. Django already provides some mechanics to create some custom user models.
You should create a model that extends django.contrib.auth.models.AbstractUser as described in this part of the documentation.
You can see that the AbstractUser class already have all the field you need.
Once you have this model, you should register it as the User model in your settings files as mentioned here.
You can then use the authentication system implemented by Django and you should be fine.
If the fields provided by AbstractUser are not the one you are looking for, you can take a step back. You will need to override from django.contrib.auth.base_user.AbstractBaseUser, possibly also from django.contrib.auth.models.PermissionsMixin if you need the permissions system.
With a little bit of tweaks and configuration, Django's built-in views and forms should work with your new model.
Managing initial user model is a lot of configuration and can be difficult to achieve in the first place. But by taking the time to understand how all of those classes and configuration keys work together, you should not have any problem with this. Don't forget to check the documentation for the auth system. It is quite heavy, but with a little bit of work you should find everything you need in it.

Django CreateView with two forms at same page

I'm using Django and trying to display the detail of the person who has posted the data. So basically showing the username of the person who has posted the 'thing' defined in models.py
In views.py I'm trying:
def thing_detail_view(request, pk):
thing_detail = Thing.objects.get(pk=pk)
user = User.objects.get(request.user)
return render(request, 'thing_detail.html', {'thing_detail': thing_detail, 'user': user})
Im getting error:
'User' object is not iterable
But I know I should not use request.user because thats basically means the user who is having current session or currently logged in. Any idea how can I get the username of the user who has posted the data of a particular 'pk' and show it in the html?
I think you have to use userId = thing_detail.userId instead of request.user
userId can be your primery key for User Model

Issue with ModelForm and related objects

I have come to an impasse when using a ModelForm.
I'm extending the User model that comes with Django, and I'm also using a ModelForm so the user can edit it.
Following the same example in the documentation, I would have this code.
models.py
class Employee(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
# In this case, department is optional, so I have set 'blank' and 'null' to True.
department = models.CharField(max_length=100, blank=True, null=True)
forms.py
class DepartmentForm(ModelForm):
class Meta:
model = Employee
fields = ['department',]
The problem comes at the view. I found that I need to pass an instance of the model to the form so the save() function works without having to customize it, but of course, user.employee has not been created yet, therefore it throws an error.
views.py
def DepartmentView(request):
# Here is the issue.
department = request.user.employee
if request.method == 'POST':
# I need to pass the instance here.
form = DepartmentForm(request.POST, instance=department)
if form.is_valid():
form.save()
else:
# And also here so it autocompletes the form.
form = DepartmentForm(instance=department)
return render(request, 'employee.html', {'form': form})
It works if I manually add a value to user.employee.department through the shell and then reload the page, otherwise the error is as follow.
RelatedObjectDoesNotExist at [something]
User has no employee.
Or something like that... I'm sorry, I didn't try the code above so the error could be a little different, but the concept is exactly the same.
I'm also sorry if this has been asked before. I did a Google search and couldn't find an answer to this issue.
You could use get_or_create to fetch the employee from the db, or create it if it doesn't exist.
department, created = Employee.objects.get_or_create(user=request_or_user, department='')
if request.method == 'POST':
form = DepartmentForm(request.POST, instance=department)
...
Another option is to use a signal, so that the related model is created when the user is created. Then you can assume that the employee already exists, and you can use request.user.employee instead of get_or_create.

Convert all CharField Form Field inputs to lowercase in Django forms

I am using a Django form for user signup, where the user is able to enter a coupon code. I want all characters entered in the coupon code field to be converted to lowercase. I've tried using .lower() in the save method, in a custom cleaning method, and in a custom validator, but am having no luck with those approaches. Below is my code.
class StripeSubscriptionSignupForm(forms.Form):
coupon = forms.CharField(max_length=30,
required=False,
validators=[validate_coupon],
label=mark_safe("<p class='signup_label'>Promo Code</p>")
def save(self, user):
try:
customer, created = Customer.get_or_create(user)
customer.update_card(self.cleaned_data["stripe_token"])
customer.subscribe(self.cleaned_data["plan"], self.cleaned_data["coupon"].lower())
except stripe.StripeError as e:
# handle error here
raise e
As mentioned above, I've also tried a cleaning method, but this doesn't work either:
def clean_coupon(self):
return self.cleaned_data['coupon'].lower()
The solution is to create a custom form field, which allows you to override the to_python method, in which the raw values from the form fields can then be modified.
class CouponField(forms.CharField):
def to_python(self, value):
return value.lower()
class StripeSubscriptionSignupForm(forms.Form):
coupon = CouponField(max_length=30,
required=False,
validators=[validate_coupon],
label=mark_safe("<p class='signup_label'>Promo Code</p>")
)
Try using a css text-transform with widget in your form like this:
class StripeSubscriptionSignupForm(forms.Form):
coupon = forms.CharField(max_length=30,
required=False,
validators=[validate_coupon],
label=mark_safe("<p class='signup_label'>Promo Code</p>")
widget=TextInput(attrs={'style': 'text-transform:lowercase;'})
)
I came across this problem myself when working on ensuring that the email field in the user model was only saved as lowercase. The advantage to the method I outline below is that you can control the formating of each field in the form - as against the selected answer above, which will convert all fields to lowercase regardless of whether you wish so or not.
The issue for me and I believe for the OP above is that the cleaned values are now indeed in lower case, however the HTML page (the one rendered after the validation and cleaning) shows the pre-cleaned value (i.e. still in uppercase), which would confuse the user. What is happening is that the the form field value is still as per initial data i.e. X#Y.com and the cleaned data is actually x#y.com .
After processing the submitted form:
>>>user_form.cleaned_data['email']
'x#y.com'
and
>>>user_form['email'].value()
'X#Y.com'
The template uses the user_form['email'].value() instead of the value provided by user_form.cleaned_data['email'], so the user thinks his email has been saved in the uppercase form whereas really it has been saved in lowercase.
In such cases, the simplest way to present the user_form back to the client with the cleaned fields appearing in the template is to just reload the saved form directly after saving. As per the following two examples (one saving to the database one not saving to the database).
forms.py
from django.contrib.auth.models import User
class UserForm(forms.ModelForm):
"""
UserForm is a simple form to allow a user to change his/her name and email.
"""
class Meta:
model = User
fields = ['first_name', 'last_name', 'email']
def clean_email(self):
"""
ensure that email is always lower case.
"""
return self.cleaned_data['email'].lower()
in views.py
def post(self, request):
user_form = UserForm(request.POST, instance=request.user)
if user_form.is_valid():
user_form.save() # using the provided save from Modelform in this case
user_form = UserForm(instance=request.user) # reload the amended user data
return render(request, 'myApp/user_details.html',{'user_form': user_form})
The key line here is in views.py,the user_form = UserForm(instance=request.user), where the form is reloaded. The effect here is to repopulate the form with the cleaned, (and in this case saved) data before it is presented to the user.
Now you can change every charfield in the form to lowercase by having the appropriate clean_fieldname call for those fields.
Note: if you are not interacting with a database (or just donĀ“t wish to reload from the database) you can repopulate the form as follows:
def post(self, request):
user_form = UserForm(request.POST) #gather the post'ed data
if user_form.is_valid():
user_form.process() # process the gathered cleaned data
user_form = UserForm(
{'email': user_form.cleaned_data['email'],
'first_name': user_form.cleaned_data['first_name'],
'last_name': user_form.cleaned_data['last_name'],}
) # reload the form
return render(request, 'myApp/user_details.html',{'user_form': user_form})
As a slight optimization here, you can use the built in check :
if user_form.has_changed():
following on from the is_valid() check (or in conjunction with it) -usually there is no need to save or process a form if nothing has changed on the form.

valueError in modelforms

I'm using modelforms for getting playlist and its items. It also contains login script. I'm trying to set the currently logged in user to the user model.
You can see this thing I've posted before
How to avoid this dropdown combo box?
class playlistmodel(models.Model):
user = models.ForeignKey(User)
title = models.CharField(max_length=200)
def __unicode__(self):
return self.title
class itemsmodel(models.Model):
playlist = models.ForeignKey(playlistmodel)
item = models.TextField()
def __unicode(self):
return self.item
class playlistform(ModelForm):
class Meta:
model = playlistmodel
exclude = {'user'}
class itemsform(ModelForm):
class Meta:
model = itemsmodel
exclude = {'playlist'}
Here is the playlist view:
def playlistview(request):
if request.method == 'POST':
form = playlistform(request.POST)
if form.is_valid():
data = form.save(commit=False)
data.user = request.user
data.save()
return render_to_response('playlist.html', {'data': data})
else:
form = playlistform()
return render_to_response('playlist.html', {'form': form, 'user': request.user}, context_instance=RequestContext(request))
Playlist.html file:
https://gist.github.com/1576136
Error Page:
https://gist.github.com/1576186
But I'm getting ValueError:
Exception Type: ValueError Exception Value: Cannot assign "<django.utils.functional.SimpleLazyObject object at 0x7f0234028f50>": "playlistmodel.user" must be a "User" instance
Traceback: Local vars --- data.user = request.user
Here is my settings.py
https://gist.github.com/1575856
Thank you.
I know this post is old, but if anyone gets here with the same problem, the answer is that request.user is actually a wrapper for django's auth.user.
So request.user is a SimpleLazyObject, and it's purpose is avoiding unnecessary instantiation, and also implementing a simple user caching mechanism.
To access the actual user (and instantiate it, when accessing the first time), you need to do:
auth.get_user(request)
This will give you an instance of auth.user.
If you need more detail on what's going on inside, see this post.
difficult to tell, but i would try this in your playlistview:
form = playlistform(request, request.POST, instance=playlistmodel)
maybe you can ommit the last parameter (instance=playlistmodel), because this would only be in need if you change an existing object
Hope this helps...
I have the very same problem, but it only arises when no user is logged in (expecting an AnonymousUser instance). At least when my superuser is logged in, I found no problem.
Despite I have not found a solution yet, maybe you'll find a clue in this answer
Well, now I've realised that in my case AnonymousUser should be stored as null in the db, but leave this answer to post the clue link (have no permission yet to leave comments).
Hope it helps!

Categories

Resources