Используя auth_user, электронная почта сохраняется в столбце last_name - PullRequest
0 голосов
/ 25 мая 2018

Я использую предоставленную Django пользовательскую модель.Все работало нормально, но после одного изменения, когда я попытался сделать поле email unique.

my forms.py:

from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User



class SignUpForm(UserCreationForm):
    first_name = forms.CharField(max_length=30, required=False, help_text='Optional.')
    last_name = forms.CharField(max_length=30, required=False, help_text='Optional.')
    email = forms.EmailField(max_length=254, help_text='Required. Inform a valid email address.')
    User._meta.get_field('email')._unique = True

    class Meta:
        model = User
        fields = ('username', 'first_name', 'last_name', 'email', 'password1', 'password2', )

строку кода, которую я добавил в forms.py чтобы поле электронной почты unique было:

User._meta.get_field('email')._unique = True

my views.py:

def signup(request):
    if request.method == 'POST':
        form = SignUpForm(request.POST)
        if form.is_valid():
            user = form.save(commit=False)
            user.is_active = False
            user.save()
            user.refresh_from_db()
            private_key = rsa.generate_private_key(
                public_exponent=65537,
                key_size=4096,
                backend=default_backend()
            )
            public_key = private_key.public_key()
            pem_private_key = private_key.private_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PrivateFormat.PKCS8,
                encryption_algorithm=serialization.NoEncryption()
            )
            user.profile.public_key = public_key.public_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PublicFormat.SubjectPublicKeyInfo
            )
            raw_password = form.cleaned_data.get('password1').encode()
            user.profile.salt = os.urandom(16)
            kdf = Scrypt(
                salt=user.profile.salt,
                length=32,
                n=2 ** 20,
                r=8,
                p=1,
                backend=default_backend()
            )
            key = base64.urlsafe_b64encode(kdf.derive(raw_password))
            f = Fernet(key)
            user.profile.encrypted_private_key = f.encrypt(pem_private_key)
            user.save()
            current_site = get_current_site(request)
            subject = 'Activate Your MySite Account'
            message = render_to_string('accounts/account_activation_email.html', {
                'user': user,
                'domain': current_site.domain,
                'uid': urlsafe_base64_encode(force_bytes(user.pk)).decode(),
                'token': account_activation_token.make_token(user),
            })
            user.email_user(subject, message)
            return redirect('account_activation_sent')
    else:
        form = SignUpForm()
    return render(request, 'accounts/signup.html', {'form': form})

здесь, где я регистрирую пользователя, я также добавилмодель профиля, в которой я создаю несколько пар ключей для пользователя, все из которых работают как положено.У меня также есть электронное письмо с запросом активации для активации пользователя.

my models.py:

from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver


class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    email_confirmed = models.BooleanField(default=False)
    encrypted_private_key = models.CharField(max_length=500, blank=True)
    public_key = models.CharField(max_length=30, blank=True)
    salt = models.CharField(max_length=16, blank=True)

@receiver(post_save, sender=User)
def update_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)
    instance.profile.save()

Здесь я создаю профиль пользователя с помощью сигналов.

myHTML-файл:

{% extends 'base.html' %}

{% block content %}
  <h2>Sign up</h2>
  <form method="post">
    {% csrf_token %}
    {% for field in form %}
      <p>
        {{ field.label_tag }}<br>
        {{ field }}
        {% if field.help_text %}
          <small style="color: grey">{{ field.help_text }}</small>
        {% endif %}
        {% for error in field.errors %}
          <p style="color: red">{{ error }}</p>
        {% endfor %}
      </p>
    {% endfor %}
    <button type="submit">Sign up</button>
  </form>
{% endblock %}

Когда я добавил эту строку кода, чтобы сделать поле email в auth_user unique, мне пришлось сделать makemigrations, а затем migrate.Поле email стало unique, и я получаю код ошибки при попытке зарегистрироваться на существующее электронное письмо.Но при просмотре базы данных я заметил, что электронная почта сохраняется в столбце last_name, что действительно странно.

Я попытался переломить ситуацию, удалив эту строку кода и снова применив миграции, но тоже самоепроисходит снова.

Все работало, как и ожидалось, прежде чем я сделал поле электронной почты уникальным.

1 Ответ

0 голосов
/ 25 мая 2018

Есть ли причина, по которой вы хотите заново изобрести процесс шифрования пароля?Как правило, это обычно менее безопасно, чем собственное решение Django.

Рассматривали ли вы создание пользовательской модели, которая будет использовать уникальный адрес электронной почты (минуя магию в форме)?Кроме того, я бы посоветовал вам изучить django-registration или django-allauth (я предпочитаю all-auth).Они фактически сделают все, что вы пытаетесь сделать для вас.

https://github.com/pennersr/django-allauth https://github.com/ubernostrum/django-registration

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...