django default Authenticaiton form shows username rather than email - django

I implemented my own user login form with django like below
from django.contrib.auth.forms import AuthenticationForm
class CustomUserLoginForm(AuthenticationForm):
class Meta:
model = CustomUser
fields = ('email', 'password')
then as a view this is what I have:
from rest_auth.views import LoginView
from users.forms import CustomUserLoginForm
class CustomLoginView(LoginView):
def get(self, request):
form = CustomUserLoginForm()
return render(request, "api/test_template.html", context={"form": form})
in my template then, I am calling {{form.as_p}} in <form> tag to show the form input details.
However, by default, this shows the username and password forms. How can I replace the username with the email?
in the rest-auth, browserable api, both the username and the email are present so I know that I can do this since I am using the rest-auth LoginView as backend.
Can I manually unpack {{form}} since later I would still like to style this form. How can I do this?
update
I unpacked the form in `api/test_template.html myself which now looks like the below:
{% block content %}
<div class="container">
<form method="POST">
{% csrf_token %}
<div>
<label for="{{ form.email.id_for_label }}">Email: </label>
<input{{ form.email }}>
</div>
<div>
<label for="{{ form.password.id_for_label }}">password: </label>
<input type="password" {{ form.password }}>
</div>
<button style="background-color:#F4EB16; color:blue" class="btn btn-outline-info" type="submit">Login</button>
</form>
Don't have an account? <strong>register here</strong>!
</div>
{% endblock %}
this works, however, rest-auth framework still require the username to not be empty. how can I change that, to ignore the username?
my user model
from django.contrib.auth.models import AbstractUser
from django.db import models
class CustomUser(AbstractUser):
def __str__(self):
return self.email

You should set USERNAME_FIELD='email' on your CustomUser model.
There is nice blogpost on How to use email as username.

Related

How to use Django-simple-captcha on the admin login page?

I would like to add captcha on my django login form using Django Simple Captcha found here: http://code.google.com/p/django-simple-captcha/
This works great if you create a new form but I'm using the django.contrib.auth.forms the one that comes with django. Any idea how I might be able to implement captcha with the existing django auth views or any ways? Thank you!
Please do not suggest using Google reCaptcha.
My urls.py
from django.contrib.auth import views as auth_views
urlpatterns = [
path('login/', auth_views.LoginView.as_view(template_name='login.html'), name='login')
,...
]
My login.html
<form class="fadeIn second" method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary"> Login </button>
</form>
My Forms.py
from captcha.fields import CaptchaField
class MyFormCaptcha(forms.Form):
captcha = CaptchaField()
This video and this GitHub project solved my problem. You can customize the project code according to your needs. For me it is as follows.
My urls.py
urlpatterns = [
...
path('captcha/',include('captcha.urls')),
path('submit',submit,name='submit')
]
My forms.py
from captcha.fields import CaptchaField
class MyForm(forms.Form):
captcha=CaptchaField()
My login.html
<form action="/submit" method="post">
{% csrf_token %}
<div>
<label for="fullname">Full Name</label>
<input type="text" id="fullname" name="fullname">
</div>
<br>
<div>
<label for="email">Email</label>
<input type="text" id="email" name="email">
</div> <br>
{{form.captcha}}
<button type="submit">Submit</button>
</form>
My views.py How to log a user in?
from django.contrib.auth import authenticate, login
def test(request):
form=MyForm()
return render(request,'captcha/home.html',{'form':form})
def submit(request):
if request.method == 'POST':
form=MyForm(request.POST)
if form.is_valid():
name=request.POST['fullname']
email=request.POST['email']
print('success')
print(name)
print(email)
user = authenticate(request,username=username,password=password)
if user is not None:
login(request, user)
return redirect('/homepage') # Redirect to a success page.
else:
# Return an 'invalid login' error message.
print('fail')
messages.success( request,f 'login failed! username or passwoed is wrong!'
return redirect('login')

Get error message from imported/external validator to print django

I am trying to build a simple user registration page. I want it to include a captcha for validation purposes. I am using django-simple-captcha for this purpose. (If there's a better library, tell me...)
So far everything is working great, EXCEPT that when a captcha is incorrect the user is not notified--they are simply returned to the registration screen. How can I get a specific ValidationError message printed when the captcha is invalid? (I'm also using django-crispy-forms, if that makes any difference)
template:
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Registration</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Sign Up</button>
</div>
</form>
<div class="border-top pt-3">
<small class="text-muted">Already Have An Account?<a class="ml-2" href="{% url 'login' %}">Log in</a></small>
</div>
</div>
{% endblock content %}
form model:
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(validators=[validate_email])
captcha = CaptchaField()
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2'] # including 'captcha here didn't seem to make a difference
and the view:
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
if form.is_valid():
*do unrelated things*
return redirect('login')
else:
form = UserRegisterForm()
return render(request, 'register-template-url', {'form': form})
from simplecaptcha.fields import CaptchaField----
if you are importing CaptchaField like this it will work. If it not works just simply do 1 change as shown below
from simplecaptcha import captcha,captchaform
#captchaform('captcha')
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(validators=[validate_email])
captcha = CaptchaField()
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2','captcha']

How to add email address in signup_form.html - Django-crispy-forms

My signup_form.html is as below, is there any way to add a email address in this form without changing views.py of back-end code?, I would like to let user fill in email adress when he is registering,
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<div class="row">
<div class="col-md-8 col-sm-10 col-12">
<form method="post" novalidate>
{% csrf_token %}
<input type="hidden" name="next" value="{{ next }}">
{{ form|crispy }}
<button type="submit" class="btn btn-success">Sign up</button>
</form>
</div>
</div>
{% endblock %}
If u use standard built in Django registration form- you can overwrite it like this:
from django.contrib.auth.forms import UserCreationForm
class UserCreateForm(UserCreationForm):
email = forms.EmailField(required=True,
label='Email',
error_messages={'exists': 'Oops'})
class Meta:
model = User
fields = ("username", "email", "password1", "password2")
def save(self, commit=True):
user = super(UserCreateForm, self).save(commit=False)
user.email = self.cleaned_data["email"]
if commit:
user.save()
return user
def clean_email(self):
if User.objects.filter(email=self.cleaned_data['email']).exists():
raise ValidationError(self.fields['email'].error_messages['exists'])
return self.cleaned_data['email']
And next I guess if u said u does not have a view for registration (if I understand correctly) - u have similar string in your urls:
from django.views.generic.edit import CreateView
from django.contrib.auth.forms import UserCreationForm
urlpatterns = [
path('register/', CreateView.as_view(
template_name='register.html',
form_class=UserCreationForm,
success_url='/')
]
So you need just to replace UserCreationForm with your custom UserCreateForm here and that should work.

Form.is_valid() returns False?

Why am I asking question despite already been asked? I read many question posted on Stack Overflow but I am not able to fix the code as I am new to Python Language.
What am I trying to do: Simply trying to take the input from user and return an HttpResponse (if successfully). Otherwise, an error HttpResponse message to return.
Problem : The MyForm.is_valid() in Forms.py is always returning False! I tried many solutions posted on previous questions and also read the documentary thrice but not able to understand, what am I doing wrong?
Views.Py
from django.http import HttpResponse
from .forms import PostForm
.
.
. <<code here>>
def register(request):
if request.method == 'POST':
Myform = PostForm(request.POST)
if Myform.is_valid():
return HttpResponse("<h1>Is_Valid is TRUE.</h1>")
else:
return HttpResponse("<h1>Is_Valid is False.</h1>")
else:
return HttpResponse("<h1> GET REQUEST>>>> </h1>")
Forms.Py
from django.forms import ModelForm
from .models import Post
class PostForm(ModelForm):
class Meta:
model= Post
fields = ['Username']
Models.Py
from django.db import models
class Post(models.Model):
Username = models.CharField(max_length = 20)
def __str__(self):
return self.name
HTML CODE
{% block body %}
<div class="container-fluid">
<form method="POST" class="post-form" action="{% url 'submit' %}">
{% csrf_token %}
<div class="form-group"> <!-- Full Name -->
<label for="Username" class="control-label">Full Name</label>
<input type="text" class="form-control" id="Username" name="full_name" placeholder="Enter the name of Patient here.">
</div>
<div class="form-group"> <!-- Submit Button -->
<button type="submit" class="btn btn-primary"> Submit!</button>
</div>
</form>
</div>
<hr/>
{% endblock %}
Urls.Py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^/submit$', views.register , name = 'submit'),
]
The name of your input should be username:
This is how you send this value to the form.
NOTE: It's better to use the django form, that you've already done with ModelForm
<input type="text" class="form-control" id="username" name="username" placeholder="Enter the name of Patient here.">

Editing users in Django

I was trying to to edit a user using the form that i used to create the user,
I have no idea why i'm getting an error A user with that username already exists.
Here is my view:
def registration_edit(request):
""" Registration Step2:
The user should be authenticated to reach this step.
Authentication is provided by first step or user login.
"""
if request.user.is_authenticated():
if request.POST:
form = RegistrationForm(request.POST or None, instance=request.user)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('reg_step_2'))
else:
form = RegistrationForm(instance=request.user)
page = 'account'
title = 'Editing User Registration'
context = {'title': title, 'form': form, 'page': page}
template = 'customer/registration.djhtml'
return render_to_response(template, context, context_instance=RequestContext(request))
else:
messages.info(request, '<strong>Note</strong>: You must logged in to edit your account.')
return HttpResponseRedirect('/')
forms.py I did this form because I want to include firstname and lastname field be included on the registration.
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class RegistrationForm(UserCreationForm):
class Meta:
model = User
exclude = ('is_staff', 'is_active', 'is_superuser', 'last_login', 'date_joined', 'groups', 'user_permissions', 'password')
and here is my template
<form class="form-horizontal" action='.' method="POST">
{% csrf_token %}
<fieldset>
<div id="legend">
<legend class="">
{{ title|title }}
</legend>
</div>
{% for f in form %}
<div class="control-group">
<label class="control-label" for="username">{{ f.label }}</label>
<div class="controls">
{{ f }} <i style="color: orange">{{ f.errors|striptags }}</i>
</div>
</div>
{% endfor %}
<div class="controls">
<button class="btn btn-success">
Continue
</button>
</div>
</fieldset>
</form>
Anyone tell me where i was messing around here?
Any help would be much appreciated.
Your from inherits from UserCreationForm which cleans the username field.
In this case see UserChangeForm instead.