i am working on login page but my form always gives me error, please find my code below, please see view.py it response always go to else statment of "if form.is_valid():" condition. please help
here you can see form.py
from django.contrib.auth.models import User
from django import forms
class LoginForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = User
fields = ['username', 'password']
this is my view.py
def login_view(request):
template_name = 'user/login.html'
form_class = LoginForm
if request.method == "POST":
form = form_class(data=request.POST)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user = authenticate(username=username, password=password)
try:
login(request, user)
return redirect('user:profile')
except:
form = form_class(None)
return render(request, template_name, {'form': form, 'custom_error': 'Error'})
else:
return HttpResponse("<h1>Data is invalid</h1>")
else:
if request.user.is_authenticated():
return redirect('user:profile')
else:
form = form_class(None)
return render(request, template_name, {'form': form,})
user/login.html
{% block body %}
<div class="section">
<div class="container">
<div class="row">
<form class="form-horizontal" role="form" action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="col-md-5">
<img src="{% static 'user/images/favicon.png' %}" class="img-responsive">
</div>
<div class="col-md-6">
{% include 'user/form-template.html' %}
<div class="col-sm-offset-2 col-sm-10" align="right">
<button type="submit" class="btn btn-default" autofocus>Sign In</button>
</div>
</div>
</form>
</div>
</div>
</div>
{% endblock %}
and finally this is my form-template.html file
{% for field in form %}
<div class="col-md-8">
<div class="col-md-4">
<label>{{ field.label_tag }} </label>
</div>
<div class="col-md-4">
{{ field }}
<div>
<span>{{ field.errors }}</span>
</div>
<div>
<span class="text-danger small">{{ custom_error }}</span>
</div>
</div>
</div>
{% endfor %}
If you are using ModelForm, you are going to operate on django model objects, creating, updating, etc. If you are only trying to login, use Form instead.
Thanks its solved, I just Changed My Form no it looks like this.
class LoginForm(forms.Form):
username = forms.CharField()
password = forms.CharField(widget=forms.PasswordInput)
now i am not using built-in form and i also changed ModelForm to Form.
Related
I'm using the basic django registration form and I'm not getting any errors displayed. I've seen a bunch of answers and nothing is working for me. I'm not sure if it's because I have custom css for the page or bootstrap or something else. Basically how do I display the errors in this particular case.
Here's my form:
<div class="form-content">
<h1>Sign Up</h1>
{% if user.is_authenticated == False %}
<form method="POST">
{% csrf_token %} {{form.as_p}}
<button class="btn form-btn">Sign Up</button>
<h4><span>or</span></h4>
<a
class="btn google-btn"
href="{% provider_login_url 'google' %}"
role="button"
style="text-transform: none; width: 100%"
>
<img
width="20px"
style="margin-bottom: 3px; margin-right: 5px"
alt="Google sign-in"
src="https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/Google_%22G%22_Logo.svg/512px-Google_%22G%22_Logo.svg.png"
/>
Sign up with Google
</a>
</form>
{% else %}
<p>You're already registered...</p>
{% endif %}
</div>
Here's my view:
class UserRegistration(generic.CreateView):
form_class = RegisterForm
template_name = 'registration/registration.html'
def form_valid(self, form):
user = form.save()
form.registration_notification()
login(self.request, user, backend='django.contrib.auth.backends.ModelBackend')
return redirect(self.request.GET.get('next'))
and form:
class RegisterForm(UserCreationForm):
email = forms.EmailField()
first_name = forms.CharField(max_length=100)
last_name = forms.CharField(max_length=100)
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email', 'password1', 'password2')
def registration_notification(self):
email = self.cleaned_data['email']
username = self.cleaned_data['username']
if self.is_valid():
registration_notification_task.delay(email, username)
I'm not sure where to return the errors or where to validate the form and no answers for other questions have helped my situation. Now when I submit an invalid form there are no errors the page just doesn't submit. There's not even an error in the network tab so it's probably happening on the html side.
Updating my post following comments below:
**forms.py** (dont forget the import bit)
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
class RegisterForm(UserCreationForm):
class Meta:
model = User
fields = ["username", "email", "password1", "password2",]
views.py
def register_user(request):
if request.method == "POST":
form = RegisterForm(request.POST)
if form.is_valid():
new_user = form.save()
new_user = authenticate(username=form.cleaned_data['username'],
password=form.cleaned_data['password1'],)
login(request, new_user)
messages.success(request,("Registration succesful!"))
return HttpResponseRedirect("/home")
else:
form = RegisterForm()
return render(request,'main/registration/register_user.html',{'form':form})
registration template
{% load crispy_forms_tags %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-md-5 mx-auto">
<div id="second">
<div class="myform form ">
<div class="logo mb-3">
<div class="col-md-12 text-center">
<h1 >Signup</h1>
</div>
</div>
<form method="POST" action = "{% url 'register_user' %}" class="form-group">
{% csrf_token %}
{{ form| crispy }}
<div class="col-md-12 text-center mb-3">
<button type="submit" class=" btn btn-block mybtn btn-primary tx-tfm">Let's do it!</button>
</div>
<div class="col-md-12 ">
<div class="form-group">
<p class="text-center">Already have an account?</p>
</div>
</div>
</div>
</form>
</div>
</div>
{% endblock %}
I'd love to write a form where a user can change their data. So I have a User model and a UserProfile extension model, the last one looks like this:
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
info = models.TextField('информация')
def get_absolute_url(self):
return reverse('user_profile', args=[str(self.user.username)])
How to generate a form where my user attribute would have all its parameters like username, email, first_name, last_name to be changed? So I could do something like this in the template:
{% extends "layout.html" %}
{% block content %}
<h2>{{ title }}</h2>
<div class="row">
<form method="POST" action="{% url 'profile_edit' user.username %}" class="col s12">
{% csrf_token %}
{{ form.non_field_errors }}
<div class="row">
<div class="input-field col s6">
{{ form.user.username }}
{{ form.user.username.label_tag }}
{% if form.user.username.errors %}
<span class="helper-text">{{ form.user.username.errors }}</span>
{% else %}
<span class="helper-text">{{ form.user.username.help_text }}</span>
{% endif %}
</div>
<div class="input-field col s6">
{{ form.user.email }}
{{ form.user.email.label_tag }}
{% if form.user.email.errors %}
<span class="helper-text">{{ form.user.email.errors }}</span>
{% else %}
<span class="helper-text">{{ form.user.email.help_text }}</span>
{% endif %}
</div>
</div>
<div class="row">
<div class="input-field col s6">
{{ form.user.first_name }}
{{ form.user.first_name.label_tag }}
</div>
<div class="input-field col s6">
{{ form.user.last_name }}
{{ form.user.last_name.label_tag }}
</div>
</div>
<div class="row">
<div class="input-field col s12">
{{ form.info }}
{{ form.info.label_tag }}
</div>
</div>
<button class="btn waves-effect waves-light blue" type="submit" name="action">Изменить</button>
<a class="waves-effect waves-light btn-flat" href="{% url 'password_change' %}">Сменить пароль</a>
</form>
</div>
{% endblock %}
And finally, this is my view, obviously incorrect:
from django.shortcuts import get_object_or_404
from django.views import generic
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from datetime import datetime
from .models import *
class UserEditView(LoginRequiredMixin, UserPassesTestMixin, generic.UpdateView): # still does not work
fields = '__all__'
template_name = 'accounts/user_form.html'
def get_object(self, queryset=None):
return get_object_or_404(UserProfile, user=self.request.user)
def test_func(self):
return self.request.user == self.get_object().user
def form_valid(self, form):
response = super().form_valid(form)
user = User.objects.get_by_natural_key(form.cleaned_data['user'])
user.email = form.cleaned_data.get('email')
user.first_name = form.cleaned_data.get('first_name')
user.last_name = form.cleaned_data.get('last_name')
user.userprofile.info = form.cleaned_data.get('info')
user.save()
return response
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = 'Редактировать профиль'
context['year'] = datetime.now().year
return context
All of this does nothing but produces status 200 response.
Some of solutions:
Create 2 forms: UserForm and UserProfileForm.
profile_form = UserProfileForm(request.POST, instance=request.user.profile)
user_form = UserForm(request.POST, instance=request.user)
if profile_form.is_valid() and user_form.is_valid():
profile_form.save()
user_form.save()
....
Without 2 forms:
Write your own method inside form_valid and pass variables from request.POST to your profile
Also, you may check this user profile in drf
Maybe it might be an oversight but I do not know the point where I am getting it wrong.
My form is rendered correctly but it keeps failing without errors.
forms.py
from crispy_forms.helper import FormHelper
from django import forms
from django.utils.translation import ugettext as _
class BeneficiaryForm(forms.Form):
"""Add Beneficiary template form"""
# Form fields
account_currency = forms.ModelChoiceField(queryset=Currency.objects.all(), empty_label=_('Select account currency'))
bank_account_type = forms.CharField(max_length=50, required=False)
email = forms.CharField(max_length=150, required=False, help_text=_("We'll notify them when a transfer is made"))
name = forms.CharField(max_length=50, required=False)
swift_code = forms.CharField(max_length=11, required=False,
widget=forms.TextInput(attrs={'placeholder': 'MSBCCNBJ001'}))
iban = forms.CharField(max_length=34)
def __init__(self, *args, **kwargs):
super(BeneficiaryForm, self).__init__()
self.helper = FormHelper()
self.helper.form_show_labels = False
views.py
def beneficiaries(request):
"""View function for viewing Beneficiaries and adding a Beneficiary instance"""
if request.method == 'POST':
form = BeneficiaryForm(request.POST)
if form.is_valid():
print("Form is valid")
print(request.POST['bank_account_type'])
print(request.POST['email'])
print(request.POST['name'])
print(request.POST['iban'])
print(request.POST['swift_code'])
print("Form is invalid")
print(form.errors)
form = BeneficiaryForm()
context = {
'form': form
}
return render(request, 'dashboard/beneficiaries.html', context)
and in my rendered form. I have this block to show errors and nothing shows up
HTML
<form action="{% url 'beneficiary_index' %}" method="post">
{% csrf_token %}
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-danger">
{% if field != '__all__' %}
<strong>{{ field.label }}:</strong>
{% endif %}
{{ error|escape}}
</div>
{% endfor %}
{% endfor %}
{% endif %}
<div class="form-group">
<div class="form-label-group">
<label class="form-label" for="default-01">{% trans "Account currency" %}</label>'
</div>
{{ form.account_currency | as_crispy_field }}
</div>
<div class="form-group">
<div class="form-label-group">
<label class="form-label" for="default-01">{% trans "Bank Account type" %}</label>
</div>
{{ form.bank_account_type | as_crispy_field }}
</div>
<div class="form-group">
<div class="form-label-group">
<label class="form-label" for="default-01">Their email(optional)</label>
</div>
{{ form.email | as_crispy_field }}
</div>
<div class="form-group">
<div class="form-label-group">
<label class="form-label" for="default-01">Full name of account holder</label>
</div>
{{ form.name | as_crispy_field }}
</div>
<h6>{% trans "Recipient Bank Information" %}</h6>
<hr>
<div class="form-group">
<div class="form-label-group">
<label class="form-label" for="default-01">Swift code</label>
</div>
{{ form.swift_code | as_crispy_field }}
</div>
<div class="form-group">
<div class="form-label-group">
<label class="form-label" for="default-01">IBAN</label>
</div>
{{ form.iban | as_crispy_field }}
</div>
<div class="form-group">
<button class="btn btn-lg btn-primary btn-block">{% trans 'Add Beneficiary' %}</button>
</div>
</form>
This is the Html to the form. I have just tried all the suggestions and still without the errors.
Form is Invalid is the only thing printed on screen without the form.errors
You need to create the GET request empty form in the else block or return the request in the POST block.
You are re-creating an empty form before returning the response.
def beneficiaries(request):
"""View function for viewing Beneficiaries and adding a Beneficiary instance"""
if request.method == 'POST':
form = BeneficiaryForm(request.POST)
if form.is_valid():
print("Form is valid")
print(request.POST['bank_account_type'])
print(request.POST['email'])
print(request.POST['name'])
print(request.POST['iban'])
print(request.POST['swift_code'])
# do other stuff like saving to DB
# then redirect
else:
print("Form is invalid")
print(form.errors)
elif request.method == 'GET':
form = BeneficiaryForm()
else:
# maybe return 404
pass
context = {
'form': form
}
return render(request, 'dashboard/beneficiaries.html', context)
Or maybe you can try Class Based Views, to avoid the if-else block for GET and POST requests.
Try adding this to the place you want the error to appear (In the HTML file)
Better if you use it inside the tags.
{% if form.errors %}
<p>Form is invalid</p>
{% endif %}
I Hope this answers the question.
When i click on the sell product link from homepage it redirects to the login page and after login done it redirects to the homepage and i have to again click on the sell product link to fill the form.I want to redirect to the sell_product page after login instead of homepage.How can i do that ?? How can i redirect to the different pages from one signin url.
urls.py
path('signin/user/',views.users_signin,name='users_signin'),
path('sell/product/',views.sell_product,name='sell_product'),
views.py
def users_signin(request):
if request.method == "POST":
form = UserSigninForm(request.POST)
username = form['username'].value()
password = form['password'].value()
user = authenticate(username=username,password=password)
login(request,user)
return redirect('shop:home')
else:
form = UserSigninForm()
return render(request,'shop/users_signin.html',{'form':form})
def sell_product(request):
if request.user.is_authenticated:
if request.method == "POST":
form = SellProductForm(request.POST,request.FILES)
if form.is_valid():
myproduct = form.save(commit=False)
myproduct.seller = request.user
myproduct.save()
messages.success(request,'Your Product has been posted successfully.!!')
return redirect("shop:home")
else:
form = SellProductForm()
return render(request,'shop/sell_product.html',{'form':form})
else:
messages.error(request,'please login first')
return redirect('shop:users_signin')
sell_product.html
{% extends "shop/base.html" %}
{% load bootstrap4 %}
<title>{% block title %}Sell a Product{% endblock %}</title>
{% block content %}
<div class="container">
<div class="row">
<div class="col-lg-6 offset-lg-3 col-sm-10 offset-sm-1">
<div class="card my-5">
<div class="card-header text-center">
Sell Your Product
</div>
<div class="card-body">
<form action="{% url 'shop:sell_product' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{% bootstrap_form form %}
<input type="submit" class="btn btn-success text-center w-100 mb-3" value="Submit">
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
base.html
<li class="nav-item">
<a class="nav-link" href="{% url 'shop:sell_product' %}">Sell a Product</a>
</li>
forms.py
class SellProductForm(forms.ModelForm):
class Meta:
model = Product
fields = ['name','image','category', 'description', 'brand', 'quantity', 'price', 'shipping_fee']
class UserSigninForm(forms.Form):
username = forms.CharField()
password = forms.CharField(widget=forms.PasswordInput)
You may specify the next parameter in the url to set the redirect page after login.
Try
return redirect('%s?next=%s' % (reverse('shop:users_signin'), request.path))
See https://docs.djangoproject.com/en/2.2/topics/auth/default/#limiting-access-to-logged-in-users-that-pass-a-test
You may also use a #login_required decorator so as to omit the 'if-else` block that ensures the authentication.
I'm new to django and I've been following a tutorial to help me create my project. My problem is that the form and its fields don't show up on my html page.
line of code from my html file
<form action="admin/signup/" method="post">
<div class="form-horizontal form-label-left">
{% csrf_token %}
{% for field in signupForm %}
<p>
{{ field.label_tag }}<br>
{{ field }}
{% if field.help_text %}
<small style="color: grey">{{ field.help_text }}</small>
{% endif %}
{% for error in field.errors %}
<p style="color: red">{{ error }}</p>
{% endfor %}
</p>
{% endfor %}
<div class="ln_solid"></div>
<div class="form-group">
<div class="col-md-9 col-sm-9 col-xs-12 col-md-offset-4">
<button class="btn btn-primary">Cancel</button>
<button type="submit" class="btn btn-success">Submit</button>
</div>
</div>
</div>
</form>
my signup form class
class SignUpForm(UserCreationForm):
usertype = forms.CharField(max_length=10)
userID = forms.CharField(label="User ID")
class Meta:
model = User
fields = (
'username', 'first_name', 'last_name', 'email',
'password1', 'password2', 'userID', 'usertype')
and my signup page view
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
user = form.save()
user.refresh_from_db()
user.profile.usertype = form.clean_data.get('usertype')
user.profile.userID = form.clean_data.get('userID')
user.save()
else:
form = SignUpForm()
context = {
'signupForm' :form
}
return render(request, 'admin.html', context)
any possible solutions and suggestions are appreciated, thanks!
May be indentation require in SignUpForm. Is it!!