Newly added fields not showing in Profile Edit form in Django Oscar?

820 views
Skip to first unread message

Nikhil Manhas

unread,
Aug 28, 2015, 7:59:19 AM8/28/15
to django-oscar

I want to extend the User model. I followed the steps mentioned in this doc. I made a new app extended_user whose models.py reads as :


from django.db import models

from oscar.apps.customer.abstract_models import AbstractUser
from django.utils.translation import ugettext_lazy as _


class User(AbstractUser):

    nickname =  models.CharField(_("nick_name"), max_length=50, null=True, blank=True)

    def get_full_name(self):
        full_name = '%s %s' % (self.last_name.upper(), self.first_name)
        return full_name.strip()

In settings.py I mention

AUTH_USER_MODEL = "extended_user.User"


I make and run migrations. In profile view I can see nickname field but in Profile Edit view I don't. What do I have to do to see the newly added field in the Profile Edit form ?

06us...@gmail.com

unread,
Sep 26, 2015, 11:22:41 AM9/26/15
to django-oscar

Hello,

Has some solution been found ? I am encountering same problem : when adding a new field to a Customized User Model (field "Musician" in example below) :
- "musician" is seen when viewing profile
- "musician" is not seen when editing profile

See screenshots below + models.py (extract) + settings.py (extract)

Django Oscar 1.1.1, Django 1.8, Python3.4

Thks for any hint/guidance.

View


Edit Profile


Models.py (extract)
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
    # musician
    musician = models.BooleanField(_('Musician (knows how to play piano, guitar, ..)'), default=False)

    def get_full_name(self):
        full_name = '%s %s' % (self.last_name.upper(), self.first_name)
        return full_name.strip()


Settings.py (extract)
INSTALLED_APPS = [
    'apps.user',
]
AUTH_USER_MODEL = 'user.User'

Auto Generated Inline Image 1
Auto Generated Inline Image 2

Ashia Zawaduk

unread,
Sep 29, 2015, 5:10:59 PM9/29/15
to django-oscar
It looks like the Profile Update View loads it's own ProfileForm:

class ProfileUpdateView(PageTitleMixin, generic.FormView):
    form_class = ProfileForm

It's loaded dynamically just like other models and forms in oscar so you should be able to override it.


The meta class specifies the fields you want to be editable, and this is what you need to change in your new form.
Hope that helps,
Ashia

06us...@gmail.com

unread,
Sep 30, 2015, 1:17:11 AM9/30/15
to django-oscar
Ashia,
Thanks for your feedback. I will investigate this solution asap (in the next few days), and will update post accordingly.
Cheers.


Message has been deleted

06us...@gmail.com

unread,
Oct 1, 2015, 1:28:15 PM10/1/15
to django-oscar
Ashia,
MANY THANKS, solution you proposed is OK :-)
Indeed, by overriding customer.forms.ProfileForm with customized list of fields, the customized fields are visible in the Edit Profile.
In order to override customer.forms.ProfileForm, customer app must be forked, as explained in Django Oscar documentation http://django-oscar.readthedocs.org/en/latest/topics/fork_app.html .
I am documenting solution below, for information.
Cheers.


Models.py (extract)
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
    # musician
       musician = models.CharField(_('Musician (knows how to play piano, guitar, ..)'), max_length=80)


    def get_full_name(self):
        full_name = '%s %s' % (self.last_name.upper(), self.first_name)
        return full_name.strip()     musician = models.CharField(_('Musician (knows how to play piano, guitar, ..)'), max_length=80


Fork customer app

manage.py oscar_fork_app customer apps


Settings.py (extract)
INSTALLED_APPS = [
    'apps.user',
]
AUTH_USER_MODEL = 'user.User'


[...]
# oscar
INSTALLED_APPS += [
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.flatpages',
    'compressor',
    'widget_tweaks',
#] + get_core_apps()
# override core customer class
] + get_core_apps(['apps.customer'])


my_project/apps/customer/forms.py
# my_project/apps/customer/forms.py
# override customer.forms.ProfileForm with customized list of fields
from oscar.apps.customer.forms import ProfileForm as UserProfileForm
from oscar.core.compat import get_user_model, existing_user_fields

User = get_user_model()

class ProfileForm(UserProfileForm):

    class Meta:
        model = User
        fields = existing_user_fields(['first_name', 'last_name', 'musician', 'email'])

Edit Profile


Auto Generated Inline Image 1

Ashia Zawaduk

unread,
Oct 2, 2015, 6:07:20 PM10/2/15
to django-oscar
Excellent, glad to hear that.
Just a small correction to the code you provided, Oscar has some code that was written before custom users existed in Django (pre 1.5). Back in the day we used to have to make a separate Profile model and connect it to the user model.
This is why there is a function called get_profile_class():
https://github.com/django-oscar/django-oscar/blob/master/src/oscar/core/loading.py#L200

Anyone using a custom user should override UserForm not UserProfileForm.
So your code should be:
class ProfileForm(UserForm):


    class Meta:
        model = User
        fields = existing_user_fields(['first_name', 'last_name', 'musician', 'email'])

Thanks for documenting with code.
Ashia

06us...@gmail.com

unread,
Oct 3, 2015, 2:26:31 AM10/3/15
to django-oscar

Ashia,


>Anyone using a custom user should override UserForm not UserProfileForm.

Thanks for pointing this out. I have made the correction in code (forms.py, see below), and everything looks OK. Your expertise is much appreciated :-)

Cheers.


my_project/apps/customer/forms.py
# my_project/apps/customer/forms.py
# override customer.forms.ProfileForm with customized list of fields
from oscar.apps.customer.forms import ProfileForm as UserForm

from oscar.core.compat import get_user_model, existing_user_fields

User = get_user_model()

Reply all
Reply to author
Forward
0 new messages