Skip to content

Commit

Permalink
major multi-profiles cleanup; this branch should now be transparently…
Browse files Browse the repository at this point in the history
… usable either with multi or single profiles
  • Loading branch information
carljm committed Aug 30, 2010
1 parent eab7f83 commit 0ffd2dd
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 58 deletions.
9 changes: 9 additions & 0 deletions idios/base_urls.py
@@ -0,0 +1,9 @@
from django.conf.urls.defaults import *


urlpatterns = patterns("idios.views",
url(r"^$", "profiles", name="profile_list"),
url(r"^profile/(?P<username>[\w\._-]+)/$", "profile", name="profile_detail"),
url(r"^edit/$", "profile_edit", name="profile_edit"),
url(r"^create/$", "profile_create", name="profile_create"),
)
26 changes: 20 additions & 6 deletions idios/models.py
@@ -1,4 +1,3 @@
from django.conf import settings
from django.core.urlresolvers import reverse
from django.db import models
from django.db.models.signals import post_save
Expand All @@ -7,31 +6,46 @@
from django.contrib.auth.models import User

from idios.utils import get_profile_model
from idios.settings import MULTIPLE_PROFILES

try:
from pinax.apps.account.signals import user_logged_in
except ImportError:
user_logged_in = None


class ClassProperty(property):
def __get__(self, cls, owner):
return self.fget.__get__(None, owner)()


class ProfileBase(models.Model):

# @@@ could be unique=True if subclasses don't inherit a concrete base class
# @@@ need to look at this more
user = models.ForeignKey(User, verbose_name=_("user"))

class Meta:
verbose_name = _("profile")
verbose_name_plural = _("profiles")
abstract = True

def __unicode__(self):
return self.user.username

def get_absolute_url(self, group=None):
# @@@ make group-aware / # @@@ hard coded nasty on the profile_slug, refactor immediately
return reverse("profile_detail", kwargs={"profile_slug": "default", "username": self.user.username})
# @@@ make group-aware
kwargs = {"username": self.user.username}
if MULTIPLE_PROFILES:
kwargs["profile_slug"] = self.profile_slug
return reverse("profile_detail", kwargs=kwargs)

@classmethod
def _default_profile_slug(cls):
return cls._meta.module_name

profile_slug = ClassProperty(_default_profile_slug)


def create_profile(sender, instance=None, **kwargs):
if instance is None:
Expand All @@ -44,4 +58,4 @@ def additional_info_kickstart(sender, **kwargs):
request = kwargs.get("request")
request.session["idios_additional_info_kickstart"] = True
if user_logged_in: # protect against Pinax not being available
user_logged_in.connect(additional_info_kickstart)
user_logged_in.connect(additional_info_kickstart)
36 changes: 36 additions & 0 deletions idios/settings.py
@@ -0,0 +1,36 @@
"""
Combine the settings ``AUTH_PROFILE_MODULE`` and
``IDIOS_PROFILE_MODULES`` into a single ``PROFILE_MODULES`` list.
``MULTIPLE_PROFILES`` is True if there is more than one profile model
defined, False otherwise.
``DEFAULT_PROFILE_MODULE`` is the profile model referenced by
``AUTH_PROFILE_MODULE``, or the first one listed in
``IDIOS_PROFILE_MODULES``.
This module also sets a default value of "idios.ProfileBase" for the
``IDIOS_PROFILE_BASE`` setting.
"""

from django.conf import settings


PROFILE_MODULES= []

modules = []
mod = getattr(settings, 'AUTH_PROFILE_MODULE', None)
if mod:
modules.append(mod)

DEFAULT_PROFILE_MODULE = None

for module in modules + getattr(settings, 'IDIOS_PROFILE_MODULES', []):
if DEFAULT_PROFILE_MODULE is None:
DEFAULT_PROFILE_MODULE = module
PROFILE_MODULES.append(module)

MULTIPLE_PROFILES = len(PROFILE_MODULES) > 1

PROFILE_BASE = getattr(settings, 'IDIOS_PROFILE_BASE', 'idios.ProfileBase')
8 changes: 4 additions & 4 deletions idios/urls.py
@@ -1,9 +1,9 @@
from django.conf.urls.defaults import *

from idios.views import profiles, ALL_PROFILES

urlpatterns = patterns("",
url(r"^(?P<profile_slug>[\w\._-]+)/$", "idios.views.profiles", name="profile_list"),
url(r"^(?P<profile_slug>[\w\._-]+)/profile/(?P<username>[\w\._-]+)/$", "idios.views.profile", name="profile_detail"),
url(r"^(?P<profile_slug>[\w\._-]+)/edit/$", "idios.views.profile_edit", name="profile_edit"),
url(r"^(?P<profile_slug>[\w\._-]+)/create/$", "idios.views.profile_create", name="profile_create"),
url(r"^all/$", profiles, {"profile_slug": ALL_PROFILES}, name="profile_list_all"),
url(r"", include("idios.base_urls")),
url(r"^(?P<profile_slug>[\w\._-]+)/", include("idios.base_urls")),
)
82 changes: 58 additions & 24 deletions idios/utils.py
@@ -1,56 +1,90 @@
"""
Utility functions for retrieving and generating forms for the
site-specific user profile model specified in the
``AUTH_PROFILE_MODULE`` setting.
``AUTH_PROFILE_MODULE`` or ``IDIOS_PROFILE_MODULES`` settings.
This file was pulled from django-profiles as it made the most sense. Slightly
modified for Eldarion standards.
"""
from django import forms
from django.conf import settings
from django.db.models import get_model

from django.contrib.auth.models import SiteProfileNotAvailable

from idios import settings

def get_profile_base():
"""
Return the profile model class which is the base class for all
profile models (used for querying on all profiles).
If multiple-profiles are not in use, this will be the single
profile model class itself: there is no reason to query on an
ancestor model in this case.
If multiple-profiles are in use, this will be the model class
referenced by the ``IDIOS_PROFILE_BASE`` setting. Normally this
will be idios' own ``ProfileBase`` model, but some projects may
have another model class inheriting from ProfileBase and defining
some additional fields, which all their profile models then
inherit from in turn.
If the appropriate setting does not resolve to an actual model,
raise ``django.contrib.auth.models.SiteProfileNotAvailable``.
"""
if settings.MULTIPLE_PROFILES:
module = settings.PROFILE_BASE
else:
module = settings.DEFAULT_PROFILE_MODULE
model = get_model(*module.split('.'))
if model is None:
raise SiteProfileNotAvailable
return model


def get_profile_model(profile_slug=None):
"""
Return the model class for the currently-active user profile
model, as defined by the ``AUTH_PROFILE_MODULE`` setting. If that
setting is missing, raise
Return the model class for the profile module identified by the
given ``profile_slug``, as defined in the ``AUTH_PROFILE_MODULE``
or ``IDIOS_PROFILE_MODULES`` settings.
If ``profile_slug`` is not provided, return the default profile
model.
If no matching profile model is found, return None.
If no default profile model is found, raise
``django.contrib.auth.models.SiteProfileNotAvailable``.
"""
if profile_slug is None:
if (not hasattr(settings, "AUTH_PROFILE_MODULE")) or \
(not settings.AUTH_PROFILE_MODULE):
module = settings.DEFAULT_PROFILE_MODULE
model = get_model(*module.split('.'))
if model is None:
raise SiteProfileNotAvailable
module = settings.AUTH_PROFILE_MODULE
else:
if (not hasattr(settings, "IDIOS_PROFILE_MODULES")) or \
(not settings.IDIOS_PROFILE_MODULES) or \
(not settings.IDIOS_PROFILE_MODULES.get(profile_slug)):
raise SiteProfileNotAvailable
module = settings.IDIOS_PROFILE_MODULES.get(profile_slug).get("model")
profile_mod = get_model(*module.split("."))
if profile_mod is None:
raise SiteProfileNotAvailable
return profile_mod
for module in settings.PROFILE_MODULES:
model = get_model(*module.split('.'))
if model and profile_slug == model.profile_slug:
break
else:
model = None
return model


def get_profile_form(profile_slug):
def get_profile_form(profile_model=None):
"""
Return a form class (a subclass of the default ``ModelForm``)
suitable for creating/editing instances of the site-specific user
profile model, as defined by the ``AUTH_PROFILE_MODULE``
setting. If that setting is missing, raise
``django.contrib.auth.models.SiteProfileNotAvailable``.
suitable for creating/editing instances of the given user profile
model.
"""
profile_mod = get_profile_model(profile_slug)
if profile_model is None:
profile_model = get_profile_model()
class _ProfileForm(forms.ModelForm):
class Meta:
model = profile_mod
model = profile_model
exclude = ("user",) # user will be filled in by the view.
return _ProfileForm

0 comments on commit 0ffd2dd

Please sign in to comment.