Browse files

Some corrections and add the userprofile base stuff

  • Loading branch information...
1 parent 056854f commit c0defb177d0f0497b2bf7a364ff2a3843bf0c9ee @sveetch committed Aug 23, 2012
Showing with 182 additions and 6 deletions.
  1. +8 −1 README.rst
  2. +1 −1 setup.py
  3. +1 −1 sveeaccounts/__init__.py
  4. +81 −2 sveeaccounts/forms.py
  5. +56 −0 sveeaccounts/models.py
  6. +0 −1 sveeaccounts/templates/registration/login.html
  7. +35 −0 sveeaccounts/views.py
View
9 README.rst
@@ -1,5 +1,6 @@
.. _autobreadcrumbs: http://pypi.python.org/pypi/autobreadcrumbs
.. _Django: https://www.djangoproject.com/
+.. _django-braces: https://github.com/sveetch/django-braces
.. _django-crispy-forms: https://github.com/maraujop/django-crispy-forms
.. _django-simple-captcha: https://github.com/mbi/django-simple-captcha
.. _django-registration: http://pypi.python.org/pypi/django-registration
@@ -13,7 +14,11 @@ Introduction
This is not really intended to be a generic app, so use it at your own risk.
Actually this is just an implementation of an inherited `django-registration`_ backend with
-`django-simple-captcha`_ usage.
+`django-simple-captcha`_ usage and with a `UserProfileBase` abstract model (and his
+form, and his form view) that can be used as a base for user profiles.
+
+A ``REGISTRATION_BLOCKED`` optionnal variable can be added in settings, if at ``True``
+the new registration form is blocked, default is ``False``.
Links
*****
@@ -27,6 +32,7 @@ Requires
========
* `autobreadcrumbs`_;
+* My `django-braces`_ fork;
* `django-registration`_ >= 0.8;
* `django-simple-captcha`_ >= 0.3.4;
* `django-crispy-forms`_ >= 1.1.x;
@@ -47,3 +53,4 @@ In your *settings* file add the app to your installed apps :
...
)
+Then you have to mount its urls map in your webapp urls.
View
2 setup.py
@@ -14,7 +14,7 @@
'Programming Language :: Python',
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
- 'Development Status :: 3 - Alpha',
+ 'Development Status :: 4 - Beta',
'Environment :: Web Environment',
'Framework :: Django',
'Intended Audience :: Developers',
View
2 sveeaccounts/__init__.py
@@ -2,4 +2,4 @@
"""
Django application to embed all the registration stuff with captcha
"""
-__version__ = '0.2.1'
+__version__ = '0.2.2'
View
83 sveeaccounts/forms.py
@@ -1,16 +1,19 @@
# -*- coding: utf-8 -*-
+from django import forms
from django.contrib.auth.forms import AuthenticationForm
from django.utils.translation import ugettext
from registration.forms import RegistrationFormUniqueEmail
from crispy_forms.helper import FormHelper
-from crispy_forms.layout import Submit
+from crispy_forms.layout import Layout, Fieldset, Div, Submit
+from crispy_forms.bootstrap import FormActions
from captcha.fields import CaptchaField
+from sveeaccounts.models import UserProfileBase
+
class RegistrationWithCaptchaForm(RegistrationFormUniqueEmail):
- #captcha = CaptchaField(label=u"Anti", help_text=u"Veuillez entrer les quatres lettres que vous voyez dans l'image ci-dessus.")
captcha = CaptchaField()
def __init__(self, *args, **kwargs):
@@ -31,3 +34,79 @@ def __init__(self, *args, **kwargs):
self.helper.add_input(Submit('submit', ugettext('Ok')))
super(LoginForm, self).__init__(*args, **kwargs)
+
+def UserProfileBaseLayout():
+ """
+ Return the default layout, this must be wrapped in a function to correct
+ translations
+ """
+ return Layout(
+ Fieldset(
+ ugettext('account'),
+ 'new_password1',
+ 'new_password2',
+ ),
+ Fieldset(
+ ugettext('identity'),
+ 'first_name',
+ 'last_name',
+ 'email',
+ 'adress',
+ 'town',
+ 'zipcode',
+ 'phone_number',
+ 'mobile_number',
+ ),
+ )
+
+class UserProfileBaseForm(forms.ModelForm):
+ """
+ User profile form
+ """
+ # Bind only some fields from the user model
+ first_name = forms.CharField(label=ugettext('first name'), max_length=30, required=True)
+ last_name = forms.CharField(label=ugettext("last name"), max_length=30, required=True)
+ email = forms.EmailField(label=ugettext("E-mail"), max_length=75, required=True)
+ new_password1 = forms.CharField(label=ugettext("Password"), widget=forms.PasswordInput, required=False)
+ new_password2 = forms.CharField(label=ugettext("Password (again)"), widget=forms.PasswordInput, required=False)
+
+ def __init__(self, *args, **kwargs):
+ self.author = kwargs.pop('user')
+
+ self.helper = FormHelper()
+ self.helper.form_action = '.'
+ self.helper.form_class = 'form-horizontal well'
+ self.helper.form_style = 'inline'
+ self.helper.layout = Layout(
+ kwargs.pop('layout', UserProfileBaseLayout()),
+ FormActions(
+ Submit('submit', 'Submit'),
+ )
+ )
+
+ super(UserProfileBaseForm, self).__init__(*args, **kwargs)
+
+ def clean_new_password2(self):
+ password1 = self.cleaned_data.get('new_password1')
+ password2 = self.cleaned_data.get('new_password2')
+ if password1 and password2:
+ if password1 != password2:
+ raise forms.ValidationError(ugettext("The two password fields didn't match."))
+ return password2
+
+ def save(self, *args, **kwargs):
+ instance = super(UserProfileBaseForm, self).save(commit=True, *args, **kwargs)
+
+ u = instance.user
+ u.first_name = self.cleaned_data["first_name"]
+ u.last_name = self.cleaned_data["last_name"]
+ u.email = self.cleaned_data["email"]
+ u.save()
+ if self.cleaned_data.get("new_password2", None) and len(self.cleaned_data["new_password2"].strip())>0:
+ u.set_password(self.cleaned_data["new_password2"])
+
+ return instance
+
+ class Meta:
+ model = UserProfileBase
+ exclude = ('user',)
View
56 sveeaccounts/models.py
@@ -1 +1,57 @@
# -*- coding: utf-8 -*-
+from django.core.exceptions import ObjectDoesNotExist
+from django.db import models
+from django.utils.translation import ugettext_lazy as _
+from django.contrib.auth.models import User
+import types
+
+class UserProfileBase(models.Model):
+ u"""
+ User Profile to extend the User model
+ """
+ user = models.ForeignKey(User, unique=True, blank=False)
+ adress = models.TextField(_('adress'), blank=False)
+ town = models.CharField(_('town'), max_length=75, blank=False)
+ zipcode = models.CharField(_('zipcode'), max_length=6, blank=False)
+ phone_number = models.CharField(_('phone'), max_length=20, blank=False)
+ mobile_number = models.CharField(_('mobile'), max_length=20, blank=True, null=True)
+
+ def __unicode__(self):
+ return u"{0}'s profile".format(self.user.username)
+
+ class Meta:
+ abstract = True
+ verbose_name = _("user profile")
+ verbose_name_plural = _("user profiles")
+
+def append_profile_on_user_create(sender, instance, created, **kwargs):
+ """
+ Automatically add an empty profile on user create if it doesn't exist yet
+
+ Need to be connected to model with something like that : ::
+
+ from django.contrib.auth.models import User
+ from django.db.models.signals import post_save as post_save_signal
+ post_save_signal.connect(append_profile_on_user_create, sender=User)
+
+ "extra_fields" can be passed in kwargs, it will contain extra fields (like these
+ appended by inherit the abstract model) with their default value. Also theses values
+ can be a lambda which receive the user instance and return a correct value.
+ """
+ if created:
+ try:
+ instance.get_profile()
+ except ObjectDoesNotExist:
+ extra_fields = kwargs.get('extra_fields', {})
+
+ for k,v in extra_fields.items():
+ if isinstance(v, types.FunctionType):
+ extra_fields[k] = v(instance)
+
+ instance.userprofile_set.create(
+ adress='placeholder',
+ town='placeholder',
+ zipcode='empty',
+ phone_number='placeholder',
+ **extra_fields
+ )
View
1 sveeaccounts/templates/registration/login.html
@@ -4,7 +4,6 @@
{% block head_more_links %}
<link rel="stylesheet" href="{{ STATIC_URL }}uni_form/uni-form.css" type="text/css" />
<link rel="stylesheet" href="{{ STATIC_URL }}uni_form/default.uni-form.css" type="text/css" />
- <link rel="stylesheet" href="{{ STATIC_URL }}sveedocuments/css/forms.css" type="text/css" />
{% endblock %}
{% block head_more_js %}
<script type="text/javascript" src="{{ STATIC_URL }}uni_form/uni-form.jquery.js"></script>
View
35 sveeaccounts/views.py
@@ -0,0 +1,35 @@
+# -*- coding: utf-8 -*-
+"""
+Accounts views
+"""
+from django.views.generic import UpdateView
+from django.core.urlresolvers import reverse
+
+from braces.views import UserFormKwargsMixin, LoginRequiredMixin
+
+from sveeaccounts.models import UserProfileBase
+from sveeaccounts.forms import UserProfileBaseForm
+
+class MyAccountBaseView(LoginRequiredMixin, UserFormKwargsMixin, UpdateView):
+ """
+ The form view to edit the user account and his profile
+
+ The following attributes are required and you have also to define a
+ 'get_success_url' method.
+ """
+ template_name = None # Required
+ form_class = UserProfileBaseForm
+ model = None # Required. This should be assigned with your profile model
+
+ def get_object(self, *args, **kwargs):
+ return self.request.user.get_profile()
+
+ def get_initial(self):
+ """
+ Returns the initial data to use for forms on this view.
+ """
+ return {
+ 'first_name': self.request.user.first_name,
+ 'last_name': self.request.user.last_name,
+ 'email': self.request.user.email,
+ }

0 comments on commit c0defb1

Please sign in to comment.