I have been woking in django for a while. Now i am facing some problems with built-in function in django. The error state that TypeError: 'bool' object is not callable. This kind of error happened because of statement 'print(request.user.is_authenticated())'.
Here below is source code:
def login_page(request):
form = LoginForm(request.POST or None)
#ensure user is logged in or not
print(request.user.is_authenticated())
if form.is_valid():
print(form.cleaned_data)
return render(request,"auth/login.html",{})
For LoginForm() is imported by my file forms.py
from django import forms
class ContactForm(forms.Form):
#first will be name which is variable
fullname = forms.CharField(widget=forms.TextInput
(attrs={"class":"form-control","placeholder":"Your fullname"}))
email = forms.EmailField(widget=forms.EmailInput
(attrs={"class":"form-control","placeholder":"Your Email"}))
content = forms.CharField(widget=forms.Textarea
(attrs={"class":"form-control","placeholder":"Your content"}))
def clean_email(self):
email = self.cleaned_data.get("email")
if not "gmail.com" in email:
raise forms.ValidationError("Email has to be gmail.com")
#return value of email to be stored
return email
class LoginForm(forms.Form):
username = forms.CharField()
password = forms.CharField()
yes what you want to do is:
print(request.user.is_authenticated)
without () because it is an built-in function
is_authenticated is an attribute of theUser model, not a method.
So, drop the method reference:
print(request.user.is_authenticated)
Related
views.py
def login_view(request):
form = LoginForm()
if request.method == 'POST':
user = form.authenticate_user()
if not user:
error(request, 'Wrong credentials!')
return render_to_response('login.html')
login(request, user)
context = user.id
return start(str(context))
return render_to_response('login.html', {'form': form})
models.py
class User(AbstractBaseUser):
phone = models.CharField(max_length=16, unique=True)
age = models.PositiveIntegerField(blank=True, null=True)
region = models.CharField(max_length=30, blank=True, null=True)
email = models.EmailField(unique=True)
first_name = models.CharField(max_length=30, unique=True)
last_name = models.CharField(max_length=30, unique=True)
USERNAME_FIELD = 'phone'
objects = UserManager()
forms.py
class LoginForm(forms.Form):
email = forms.CharField()
password = forms.CharField(
widget=forms.PasswordInput(render_value=False)
)
def clean(self):
user = self.authenticate_via_email()
if not user:
raise forms.ValidationError("Sorry, that login was invalid. Please try again.")
else:
self.user = user
return self.cleaned_data
def authenticate_user(self):
return authenticate(
email=self.cleaned_data['email'],
password=self.cleaned_data['password']
)
def authenticate_via_email(self):
"""
Authenticate user using email.
Returns user object if authenticated else None
"""
email = self.cleaned_data['email']
if email:
try:
user = User.objects.get(email__iexact=email)
if user.check_password(self.cleaned_data['password']):
return user
except ObjectDoesNotExist:
pass
return None
why it doesn't work?
Traceback:
AttributeError at /auth/
'LoginForm' object has no attribute 'cleaned_data'
Traceback:
views.py in login_view
user = form.authenticate_via_email()
forms.py in authenticate_user
email=self.cleaned_data['email'],
You need to call .is_valid() on form before accessing cleaned_data attribute.
There is not calling form.is_valid() in your views.py.
Also there is no populating of your form from POST data, you need to do it with form = LoginForm(request.POST) if your request.method is POST
You can also view the source:
full_clean() is respected for assigning self.cleaned_data, and full_clean() is called by property self.errors in is_valid() method. So you can track from the django source code what is wrong with yours.
You haven't called form.is_valid().
Inorder to access form.cleaned_data, the form validation should be done first.
Form validation is carried out only when form.is_valid() is called upon the form, which in turn returns a validated cleaned_data.
Also, on request.POST, your form is not getting data, because, for that, you need to initialise your form with request.POST, like
form = LoginForm(request.POST)
The return statement before the last render_to_response would also raise some errors, I presume.
You could read more about form validation here from the docs
I am working on my Checkout view with regular/guest user but getting hard time to come around the integrity error. Idea is to let guest users register with email only to checkout and I need to set the user email unique.
models.py
from django.conf import settings
from django.db import models
class UserCheckout(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, null=True, blank=True)
email = models.EmailField(unique=True)
def __unicode__(self):
return self.email
forms.py
from django import forms
from django.contrib.auth import get_user_model
User=get_user_model()
class GuestCheckoutForm(forms.Form):
email = forms.EmailField()
email2 = forms.EmailField(label='Verify Email')
def clean_email2(self):
email = self.cleaned_data.get("email")
email2 = self.cleaned_data.get("email2")
if email == email2:
user_exists = User.objects.filter(email=email).count()
if user_exists != 0:
raise forms.ValidationError("User already exists. Please login instead")
return email2
else:
raise forms.ValidationError("Please confirm emails addresses are the same.")
In my cart views this is how I've rendered my form.
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
email = form.cleaned_data.get("email")
user_checkout = UserCheckout.objects.create(email=email)
return self.form_valid(form)
else:
return self.form_invalid(form)
I've registered the model with admin and in admin it shows the error for duplication perfectly fine but from frontend I am getting error below:
IntegrityError at /checkout/
column email is not unique
Request Method: POST
Request URL: http://localhost:8000/checkout/
Django Version: 1.8.13
Exception Type: IntegrityError
Exception Value:
column email is not unique
Exception Location: C:\Users\Ali\ecomm\lib\site-packages\django\db\backends\sqlite3\base.py in execute, line 318
Python Executable: C:\Users\Ali\ecomm\Scripts\python.EXE
Python Version: 2.7.9
You create every time when a checkout occurs an new UserCheckout. And in all these entries it is only allowed that every email exists only once.
I don't think you want this. Because if a guest orders two times it isn't allowed because his email is already in the DB. And that's why you get this error.
The clean_<fieldname> methods of a Form are used to perform validation relative to single field. If you need validation with access to multiple fields, use the clean method. Check the documentation on form validation for a thorough explanation.
That would give:
class GuestCheckoutForm(forms.Form):
email = forms.EmailField()
email2 = forms.EmailField(label='Verify Email')
def clean_email(self):
email = self.cleaned_data["email"]
if User.objects.filter(email=email).exists():
raise forms.ValidationError("Please confirm emails addresses are the same.")
return email
def clean(self):
cleaned_data = super(GuestCheckoutForm, self).clean()
email = cleaned_data.get('email')
email2 = cleaned_data.get('email2')
if email and email2 and email != email2:
self.add_error('email2', forms.ValidationError('Please confirm emails addresses are the same.'))
EDIT: I believe I found out why you got an IntegrityError:
You are validation that no User with the given email is in the database, you should also be validating that no other UserCheckout with the given email is in the database. Replace if User.objects.filter(email=email).exists(): by if User.objects.filter(email=email).exists() or UserCheckout.objects.filter(email=email).exists():
I want to write a form that will display the user's email but allow them to change their password by entering their current password and their new password twice. I want to use a ModelForm, too.
I have the User:
# models.py
class User(AbstractBaseUser):
email = models.EmailField(unique=True)
And I've started on a form:
# forms.py
class ChangeAccountDetailsForm(forms.ModelForm):
class Meta:
model = User
fields = ('email',)
current_password = forms.CharField(widget=forms.PasswordInput)
password = forms.CharField(widget=forms.PasswordInput)
confirm_password = forms.CharField(widget=forms.PasswordInput)
I've created a simple view that only works with a GET request at the minute:
# views.py
def edit_account_details(request):
if request.method == 'GET':
account_form = ChangeAccountDetailsForm()
return render(request, 'freelancestudent/edit_account_details.html', {
{'form': account_form}
})
else:
pass
And a simple HTML file that simply calls {{form.as_p}}. When I run it as is I get the error unhashable type: 'dict' at {'form': account_form}. How can I display, then, the current user's email and allow functionality for changing password. Is this possible with a ModelForm or will I have to roll my own form and do all the logic myself?
Here :
return render(
request,
'freelancestudent/edit_account_details.html', {
{'form': account_form}
})
You have two sets of {}. The inner one defines a dict, the outer one defines a set, so it's equivalent to:
context = {'form': account_form}
whatever = set(context)
Now sets needs their values to be hashable (just like dict keys), and a dict is not hashable, hence your error message.
But anyway: render expects a dict, not a set, so what you want is:
return render(
request,
'freelancestudent/edit_account_details.html',
{'form': account_form}
)
Ok so I actually solved this one by accident and would simply like to understand what happened.
I have my own user registration form BaseCreationForm which extends a ModelForm and uses a UserProfile as its model. All the validation methods were working fine, but the save method was giving me grief. Whenever I tried to create a user (the profile is created in the view, I may refactor this), Django would tell me that "BaseCreationForm object has no attribute cleaned data".
BUT, when out of frustration and running out of ideas I added a simple "print self" statement before creating the user in the save() method, the problem disappeared and users are being created normally. Below are a couple of clean() methods that work, the save() method and a snippet from the view that calls the clean() and save() method.
clean() methods working normally
#example clean methods, both work beautifully
def clean_email(self):
email = self.cleaned_data["email"]
if not email:
raise forms.ValidationError(self.error_messages['no_email'])
try:
User.objects.get(email=email)
except User.DoesNotExist:
return email
raise forms.ValidationError(self.error_messages['duplicate_email'])
def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError(
self.error_messages['password_mismatch'])
return password2
save() method:
#save method requiring wizardry
def save(self, commit=True):
#This line makes it work. When commented, the error appears
print self
###
user = User.objects.create_user(
username=self.cleaned_data.get("username"),
first_name=self.cleaned_data["first_name"],
last_name=self.cleaned_data["last_name"],
email=self.cleaned_data["email"],
)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
And the view (some stuff left out):
class RegistrationView(FormView):
template_name = 'register.html'
form_class = BaseCreationForm
model = UserProfile
success_url = '/account/login/'
def form_valid(self, form):
form = BaseCreationForm(self.request.POST,
self.request.FILES)
user = form.save()
profile = user.get_profile()
profile.user_type = form.cleaned_data['user_type']
profile.title = form.cleaned_data['title']
profile.company_name = form.cleaned_data['company_name']
.
.
.
profile.save()
return super(RegistrationView, self).form_valid(form)
You shouldn't be re-instantiating the form inside the form_valid method. That's called when the form is already valid, and indeed the form is passed into the method. You should use that instead.
(Note that the actual error is because you haven't called form.is_valid() at all, but as I say above you shouldn't, because the view is already doing it.)
I am trying to program a Django CreateView (CBV), which takes instead of the user id the user email and determines (or creates) the user based on the email.
My model does not contain anything special:
class Project(models.Model):
name = models.CharField(_('Title'), max_length=100,)
user = models.ForeignKey(User, verbose_name=_('user'),)
...
My forms.py adds the additional email field to the form:
class ProjectCreateForm(forms.ModelForm):
email = forms.EmailField(required=True, )
class Meta:
model = Project
fields = ('name', ...,)
In my views.py, I am trying to determine if the user exists or should be created. In both cases, the user id should be saved as part of the Project instance.
class ProjectCreateDetails(CreateView):
form_class = ProjectCreateForm
template_name = '...'
success_url = reverse_lazy('login')
model = Project
def form_valid(self, form):
try:
user = User.objects.get(email=form.email)
except User.DoesNotExist:
user = User.objects.create_user(form.email, form.email, ''.join([random.choice(string.digits + string.letters) for i in range(0, 10)]))
user.save()
form.instance.user = user
return super(ProjectCreateDetails, self).form_valid(form)
However I am facing an error that the 'Solution' object has no attribute 'email'.
Do I need to switch to a FormView instead of a CreateView?
You get the error 'Solution' object has no attribute 'email' because form.email is invalid. Validated data is never available as attributes of a form or model form. When forms (including model forms) are valid, the successfully validated data is available in the form.cleaned_data dictionary.
Note that you don't need to call user.save(). The create_user call has already added the user to the database. You don't have to generate a random password either -- if password is None, then create_user will set an unusable password.
Finally, make sure that you do not include the user field in the ProjectCreateForm. You probably do not, but your code says fields = ('name', ...,) so I can't tell for sure.
Put it together and you get the following (untested) code:
def form_valid(self, form):
try:
user = User.objects.get(email=form.cleaned_data['email'])
except User.DoesNotExist:
user = User.objects.create_user(form.cleaned_data['email'], form.cleaned_data['email'])
form.instance.user = user
return super(ProjectCreateDetails, self).form_valid(form)