Заполнение пользовательского поля в форме Django

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

# forms.py

class ProfileForm(forms.ModelForm):
    
    class Meta:
        model = Profile
        fields = ('name', 'timezone')


class ProfileUpdateForm(ProfileForm):
    
    email = forms.EmailField(max_length=254)

    class Meta(ProfileForm.Meta):
        fields = ProfileForm.Meta.fields + ('email',)
# views.py

@login_required
@require_http_methods(["GET","POST"])
def profile_update_view(request):

    context = {}
    
    # Get the logged in users profile
    profile_object = Profile.objects.get(user=request.user.id)

    if request.method == 'GET':
        profile_form = ProfileUpdateForm(None, instance=profile_object)
        context["form"] = profile_form
        # how can I add User.objects.get(id=request.user.id).email to the custom field

    if request.method == 'POST':
        profile_form = ProfileUpdateForm(request.POST or None, instance=profile_object)
        context["form"] = profile_form
        
        if profile_form.is_valid():
            try:
                # email address exists
                user = User.objects.get(email=profile_form.cleaned_data.get('email'))
                messages.error(request, 'Failed profile update. Email address already exists.')
            except:
                # email address available
                # get user object                
                user = User.objects.get(id=request.user.id)
                user.email = profile_form.cleaned_data.get('email')
                # update user object
                user.save()
                profile_form.save()
                messages.success(request, 'Successful profile update.')
            

    return render(request, "profile.html", context)

# forms.py

    def __init__(self, *args, **kwargs):
        self.email = kwargs.pop("email")
        super(ProfileUpdateForm, self).__init__(*args, **kwargs)
        self.initial['email'] = self.email

# views.py

    if request.method == 'GET':
        profile_form = ProfileUpdateForm(None, instance=profile_object, email=request.user.email)
        context["form"] = profile_form

    if request.method == 'POST':
        profile_form = ProfileUpdateForm(request.POST or None, instance=profile_object, email=request.POST.get('email'))
        context["form"] = profile_form

PS, закладка Classy Class-based Views, бесценный ресурс

Я склоняюсь к классовым представлениям, и такие вещи, как эта, как раз то, где они вступают в свои права. Форма:

class ProfileUpdateForm(forms.ModelForm):

    class Meta:
        model = Profile
        fields = ('name', 'timezone')

    email = forms.EmailField(max_length=254) #add non-model form field

И представление на основе класса. Обработка начального значения для email в get_initial(), и обновление self.request.user в form_valid():

class ProfileUpdateView( UpdateView):
    model = Profile
    form_class = ProfileUpdateForm
    template_name = 'profile.html'  # profiles/update_profile.html would be better
    # other declarations ...?
      

    def get_initial(self):
        initial = super().get_initial()
        initial['email'] = self.request.user.email
        return initial

    # @transaction.atomic might be a good idea
    def form_valid(self,  form):
        new_email = form.cleaned_data['email']
        user = self.request.user
        if user.email != new_email:  # don't do a pointless non-update save
             user.email = new_email
             user.save()
        return super().form_valid( form)  # will save the profile
Вернуться на верх