Browse Source

Add support for a truly custom User model

The new model must have an email field but Oscar will work without
anything else.
master
David Winterbottom 12 years ago
parent
commit
d4e51bb6f9

+ 10
- 3
oscar/apps/customer/auth_backends.py View File

6
 
6
 
7
 User = get_user_model()
7
 User = get_user_model()
8
 
8
 
9
-if hasattr(User, 'REQUIRED_FIELDS') and 'email' not in User.REQUIRED_FIELDS:
10
-    raise ImproperlyConfigured("Emailbackend: Your User model must have an email"
11
-                               " field with blank=False")
9
+if hasattr(User, 'REQUIRED_FIELDS'):
10
+    if not (User.USERNAME_FIELD == 'email' or 'email' in User.REQUIRED_FIELDS):
11
+        raise ImproperlyConfigured(
12
+            "Emailbackend: Your User model must have an email"
13
+            " field with blank=False")
12
 
14
 
13
 
15
 
14
 class Emailbackend(ModelBackend):
16
 class Emailbackend(ModelBackend):
17
+    """
18
+    Custom auth backend that users an email address
19
+
20
+    For this to work, the User model must have an 'email' field
21
+    """
15
 
22
 
16
     def authenticate(self, email=None, password=None, *args, **kwargs):
23
     def authenticate(self, email=None, password=None, *args, **kwargs):
17
         if email is None:
24
         if email is None:

+ 31
- 19
oscar/apps/customer/forms.py View File

240
 if Profile:
240
 if Profile:
241
 
241
 
242
     class UserAndProfileForm(forms.ModelForm):
242
     class UserAndProfileForm(forms.ModelForm):
243
-        first_name = forms.CharField(
244
-            label=_('First name'), max_length=128, required=False)
245
-        last_name = forms.CharField(
246
-            label=_('Last name'), max_length=128, required=False)
247
         email = forms.EmailField(label=_('Email address'), required=True)
243
         email = forms.EmailField(label=_('Email address'), required=True)
248
 
244
 
249
-        # Fields from user model
250
-        user_fields = ('first_name', 'last_name', 'email')
251
-
252
         def __init__(self, user, *args, **kwargs):
245
         def __init__(self, user, *args, **kwargs):
253
             self.user = user
246
             self.user = user
254
             try:
247
             try:
260
 
253
 
261
             super(UserAndProfileForm, self).__init__(*args, **kwargs)
254
             super(UserAndProfileForm, self).__init__(*args, **kwargs)
262
 
255
 
263
-            # Add user fields
264
-            self.fields['first_name'].initial = self.instance.user.first_name
265
-            self.fields['last_name'].initial = self.instance.user.last_name
256
+            # Get a list of profile fields to help with ordering later
257
+            profile_field_names = self.fields.keys()
258
+            del profile_field_names[profile_field_names.index('email')]
259
+
266
             self.fields['email'].initial = self.instance.user.email
260
             self.fields['email'].initial = self.instance.user.email
267
 
261
 
268
-            # Ensure user fields are above profile
269
-            order = list(self.user_fields)
270
-            for field_name in self.fields.keys():
271
-                if field_name not in self.user_fields:
272
-                    order.append(field_name)
273
-            self.fields.keyOrder = order
262
+            # Add user fields (we look for core user fields first)
263
+            core_field_names = set([f.name for f in User._meta.fields])
264
+            user_field_names = ['email']
265
+            for field_name in ('first_name', 'last_name'):
266
+                if field_name in core_field_names:
267
+                    user_field_names.append(field_name)
268
+            user_field_names.extend(User._meta.additional_fields)
269
+
270
+            # Store user fields so we know what to save later
271
+            self.user_field_names = user_field_names
272
+
273
+            # Add additional user fields
274
+            additional_fields = forms.fields_for_model(
275
+                User, fields=user_field_names)
276
+            self.fields.update(additional_fields)
277
+
278
+            # Set initial values
279
+            for field_name in user_field_names:
280
+                self.fields[field_name].initial = getattr(user, field_name)
281
+
282
+            # Ensure order of fields is email, user fields then profile fields
283
+            self.fields.keyOrder = user_field_names + profile_field_names
274
 
284
 
275
         class Meta:
285
         class Meta:
276
             model = Profile
286
             model = Profile
290
 
300
 
291
         def save(self, *args, **kwargs):
301
         def save(self, *args, **kwargs):
292
             user = self.instance.user
302
             user = self.instance.user
293
-            user.first_name = self.cleaned_data['first_name']
294
-            user.last_name = self.cleaned_data['last_name']
295
-            user.email = self.cleaned_data['email']
303
+
304
+            # Save user also
305
+            for field_name in self.user_field_names:
306
+                setattr(user, field_name, self.cleaned_data[field_name])
296
             user.save()
307
             user.save()
308
+
297
             return super(ProfileForm, self).save(*args, **kwargs)
309
             return super(ProfileForm, self).save(*args, **kwargs)
298
 
310
 
299
     ProfileForm = UserAndProfileForm
311
     ProfileForm = UserAndProfileForm

+ 6
- 5
oscar/apps/customer/views.py View File

38
 ProductAlert = get_model('customer', 'ProductAlert')
38
 ProductAlert = get_model('customer', 'ProductAlert')
39
 User = get_user_model()
39
 User = get_user_model()
40
 
40
 
41
+
41
 class LogoutView(RedirectView):
42
 class LogoutView(RedirectView):
42
     url = '/'
43
     url = '/'
43
     permanent = False
44
     permanent = False
123
     def get_profile_fields(self, user):
124
     def get_profile_fields(self, user):
124
         field_data = []
125
         field_data = []
125
 
126
 
127
+        # Check for custom user model
128
+        for field_name in User._meta.additional_fields:
129
+            field_data.append(
130
+                self.get_model_field_data(user, field_name))
131
+
126
         # Check for profile class
132
         # Check for profile class
127
         profile_class = get_profile_class()
133
         profile_class = get_profile_class()
128
         if profile_class:
134
         if profile_class:
137
                 field_data.append(
143
                 field_data.append(
138
                     self.get_model_field_data(profile, field_name))
144
                     self.get_model_field_data(profile, field_name))
139
 
145
 
140
-        # Check for custom user model
141
-        for field_name in User._meta.additional_fields:
142
-            field_data.append(
143
-                self.get_model_field_data(user, field_name))
144
-
145
         return field_data
146
         return field_data
146
 
147
 
147
     def get_model_field_data(self, model_class, field_name):
148
     def get_model_field_data(self, model_class, field_name):

+ 6
- 8
oscar/templates/oscar/customer/profile.html View File

65
             </div>
65
             </div>
66
             <table class="table table-striped table-bordered">
66
             <table class="table table-striped table-bordered">
67
                 <tbody>
67
                 <tbody>
68
-                    <tr>
69
-                        <th>{% trans 'Name' %}</th>
70
-                        <td>{{ request.user.get_full_name|default:'-' }}</td>
71
-                    </tr>
72
                     <tr>
68
                     <tr>
73
                         <th>{% trans 'Email address' %}</th>
69
                         <th>{% trans 'Email address' %}</th>
74
                         <td>{{ user.email }}</td>
70
                         <td>{{ user.email }}</td>
81
                         </tr>
77
                         </tr>
82
                         {% endfor %}
78
                         {% endfor %}
83
                     {% endblock %}
79
                     {% endblock %}
84
-                    <tr>
85
-                        <th>{% trans 'Date registered' %}</th>
86
-                        <td>{{ user.date_joined }}</td>
87
-                    </tr>
80
+                    {% if user.date_joined %}
81
+                        <tr>
82
+                            <th>{% trans 'Date registered' %}</th>
83
+                            <td>{{ user.date_joined }}</td>
84
+                        </tr>
85
+                    {% endif %}
88
                 </tbody>
86
                 </tbody>
89
             </table>
87
             </table>
90
 
88
 

+ 35
- 1
sites/sandbox/apps/user/models.py View File

1
 from django.db import models
1
 from django.db import models
2
+from django.utils import timezone
2
 
3
 
3
 from django.contrib.auth import models as auth_models
4
 from django.contrib.auth import models as auth_models
4
 
5
 
20
 
21
 
21
 
22
 
22
 # A simple extension of the core User model
23
 # A simple extension of the core User model
23
-class CustomUserModel(auth_models.AbstractUser):
24
+class ExtendedUserModel(auth_models.AbstractUser):
24
     twitter_username = models.CharField(max_length=255, unique=True)
25
     twitter_username = models.CharField(max_length=255, unique=True)
26
+
27
+
28
+class CustomUserManager(auth_models.BaseUserManager):
29
+
30
+    def create_user(self, email, password=None):
31
+        now = timezone.now()
32
+        email = auth_models.BaseUserManager.normalize_email(email)
33
+        user = self.model(email=email, last_login=now)
34
+        user.set_password(password)
35
+        user.save(using=self._db)
36
+        return user
37
+
38
+    def create_superuser(self, email, password):
39
+        return self.create_user(email, password)
40
+
41
+
42
+# A user model which doesn't extend AbstractUser
43
+class CustomUserModel(auth_models.AbstractBaseUser):
44
+    name = models.CharField(max_length=255, blank=True)
45
+    email = models.EmailField(unique=True)
46
+    twitter_username = models.CharField(max_length=255, unique=True)
47
+
48
+    USERNAME_FIELD = 'email'
49
+
50
+    objects = CustomUserManager()
51
+
52
+    def __unicode__(self):
53
+        return self.email
54
+
55
+    def get_full_name(self):
56
+        return self.name
57
+
58
+    get_short_name = get_full_name

Loading…
Cancel
Save