在Django中注册自定义用户时出错

时间:2019-04-01 00:40:19

标签: django

当我想在Django中注册新用户时,收到以下警告:

UNIQUE constraint failed: polls_usuario.matriculaUsuario

当我通过管理员和主视图编辑注册表时,不会发生此错误。仅当创建新用户时才会发生此错误。当我通过视图注册创建用户时,将使用默认注册创建该用户。当我尝试通过管理员创建时,甚至没有创建用户。可能会发生什么?

views.py

def registrar(request):
    if request.method == 'POST':
        form = SignUpForm(request.POST)
        usuario_form = UsuarioForm(request.POST)
        if form.is_valid() and usuario_form.is_valid():
            user = form.save(commit=False)
            user.refresh_from_db()  # load the profile instance created by the signal
            user.usuario.matriculaUsuario = form.cleaned_data.get('matriculaUsuario')
            usuario_form.save()
            user.save()
            raw_password = form.cleaned_data.get('password1')
            user = authenticate(username=user.username, password=raw_password)
            login(request,user)
            return render(request, 'polls/index.html', user)
            #return HttpResponseRedirect(reverse('/')) 
            #return redirect('/')
    else:
        form = SignUpForm()
        usuario_form = UsuarioForm()
    return render(request, 'polls/registrar.html', {'form': form , 'usuario_form':usuario_form})

forms.py

class UsuarioForm(forms.ModelForm):
    class Meta:
        model = Usuario
        fields = ('matriculaUsuario',)

class SignUpForm(UserCreationForm):
    first_name = forms.CharField(label='Primeiro Nome',max_length=30, required=False, help_text='Opcional.')
    last_name = forms.CharField(label='Último Nome',max_length=30, required=False, help_text='Opcional.')
    email = forms.EmailField(label='E-mail',max_length=254, help_text='Informe o seu e-mail (Requerido)')   
    username = forms.CharField(label='Nome de usuário', min_length=4, max_length=150)
    password1 = forms.CharField(label='Senha', widget=forms.PasswordInput)
    password2 = forms.CharField(label='Confirmação da senha', widget=forms.PasswordInput)

    matriculaUsuario = forms.CharField(label='Matrícula',max_length=12,validators=[ validators.RegexValidator(re.compile('^[0-9]{12}$'), _('Digite uma matrícula válida'), _('invalid'))])

    class Meta:
        model = User
        fields = ['first_name', 'last_name','username','matriculaUsuario','email','password1', 'password2',] 
    def clean_username(self):
        username = self.cleaned_data['username'].lower()
        r = User.objects.filter(username=username)
        if r.count():
            raise  ValidationError("Nome de usuário já cadastrado")
        return username

    def clean_email(self):
        email = self.cleaned_data['email'].lower()
        r = User.objects.filter(email=email)
        if r.count():
            raise  ValidationError("E-mail já cadastrado")
        return email

    def clean_password2(self):
        password1 = self.cleaned_data.get('password1')
        password2 = self.cleaned_data.get('password2')

        if password1 and password2 and password1 != password2:
            raise ValidationError("Senhas não conferem")

        return password2

    def save(self, commit=True):
        user = User.objects.create_user(
            self.cleaned_data['username'],
            self.cleaned_data['email'],
            self.cleaned_data['password1']
        )
        return user
class EditProfileForm(forms.ModelForm):
    first_name = forms.CharField(label='Nome')
    last_name = forms.CharField(label='Sobrenome')
    username = forms.CharField(min_length=4, max_length=150,help_text=("Insira um novo nome de usuário"), label='Nome de usuário')
    email = forms.EmailField(label='E-mail')
    matriculaUsuario = forms.CharField(label='Matrícula', max_length=12,validators=[ validators.RegexValidator(re.compile('^[0-9]{12}$'), _('Digite uma matrícula válida'), _('invalid'))])
    class Meta:
        model = User
        fields = ['first_name', 'last_name','username','matriculaUsuario','email']

models.py

class Usuario(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE,null=True)
    matriculaUsuario = models.CharField(default='000000000000',max_length=12,primary_key=True,null=False,help_text=_('São requeridos os 12 dígitos referentes à sua matrícula'), validators=[ validators.RegexValidator(re.compile('^[0-9]{12}$'), _('Digite uma matrícula válida'), _('invalid'))])
    def __str__(self):
        return self.user.username
    @receiver(post_save, sender=User)
def update_user_usuario(sender, instance, created, **kwargs):
    if created:
        Usuario.objects.create(user=instance)
    instance.usuario.save()

@receiver(post_save, sender=User)
def create_user_usuario(sender, instance, created, **kwargs):
    if created:
        Usuario.objects.create(user=instance)
post_save.connect(create_user_usuario,sender=User)
@receiver(post_save, sender=User)
def save_user_usuario(sender, instance, created,**kwargs):
    if created:
        instance.usuario.save()

1 个答案:

答案 0 :(得分:0)

在您的models.py中,将matriculaUsuario设置为primary_key:

class Usuario(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE,null=True)
    matriculaUsuario = models.CharField(default='000000000000',max_length=12,primary_key=True,null=False,help_text=_('São requeridos os 12 dígitos referentes à sua matrícula'), validators=[ validators.RegexValidator(re.compile('^[0-9]{12}$'), _('Digite uma matrícula válida'), _('invalid'))]) # you set this as primary key

您还为其设置了默认值='000000000000'。这很不好,因为在创建新用户并保存表单时,该字段每次都获得相同的值('000000000000')。因为您设置primary_key = True,所以这是不可能的。主键是对象的唯一标识符,因此它应该是唯一的。

primary_key = True表示null = False和unique = True。一个对象只允许使用一个主键。

参考:https://django.readthedocs.io/en/2.1.x/ref/models/fields.html

考虑使用自动字段,该字段将在创建对象时自动增加pk:

matriculaUsuario = models.AutoField(primary_key=True)

UUIDField还是另一个不错的选择,它可以长期使用较大的数据库,并且使攻击者难以猜测对象的pk。

matriculaUsuario = models.UUIDField(primary_key=True, unique=True, default=uuid.uuid4, editable=False)

此外,我认为您不应该允许用户在EditProfile表单中编辑其matricualUsuario,因为这会造成问题。

相关问题