4

I'm trying to create an update profile page for my custom User model. In my model, my email field is set to be unique.

class User(UserBase):
     ...
     email = models.EmailField(
            max_length=100,
            unique=True,
            blank=True,
            verbose_name='email address',
        )

Then in my view I have:

class UpdateProfileView(LoginRequiredMixin, UpdateView):
    template_name = 'accounts/update-profile.html'
    form_class = UpdateProfileForm
    model = User

The only thing that UpdateProfileForm does is check that the old password is different from the new one in the clean method.

My issue is that when I save the form I'm getting the error message User with this Email address already exists.. Since it's an update view and saving a unique field that hasn't changed shouldn't it not throw this error? If this is the correct behavior, then how do I save the form and ignore the email address if it hasn't changed.

Thanks for the help in advance.

6
  • Am I taking crazy pills, is this not a thing or a dumb question? Commented Feb 7, 2014 at 15:19
  • No one has any feedback on this? Commented Mar 18, 2014 at 15:30
  • 1
    Why don't you show us the UpdateProfileForm so we can get a better idea. Commented Mar 18, 2014 at 15:34
  • 3
    Right from the form.save docs: "A subclass of ModelForm can accept an existing model instance as the keyword argument instance; if this is supplied, save() will update that instance. If it’s not supplied, save() will create a new instance of the specified model." Are you using the instance argument? Commented Mar 18, 2014 at 15:39
  • 1
    Does it work when you comment out the form_class? Commented Mar 18, 2014 at 19:01

3 Answers 3

2
+50

Remove blank=True from your User Model definition. The field definition is null=False by default and additionally you specify the field must be unique—it's a important field—so you don't want your form validation to allow blank values. Here is the Django documentation on those attributes. blank is entirely a form validation thing. That alone might fix the error.

Unless you have custom form logic/validation, you don't need the form_class attribute on your UpdateProfileView. From the docs: "These generic views will automatically create a ModelForm". (There is even an UpdateView example).

See if the view works without form_class and if it does then examine your UpdateProfileForm code.

Sign up to request clarification or add additional context in comments.

Comments

0

Here are some suggestions/alternatives:

  1. If you stop using Generic Views (i.e. UpdateProfileView), you can then do the following steps in your logic view: if the request is a POST, take the data from the form and update your Model (How to update fields in a model without creating a new record in django?)

  2. Why don't you use a ModelForm instead? https://docs.djangoproject.com/en/dev/topics/forms/modelforms/

  3. Why don't you work with User from django.contrib.auth.models? https://docs.djangoproject.com/en/dev/topics/auth/default/#user-objects

  4. Finally, have you considered working with this already built Django registration app? http://www.michelepasin.org/blog/2011/01/14/setting-up-django-registration/

Comments

0
  1. Never use blank=True and unique=True, its senseless. If you want to make this field is not required in form, just do.

    class Form(forms.Form):
         ...
    
         def __init__(self, *args, **kwargs):
              super().__init__(*args, **kwargs)
              self.fields['unique_field].required = False 
    
  2. In addition to previous answer, when u use blank=True and unique=True, the "Is already exits ... blah bla" its correct behavior, coz form accepting empty string as value and its already exists. You need to override clean_field method:

    class Form(forms.Form):
        ...
    
        def clean_unique_id(self):
            """
            Take new value or if its '' e.g. None take initial value 
            """
            return self.data['unique_id'] or self.initial['unique_id']
    

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.