Django - authenticate() A user with that username already exists - python

Okay I'm confused.
I'm trying to build a login page, but whenever I try to login, django gives the error that the username already exists. I haven't used save() anywhere.
I'm using authenticate(), I referred the Django docs for that:
https://docs.djangoproject.com/en/1.10/topics/auth/default/#how-to-log-a-user-in
Here is my code, please tell me where I'm going wrong:
forms.py
class LoginForm(forms.ModelForm):
username = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Username'}))
password = forms.CharField(widget=forms.PasswordInput(attrs={'placeholder': 'Password'}))
class Meta:
model = User
fields = ['username', 'password']
views.py
class LoginFormView(View):
form_class = LoginForm
template_name = 'login.html'
# display a blank form
def get(self, request):
form = self.form_class(None)
return render(request, self.template_name, {'form': form})
# authenticate user
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
return redirect('slrtcebook:home')
return render(request, self.template_name, {'form': form})
login.html
<div class="form-container">
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{% for field in form %}
{{ field }}
{{ field.errors }}
{% endfor %}
<input id="submit" type="submit" value="Log in" />
</form>
</div>
<p>Don't have an account? Register here</p>

Don't use a ModelForm for this; it will assume you're trying to create a user, and validate that you can do so with the data you've entered. Just use a standard form - inherit from forms.Form and remove the Meta class.

For those of you who want the code here is what I did to fix it:
inside of views.py:
class UserLoginView(View):
form_class = LoginForm
template_name = 'music/login_form.html'
#display a blank form
def get(self, request):
form = self.form_class(None)
return render(request, self.template_name, {'form': form})
#proces form data
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
# user = form.save(commit=False)
#cleaned (normalized) data
username = form.cleaned_data['username']
password = form.cleaned_data['password']
# user.set_password(password) #this is the only way to change a password because of hashing
#returns the User obejects if credintials are correct
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
return redirect('music:index')
return render(request, self.template_name,{'form': form})
inside of froms.py:
class LoginForm(forms.Form):
username = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Username'}))
password = forms.CharField(widget=forms.PasswordInput(attrs={'placeholder': 'Password'}))
fields = ['username', 'password']
don't forget to also import LoginForm at the top of views.py, where you import UserForm:
from .forms import UserForm, LoginForm

Related

Does not show forms errors in Django

I want to show the required errors but not showing them. I made custom errors in form.py but it does not show either my current or default and why?
When I submit a blank form I want it to appear, my created error
this is my code -->
home.html
{% extends "home/base.html" %}
{% block content %}
<h2>Sign up Form</h2>
<div class="frm">
<form method="post" novalidate>
{% csrf_token %}
{{form}}
<button type="submit">sign up</button>
</form>
</div>
{% endblock %}
forms.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import get_user_model
User = get_user_model()
class SignUpForm(UserCreationForm):
username = forms.CharField(max_length=30)
username.error_messages['required'] = ('Username field is required')
email = forms.EmailField(max_length=200)
def __init__(self, *args, **kwargs):
super(SignUpForm, self).__init__(*args, **kwargs)
for field_name, field in self.fields.items():
field.widget.attrs['class'] = 'inp'
for field in self.fields.values():
field.error_messages = {'required':'The field {fieldname} is required'.format(
fieldname=field.label)}
class Meta:
model = User
fields = ('username', 'email', 'password1', 'password2','mob', )
views.py
from .forms import SignUpForm
from django.http import HttpResponseRedirect
from django.shortcuts import redirect
from django.contrib.auth.forms import authenticate
from django.contrib.auth import login
def home(request):
form = SignUpForm(request.POST)
if request.method=="POST":
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password1')
user = authenticate(username=username, password=password)
login(request, user)
return redirect('/')
else:
form = SignUpForm()
return render(request, 'home/home.html', {'form': form})
def about(request):
return render (request, 'home/about.html')
who can help me?
I searched a lot on Google but could not find a solution
You are returning a clean form without the invalid data, when your form is invalid.
It seems your else block is not correctly indented.
def home(request):
if request.method=="POST":
form = SignUpForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password1')
user = authenticate(username=username, password=password)
login(request, user)
return redirect('/')
else: # << change indentation
form = SignUpForm()
return render(request, 'home/home.html', {'form': form})
In your views.py, how you call the form is wrong, and also how you pass POST request. It should be like this
def home(request):
form = SignUpForm() # here
if request.method=="POST":
form = SignUpForm(request.POST) # and here
if form.is_valid():
...
or this,
def home(request):
form = SignUpForm(request.POST or None) # here
if request.method=="POST":
if form.is_valid():
...
The other main issue is mentioned in HÃ¥ken Lid's answer.

Images Along With Post Only Applying In Django Admin and Not Regular Form

Like the title says, I'm trying to create a social media app and my users can upload text to their websites. Currently I'm working on adding Image functionality. I can easily add this images in the Django admin page, but whenever I try to do it from the User's create post form, nothing shows up. Here's my post create form:
{% extends "social/base.html" %}
{% load crispy_forms_tags %}
{% block content4 %}
<h1>Make Your Post</h1>
<p>Write a post / Share an image</p>
<br>
<div class="container">
<form method="post">
{% csrf_token %}
{{form|crispy}}
<button type="submit" name="button">Make Post</button>
</form>
</div>
{% endblock content4 %}
Here's my views.py:
from django.shortcuts import render, redirect
from django.http import HttpResponse
from .models import Posts
from django.contrib.auth.forms import AuthenticationForm
from .forms import NewUserForm
from django.contrib import messages
from django.contrib.auth import logout, authenticate, login
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import CreateView
from django.contrib.auth.decorators import login_required
# Create your views here.
def home(request):
context = {
'posts' : Posts.objects.all()
}
return render(request, 'social/social.html', context)
def register(request):
if request.method == "POST":
form = NewUserForm(request.POST)
if form.is_valid():
user = form.save()
username = form.cleaned_data.get('username')
messages.success(request, f"New Account Created: {username}")
login(request, user)
return redirect ("/social")
else:
for msg in form.error_messages:
print(form.error_messages[msg])
messages.error(request, f"{msg}: {form.error_messages[msg]}")
return render(request, 'social/register.html', {"form" : form})
form = NewUserForm
return render(request, 'social/register.html', {"form" : form})
def logout_request(request):
logout(request)
messages.info(request, "Logged out successfully!")
return redirect('/social')
def login_request(request):
if request.method == 'POST':
form = AuthenticationForm(request, data = request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(username = username, password = password)
if user is not None:
login(request, user)
messages.info(request, f"You are now logged in as {username}")
return redirect ('/social')
else:
messages.error(request, "Invalid username and/or password.")
else:
messages.error(request, "Invalid username and/or password.")
form = AuthenticationForm()
return render(request, 'social/login.html', {'form' : form})
class PostCreateView(CreateView):
model = Posts
fields = ['post_title', 'post_text_content', 'post_image']
def form_valid(self, form):
form.instance.post_author = self.request.user
print(self.request.user)
return super().form_valid(form)
my model:
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
# Create your models here.
class Posts(models.Model):
post_title = models.CharField(max_length = 40, help_text = 'Enter post title')
post_text_content = models.TextField(max_length = 1000)
post_author = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
post_date = models.DateField(auto_now = True, auto_now_add = False)
#Make optional Image Field
post_image = models.ImageField(upload_to = 'images', blank = True)
class Meta:
ordering = ['-post_date', 'post_title', 'post_author', 'post_text_content', 'post_image']
def __str__(self):
return self.post_title
def get_absolute_url(self):
return reverse('social-home')
That's pretty much it. If you need any more code, please ask me.
Thank you in advance!
EDIT: To be clear, when I add the images from the admin "create new post" it works, but when I add the image from the regular django form it does not show up.
You need to set enctype="multipart/form-data" on your form tag in you HTML to upload files.
<form method="post" enctype="multipart/form-data">

login form keeps telling my username already exists django

So I am trying to make a login form for a django website using a forms.py file to generate a form in my html. I have already made a registration form using the same methods and that works fine but for some reason my login form keeps working like a registration form and saying that my username already exists. i assume it is just a litle mistake but I can't figure out what it is exactly.
forms.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']
models.py
class LoginFormView(View):
form_class = LoginForm
template_name = 'intranet/login_form.html'
def get(self, request):
form = self.form_class(None)
return render(request,self.template_name,{'form': form})
def post(self,request):
form = self.form_class(request.POST)
if form.is_valid():
username = request.POST.get['username']
password = request.POST.get['password']
user = authenticate(username=username,password=password)
if user is not None:
if user.is_active:
login(request,user)
return redirect('werknemers_list')
return render(request, self.template_name, {'form': form})
login_form.html
<h1>Log in</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="log in" />
</form>
urls.py
from django.conf.urls import url
from intranet import views
urlpatterns = [
url(r'^$', views.LoginFormView.as_view(), name='login'),
url(r'^registreer$', views.UserFormView.as_view(), name='registreer')]
You shouldn't use a ModelForm for this. That will always call the model validation, which in this case checks for username uniqueness.
Use a standard Form class instead.

Why my django registration form does not pass is_valid()

I am new to Django and was following a tutorial on how to build a register view. I did exactly the same but my form does not pass form.is_valid().
Here is what I did:
forms.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class MyRegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = User
fields = ('username', 'email', 'password1', 'password2')
def save(self, commit=True):
user = super(MyRegistrationForm, self).save(commit=False)
user.email = self.cleaned_data['email']
if commit:
user.save()
return user
views.py
def register_user(request):
if request.method == 'POST':
form = MyRegistrationForm(request.POST)
if form.is_valid():
user = form.save()
return HttpResponseRedirect('/accounts/register_success')
form = MyRegistrationForm()
return render(request, 'register.html', {'form':form})
def register_success(request):
return render(request, 'register_success.html')
register.html
{% extends "base.html" %}
{% block content %}
<h2>Register</h2>
<form action="/accounts/register/" method="post">{% csrf_token %}
{{ form }}
<input type="submit" value="Register" />
</form>
{% endblock %}
When I tried to register new users on the webpage, none of them passed. Even when I used username: testuser email: testuser#example.com password:testuser123, it failed. So what is wrong?
Thanks in advance!
You should follow the correct view pattern. Put the line form = MyRegistrationForm() inside an else block, then the page itself will tell you why the form is not valid.

Cannot Authenticate Registered User

I've expanded the default django user model with the AbstractUser mixin. When I register the user I recieve the User created successfully message. But when I try to log in, the user does not authenticate. It returns Wrong username/password. The user_login method worked with the default user model before I started using the abstractuser class. I know that the data inserts in to the database because I cannot register the same user more than once. I wonder if its not authenticating because the user registration method is not salting the password? Any help is appreciated.
tl;dr: Cannot authenticate a user that was registered with the user_register method. Why?
settings.py
AUTH_USER_MODEL = "users.User"
models.py
class User(AbstractUser):
avatar = models.ImageField(upload_to='images/', blank=True, null=True)
def get_absolute_url(self):
return reverse('detail-user', kwargs={'pk': self.id})
views.py
def user_register(request):
if request.user.is_anonymous():
if request.method == 'POST':
form = UserRegisterForm(request.POST)
if form.is_valid:
form.save()
return HttpResponse('User created succcessfully.')
else:
form = UserRegisterForm()
context = {}
context.update(csrf(request))
context['form'] = form
return render_to_response('/', context)
else:
return HttpResponseRedirect('/')
def user_login(request):
if request.user.is_anonymous():
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
else:
return HttpResponse("Not active")
else:
return HttpResponse("Wrong username/password")
return HttpResponseRedirect('/')
forms.py
class UserRegisterForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ('username', 'email', 'password')
template.html
<form action="/users/create" method="POST">
{% csrf_token %}
<h4>Username</h4>
<input type="text" name="username" placeholder="admin">
<h4>Email</h4>
<input type="text" name="email" placeholder="admin#mail.com">
<h4>Password</h4>
<input type="password" name="password">
<div class="btn-list">
<button type="submit">Register</button>
</div>
</form>
Sorry for the wall of code. I wanted to be as explicit as possible.

Categories