Авторизация электронной почты в Django
Я делаю свое первое приложение, которое является приложением-тодолистом. Я пытаюсь заставить пользователей регистрироваться с помощью электронной почты и входить в систему с ее помощью.
Вот ошибка, которую показывает отладка:
ProgrammingError at /register/
no existe la relación «core_user»
LINE 1: SELECT 1 AS "a" FROM "core_user" WHERE "core_user"."email" =...
^
Request Method: POST
Request URL: http://127.0.0.1:8000/register/
Django Version: 5.0.2
Exception Type: ProgrammingError
Exception Value:
no existe la relación «core_user»
LINE 1: SELECT 1 AS "a" FROM "core_user" WHERE "core_user"."email" =...
Мои файлы имеют следующую конфигурацию
models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
email = models.EmailField(unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
class Task(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=200)
description = models.TextField()
complete = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
class Meta:
ordering = ['complete']
views.py
from django.shortcuts import render, redirect
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView, FormView
from django.urls import reverse_lazy
from django.contrib.auth.views import LoginView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth import login
from .models import Task
from .forms import LoginForm, RegisterForm
class CustomLoginView(LoginView):
template_name = 'core/login.html'
form_class = LoginForm
redirect_authenticated_user = True
def get_success_url(self):
return reverse_lazy('task_list')
class RegisterPage(FormView):
template_name = 'core/register.html'
form_class = RegisterForm
redirect_authenticated_user = True
success_url = reverse_lazy('task_list')
def form_valid(self, form):
user = form.save()
if user is not None:
login(self.request, user)
return super(RegisterPage, self).form_valid(form)
def get(self, *args, **kwargs):
if self.request.user.is_authenticated:
return redirect('task_list')
return super(RegisterPage, self).get(*args, **kwargs)
class TaskList(LoginRequiredMixin, ListView):
model = Task
template_name = 'core/index.html'
context_object_name = 'task_list'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['task_list'] = context['task_list'].filter(user=self.request.user)
context['count'] = context['task_list'].filter(complete=False).count()
search_input = self.request.GET.get('search-area') or ''
if search_input:
context['task_list'] = context['task_list'].filter(title__startswith=search_input)
context['search_input'] = search_input
return context
class TaskDetail(LoginRequiredMixin, DetailView):
model = Task
template_name = 'core/task_detail.html'
context_object_name = 'task'
class TaskCreate(LoginRequiredMixin, CreateView):
model = Task
template_name = 'core/task_form.html'
fields = ['title', 'description', 'complete']
success_url = reverse_lazy('task_list')
def form_valid(self, form):
form.instance.user = self.request.user
return super(TaskCreate, self).form_valid(form)
class TaskUpdate(LoginRequiredMixin, UpdateView):
model = Task
fields = ['title', 'description', 'complete']
success_url = reverse_lazy('task_list')
class TaskDelete(LoginRequiredMixin, DeleteView):
model = Task
context_object_name = 'task'
success_url = reverse_lazy('task_list')
forms.py
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django.contrib.auth import get_user_model
from django import forms
class RegisterForm(UserCreationForm):
class Meta:
model = get_user_model()
fields = ('email', 'password1', 'password2')
class LoginForm(AuthenticationForm):
username = forms.CharField(label='Email')
def clean(self):
username = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
# Verificar si el nombre de usuario es un correo electrónico
if '@' in username:
kwargs = {'email': username}
# Asignar los datos limpios validados al formulario
self.cleaned_data['username'] = username
self.cleaned_data['password'] = password
return super().clean()
backends.py
from django.contrib.auth.hashers import check_password
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model
from django.db.models import Q
UserModel = get_user_model()
class EmailBackend(ModelBackend):
def authenticate(self, request, username=None, password=None, **kwargs):
try:
user = UserModel.objects.get(Q(username__iexact=username) | Q(email__iexact=username))
except UserModel.DoesNotExist:
return None
except UserModel.MultipleObjectsReturned:
# Podrías manejar este caso de manera más específica si es necesario
user = UserModel.objects.filter(Q(username__iexact=username) | Q(email__iexact=username)).order_by('id').first()
if user and check_password(password, user.password):
return user
else:
return None
settings.py
Я хочу иметь возможность корректно входить и регистрироваться, не используя имя пользователя, используя электронную почту и пароль.
В вашем случае, поскольку вы переопределили поведение по умолчанию, чтобы использовать электронную почту в качестве имени пользователя, вы должны включить 'email' в список REQUIRED_FIELDS вместо 'username'.
class User(AbstractUser):
email = models.EmailField(unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['email']