Django modelform переопределяет метод save () self.instance изменен

Я делаю страницу с информацией о пользователе.

В представлении я передаю request.user, чтобы сформировать вот так

form = UserForm(request.POST, instance=request.user)

Проблема в том, что когда я сохраняю форму с помощью form.save(), имя пользователя изменено, и я проверил self.isntance. В UserForm я обнаружил, что self.instance.username в методе save() изменен, но не в методе очистки поля (clean_username()) и методе подкласса формы clean(). self.instance.username изменяется только в методе save().

У меня есть другое поле с Usermodel, например поле электронной почты, но изменено только поле имени пользователя.

Любой совет или подсказка полезны для меня

пс. После того, как я написал этот вопрос, я обнаружил еще одну вещь, что self.instance в методе save() не является экземпляром исходного пользователя. Это имя пользователя и адрес электронной почты - это данные request.POST.

Вот мой код

Посмотреть

@login_required(login_url='/member/login')
def change_user_info(request):
    if request.method == 'POST':
        form = UserForm(request.POST, instance=request.user)
        if form.is_valid():
            form.save()
            update_session_auth_hash(request, form.instance)
            return redirect('/member/change-user-info')
    else:
        form = UserForm(instance=request.user)
    context = {
        'form': form,
        'home_button': True
    }
    return render(request, 'member/user_info.html', context)

модель

class User(AbstractUser):
    username = models.CharField(max_length=50, unique=True)
    email = models.EmailField()


    USERNAME_FIELD = 'username'
    EMAIL_FIELD = 'email'

форма

class UserForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        field_list = ['username', 'email']
        for field in field_list:
            self.fields[field].required = False

    new_password1 = forms.CharField(
        required=False,
        widget=forms.PasswordInput(
            attrs = {
                'autofocus': True,
                'id': 'userinfo-new-password1',
                'class': 'form-control',
                'placeholder': '새 비밀번호',
                'aria-describedby': 'newpassword1HelpBlock',
            }),
    )
    new_password2 = forms.CharField(
        required=False,
        widget=forms.PasswordInput(
            attrs = {
                'autofocus': True,
                'id': 'userinfo-new-password2',
                'class': 'form-control',
                'placeholder': '새 비밀번호 확인',
                'aria-describedby': 'newpassword2HelpBlock',
            }),
    )
    old_password = forms.CharField(
        required=False,
        widget=forms.PasswordInput(
            attrs = {
                'autofocus': True,
                'id': 'userinfo-old-password',
                'class': 'form-control',
                'placeholder': '기존 비밀번호',
                'aria-describedby': 'oldpasswordHelpBlock',
            })
    )

    class Meta:
        model = User
        fields = [
            'username',
            'email',
        ]
        widgets = {
            'username': TextInput(attrs = {
                # 'readonly': True,
                'disabled': True,
                'autofocus': True,
                'id': 'disabledTextInput',
                'class': 'form-control',
                'aria-describedby': 'usernameHelpBlock',
            }),
            'email': EmailInput(attrs = {
                'autofocus': True,
                'id': 'userinfo-email',
                'class': 'form-control',
                'placeholder': 'EMAIL',
                'aria-describedby': 'emailHelpBlock',
            }),
        }

    def clean_username(self):
        test = self.cleaned_data['username']  --> ''
        test2 = self.instance.username   --> has correct user name
        return test

    def clean_new_password1(self):
        if not self.cleaned_data.get('new_password1'):
            return None
        return self.cleaned_data['new_password1']

    def clean_new_password2(self):
        if not self.cleaned_data.get('new_password2'):
            return None
        return self.cleaned_data['new_password2']

    def clean_old_password(self):
        password = self.cleaned_data.get('old_password')
        if not self.instance.check_password(password):
            raise forms.ValidationError('정보 변경을 위해서 기존 비밀번호를 입력해 주세요')
        return password

    def clean(self):
        test = self.instance.username --> has correct username
        super().clean()
        new_password1 = self.cleaned_data.get('new_password1')
        new_password2 = self.cleaned_data.get('new_password2')

        if new_password1 and new_password2:
            if new_password1 != new_password2:
                raise forms.ValidationError(
                    "새 비밀번호가 일치하지 않습니다."
                )
        elif new_password1 is None and new_password2 is None:
            pass
        else:
            raise forms.ValidationError(
                "비밀번호 변경을 위해선 '새 비밀번호' '새 비밀번호 확인'란에 모두 입력하셔야 합니다."
            )

    def save(self, commit=True):
        user = self.instance
        username = self.instance.username --> ''
        email = self.instance.email --> has correct email
        if self.instance.email != self.cleaned_data.get('email'):
            user.email = self.cleaned_data.get('email')
        if self.cleaned_data['new_password2'] is not None:
            user.set_password(self.cleaned_data.get('new_password2'))
        user.save()

Спасибо

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
1 783
1

Ответы 1

Поле вашего имени пользователя в форме отключено, поэтому вы получаете пустое значение в self.cleaned_data ['username'] в методе clean_username. Так что измените свой код, как показано ниже

def clean_username(self):
    return self.cleaned_data['username']  or self.instance.username

Да, я понимаю это и это может быть одним из решений ~ !! Но я не могу понять, почему self.instance в методе save() заменен на request.POSTdata. Даже я отменяю метод save(). Я думаю, что self.instance не следует менять раньше self.instance.save() в методе save() ...

zoozooclub 03.05.2018 03:56

Другие вопросы по теме