#python #django #django-forms
#python #django #django-forms
Вопрос:
В настоящее время у меня есть 4 записи в моей Role
таблице, которые относятся к роли пользователя на веб-сайте. Эти роли можно выбрать в списке флажков с помощью, но я не могу сохранить данные, отправленные через форму. Я получаю следующую ошибку: 'RegisterForm' object has no attribute 'roles'**
в forms.py .
чего мне здесь не хватает?
Вот код:
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from .models import User, Profile, Role
class RegisterForm(UserCreationForm):
password1 = forms.CharField(min_length=4, widget=forms.PasswordInput(attrs={
'placeholder': 'Password'
}), label='password')
password2 = forms.CharField(min_length=4, widget=forms.PasswordInput(attrs={
'placeholder': 'Confirm Password'
}), label='Confirm Password')
class Meta:
model = User
fields = ['email', 'first_name', 'last_name', 'roles', 'password1']
widgets = {
'roles': forms.CheckboxSelectMultiple()
}
def clean_password2(self):
password = self.cleaned_data['password1']
password2 = self.cleaned_data['password2']
if password and password2 and password != password2:
raise forms.ValidationError("password and confirm password is not same")
if len(password) < 4:
raise forms.ValidationError('Password is very weak please enter 4 words at least')
return password
def save(self, commit=True):
user = super().save(commit=False)
if commit:
user.staff = True
user.set_password(self.cleaned_data['password1'])
self.roles.add(self.cleaned_data['roles'])
user.save()
return user
models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from .managers import UserManager
from django.db.models.signals import post_save
class Role(models.Model):
MEMBER = 1
SECRETARY = 2
SUPERVISOR = 3
ADMIN = 4
ROLE_CHOICES = (
(MEMBER, 'Member'),
(SECRETARY, 'Secretary'),
(SUPERVISOR, 'Supervisor'),
(ADMIN, 'Admin'),
)
id = models.PositiveSmallIntegerField(choices=ROLE_CHOICES, primary_key=True)
def __str__(self):
return self.get_id_display()
class User(AbstractBaseUser, PermissionsMixin):
roles = models.ManyToManyField(Role)
email = models.EmailField(unique=True)
first_name = models.CharField(max_length=15)
last_name = models.CharField(max_length=15)
date_joined = models.DateTimeField(auto_now_add=True)
active = models.BooleanField(default=True)
admin = models.BooleanField(default=False)
staff = models.BooleanField(default=False)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
def __str__(self):
return self.email
def get_full_name(self):
return '{} {}'.format(self.first_name, self.last_name)
def get_short_name(self):
return self.email
@property
def is_staff(self):
return self.staff
@property
def is_admin(self):
return self.admin
@property
def is_active(self):
return self.active
def has_perm(self, perm, obj=None):
return True
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
overview = models.TextField(max_length=2000, blank=True)
def create_profile(sender, **kwargs):
if kwargs['created']:
Profile.objects.create(user=kwargs['instance'])
post_save.connect(receiver=create_profile, sender=User)
Редактировать с новой трассировкой
Traceback (most recent call last):
File "/home/medo/.local/lib/python3.8/site-packages/django/db/backends/base/base.py", line 242, in _commit
return self.connection.commit()
The above exception (FOREIGN KEY constraint failed) was the direct cause of the following exception:
File "/home/medo/.local/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/home/medo/.local/lib/python3.8/site-packages/django/core/handlers/base.py", line 179, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/media/medo/BE4C6BE74C6B98C3/Cources/Django/Infrastructure_django/UserApp/More than three users/project/app1/views.py", line 16, in register
form.save()
File "/media/medo/BE4C6BE74C6B98C3/Cources/Django/Infrastructure_django/UserApp/More than three users/project/app1/forms.py", line 36, in save
user.roles.add(self.cleaned_data['roles'])
File "/home/medo/.local/lib/python3.8/site-packages/django/db/models/fields/related_descriptors.py", line 957, in add
self._add_items(
File "/home/medo/.local/lib/python3.8/site-packages/django/db/transaction.py", line 232, in __exit__
connection.commit()
File "/home/medo/.local/lib/python3.8/site-packages/django/utils/asyncio.py", line 26, in inner
return func(*args, **kwargs)
File "/home/medo/.local/lib/python3.8/site-packages/django/db/backends/base/base.py", line 266, in commit
self._commit()
File "/home/medo/.local/lib/python3.8/site-packages/django/db/backends/base/base.py", line 242, in _commit
return self.connection.commit()
File "/home/medo/.local/lib/python3.8/site-packages/django/db/utils.py", line 90, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/home/medo/.local/lib/python3.8/site-packages/django/db/backends/base/base.py", line 242, in _commit
return self.connection.commit()
Exception Type: IntegrityError at /register/
Exception Value: FOREIGN KEY constraint failed
кроме того, может это может помочь
Ответ №1:
Причина, по которой вы получаете 'RegisterForm' object has no attribute 'roles'
ошибку, заключается в том, что self
в
self.roles.add(self.cleaned_data['roles'])
относится к форме, а не к вашему экземпляру пользователя.
Вместо этого вы хотите добавить к ролям пользователя вот так:
user.roles.add(self.cleaned_data['roles'])
Однако имейте в виду, что при создании User
экземпляра вам необходимо убедиться, что User
объект уже создан / сохранен, прежде чем добавлять роли. Это необходимо, потому что для добавления внешнего ключа из ManyToMany
отношения к User
User
экземпляру требуется id
. Это id
создается только после сохранения User
экземпляра. Таким образом, в качестве конечного результата вы получите что-то вроде:
user.save()
user.roles.add(self.cleaned_data['roles'])
Комментарии:
1. но когда я использую (user) Я получаю эту ошибку: «<Пользователь: sam@gmail.com >» должно быть значение для поля «id», прежде чем можно будет использовать это отношение «многие ко многим». когда я регистрируюсь
2. Это имеет смысл, поскольку ваш пользователь еще не создан в вашей базе данных. Перед добавлением ролей необходимо выполнить сохранение
user.save()
.3. В своем ответе я добавил объяснение, зачем это нужно.
4. это исправлено, но у меня возникла другая проблема: сбой ограничения ВНЕШНЕГО КЛЮЧА
5. Таким образом, это не связано с исходной ошибкой и может означать несколько разных вещей. У вас есть дополнительная информация о том, какая строка выдает эту ошибку? Один из вариантов, который вы можете попробовать, — это добавление
blank=True, null=True
roles = models.ManyToManyField(Role, blank=True, null=True)
. Другой — проверка содержимогоself.cleaned_data['roles']
. Содержит ли он правильные идентификаторы ролей?