Change Email Form wont work

I tried to make a ModelForm for changing the email in the user model but the input field on the page wont appear. I guess i messed something up in the views.py

views.py


@login_required(login_url='home:login')
def ChangeEmailView(request):
        if request.method == 'POST':
            form = EmailChangingForm(request.POST)
            if form.is_valid():
                emailvalue = form.save()
                account = User.objects.update(user=request.user, email=emailvalue)
                account.save()
   

            return redirect('home:profilesettings')
        else:
            form = EmailChangingForm()
        return render(request, 'home/email_settings.html')

forms.py

from django.contrib.auth import forms
from django.contrib.auth.forms import PasswordResetForm, SetPasswordForm, UserCreationForm
from django.contrib.auth.models import User
from django.contrib.auth.views import PasswordResetConfirmView, PasswordResetView
from django.forms import ModelForm
from django.forms.fields import CharField, EmailField
from StartSite.models import Account
from django.contrib.auth.forms import PasswordChangeForm
from django.forms.widgets import EmailInput, PasswordInput

class EmailChangingForm(ModelForm):
    class Meta:
        model = User
        fields = ['email']

...

template

                  <form method="post" class="id_password_reset_form">
                      {% csrf_token %}
                      <p>Please enter your new Email</p>
                      <h6 class="mb-0">New Email</h6>
                      <div class="pw_space2"></div>
                        {{ form }}
                      <div class="pw_space2"></div>
                      <button style="background-color:#7231aa; border:#7231aa; color:white;" class="btn btn-secondary " type="submit">Change Email</button>
                      <a style="background-color:#7231aa; border:#7231aa; color:white;" class="btn btn-secondary " target="__blank" href="{% url 'home:profilesettings' %}">Cancel</a>
                </form>

urls.py

from django.contrib.auth.forms import PasswordChangeForm
from django.urls import path
from django.contrib.auth import views as auth_views
from django.urls.base import reverse_lazy

from . import views
app_name = 'home'
urlpatterns = [
    path('', views.index_view, name="index"),
    path('login/', views.login_view, name="login"),
    path('register/', views.register_view, name="register"),
    path('logout/', views.logout_view, name="logout"),
    path('profile/', views.profile_view, name="profile"),
    path('settings/', views.profilesettings_view, name="profilesettings"),
    path('settings/prename/', views.AccountInfoPrename, name="ps_prename"),
    path('settings/company/', views.AccountInfoCompany, name="ps_company"),
    path('settings/country/', views.AccountInfoCountry, name="ps_country"),
    path('settings/surname/', views.AccountInfoSurname, name="ps_surname"),
    path('settings/email/', views.email_settings_view, name="emailsettings"),
    path('settings/language/', views.language_settings_view, name="languagesettings"),
    path('plans/', views.plans_view, name="plans"),
    path('settings/password/', views.PasswordChangeView.as_view(success_url=reverse_lazy('home:password_success'), template_name='home/password_settings.html'), name="passwordsettings"),
    path('settings/password_success/', views.password_success, name="password_success"),
    path('converter/', views.vc_view, name="vc"),
    path('imageupload/', views.imgupload_view, name="imgupload"),



]

You’re not providing a context containing the form for your template to render.

thx this worked, with the code in the views above a new user without username etc. was created but I just want to overwrite the acutal users email I tried it with this


@login_required(login_url='home:login')
def ChangeEmailView(request):
        if request.method == 'POST':
            form = EmailChangingForm(request.POST)
            if form.is_valid():
                new_email = form.save()
                account = User.objects.update_or_create(email=new_email)
                account.save()
   

            return redirect('home:profilesettings')
            
        else:
            form = EmailChangingForm()
        context = {'form': form}
        return render(request, 'home/email_settings.html', context)

but now this erorr shows up

Traceback (most recent call last):
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\contrib\auth\decorators.py", line 21, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "D:\Developement\Projekte\DivusX\DivusX\StartSite\views.py", line 276, in ChangeEmailView
    new_email = form.save()
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\forms\models.py", line 468, in save
    self.instance.save()
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\contrib\auth\base_user.py", line 67, in save
    super().save(*args, **kwargs)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\base.py", line 726, in save
    self.save_base(using=using, force_insert=force_insert,
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\base.py", line 763, in save_base
    updated = self._save_table(
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\base.py", line 868, in _save_table
    results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\base.py", line 906, in _do_insert
    return manager._insert(
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\query.py", line 1270, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\sql\compiler.py", line 1416, in execute_sql
    cursor.execute(sql, params)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\utils.py", line 98, in execute
    return super().execute(sql, params)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\utils.py", line 66, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\utils.py", line 75, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\sqlite3\base.py", line 423, in execute
    return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: UNIQUE constraint failed: auth_user.username

what should I do

Review the page Creating forms from models | Django documentation | Django

@login_required(login_url='home:login')
def ChangeEmailView(request):
        if request.method == 'POST':
            form = EmailChangingForm(request.POST)
            if form.is_valid():
                f = EmailChangingForm(request.POST)
                new_author = f.save(commit=False)
                new_author.email = 'some_value'
                new_author.save()
   

            return redirect('home:profilesettings')
            
        else:
            form = EmailChangingForm()
        context = {'form': form}
        return render(request, 'home/email_settings.html', context)

how can I replace “some_value” with the email, how do I get it?

Are you talking about creating a new author here (implied by your use of the variable new_author), or are you looking to edit an existing author (implied by the name of the view)?

They’re two different processes.

When you’re looking to edit an existing author, you want to initialize your form with the instance of the model that already exists. (See the very first example block of code in the link I referred to in my previous response.)

so I have this now

@login_required(login_url='home:login')
def ChangeEmailView(request):
        if request.method == 'POST':
            form = EmailChangingForm(request.POST)
            if form.is_valid():
                emailvalue = User.objects.get(pk=request.user.id)
                form = EmailChangingForm(instance=emailvalue, email=emailvalue)

   

            return redirect('home:profilesettings')
            
        else:
            form = EmailChangingForm()
        context = {'form': form}
        return render(request, 'home/email_settings.html', context)

    

and if I remove the second parameter “email=emailvalue” no error apperars but the email doesnt get settet like it should. But now this error shows up

Internal Server Error: /settings/email/
Traceback (most recent call last):
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\contrib\auth\decorators.py", line 21, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "D:\Developement\Projekte\DivusX\DivusX\StartSite\views.py", line 276, in ChangeEmailView
    form = EmailChangingForm(instance=emailvalue, email=emailvalue)
TypeError: __init__() got an unexpected keyword argument 'email'

how can I just set the email of the user with this code

Ok, take a step back here then and review Working with forms | Django documentation | Django.

In particular, read the sections:

so I came to this code which I think is near to my goal

@login_required(login_url='home:login')
def ChangeEmailView(request):
        if request.method == 'POST':
            form = EmailChangingForm(request.POST)
            if form.is_valid():
                user = User.objects.get(email = request.user.email)
                user.email = form.save(commit=False)
                user.save()

   

            return redirect('home:profilesettings')
            
        else:
            form = EmailChangingForm()
        context = {'form': form}
        return render(request, 'home/email_settings.html', context)

    

But now this error comes:

Internal Server Error: /settings/email/
Traceback (most recent call last):
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\contrib\auth\decorators.py", line 21, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "D:\Developement\Projekte\DivusX\DivusX\StartSite\views.py", line 279, in ChangeEmailView
    user.save()
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\contrib\auth\base_user.py", line 67, in save
    super().save(*args, **kwargs)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\base.py", line 726, in save
    self.save_base(using=using, force_insert=force_insert,
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\base.py", line 763, in save_base
    updated = self._save_table(
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\base.py", line 845, in _save_table
    updated = self._do_update(base_qs, using, pk_val, values, update_fields,
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\base.py", line 899, in _do_update
    return filtered._update(values) > 0
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\query.py", line 802, in _update
    return query.get_compiler(self.db).execute_sql(CURSOR)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\sql\compiler.py", line 1559, in execute_sql
    cursor = super().execute_sql(result_type)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\sql\compiler.py", line 1162, in execute_sql
    sql, params = self.as_sql()
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\sql\compiler.py", line 1519, in as_sql
    raise TypeError(
TypeError: Tried to update field auth.User.email with a model instance, <User: >. Use a value compatible with EmailField.

Oh so close.

From the example at Creating forms from models | Django documentation | Django

# Creating a form to change an existing article.
>>> article = Article.objects.get(pk=1)
>>> form = ArticleForm(instance=article)

When you’re creating an instance of a form, you’re either supplying initial data (initial for a non-Model form or instance for a Model form)

Drawing from the example at Working with forms | Django documentation | Django, the basic flow of a view handling a form - when combined with the previous reference - is:

def view_function(request, parameters):
    # Somehow at this point you want to identify what the instance being edited is.
   some_model_instance = MyModel.objects.get(id=the_parameter)
    if request.method == 'POST':
        # Create an instance of the form, binding it to the post data
        my_form = SomeForm(request.POST, instance=some_model_instance)
        if my_form.is_valid():
            my_form.save()
            return redirect('target_url_name')
        else:
            # Handle invalid form here
    else:
        # Handle a GET
        my_form = SomeForm(instance=some_model_instance)
    return render(request, 'some_template', {'form': my_form})

Notice that the only real difference here is the assignment of a model instance to the form.

so I’m at this point now

@login_required(login_url='home:login')
def ChangeEmailView(request):
        if request.method == 'POST':
            form = EmailChangingForm(request.POST)
            if form.is_valid():

                objects = User.objects.get(email = request.user.email)
                form2 = EmailChangingForm(instance=objects)
                form2.save()

   

            return redirect('home:profilesettings')
            
        else:
            form = EmailChangingForm()
        context = {'form': form}
        return render(request, 'home/email_settings.html', context)

    

and I’m getting this error:

Internal Server Error: /settings/email/
Traceback (most recent call last):
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\contrib\auth\decorators.py", line 21, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "D:\Developement\Projekte\DivusX\DivusX\StartSite\views.py", line 280, in ChangeEmailView
    form2.save()
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\forms\models.py", line 469, in save
    self._save_m2m()
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\forms\models.py", line 436, in _save_m2m
    cleaned_data = self.cleaned_data
AttributeError: 'EmailChangingForm' object has no attribute 'cleaned_data'

What should I do next

I fixed it by myself and now no error appears

@login_required(login_url='home:login')
def ChangeEmailView(request):
        if request.method == 'POST':
            objects = User.objects.get(email = request.user.email)
            form = EmailChangingForm(instance=objects)
            if form.is_valid():
                form.save()
                
            return redirect('home:profilesettings')
            
        else:
            objects = User.objects.get(email = request.user.email)
            form = EmailChangingForm(instance=objects)
        context = {'form': form}
        return render(request, 'home/email_settings.html', context)

but the value still doesnt gets overwritten, nothing in the DB happens because I can see in windows the time when it was editet last and the views.py is different to the db time.

Any ideas whats missing in my code, that it finally works?

Yes, you’ve removed the request.POST parameter from your form reconstruction in the POST handler part of the view.