django-polymorphic-auth 0.4
Polymorphic user model with plugins for common options, plus abstract and mixin classes to create your own.
License: MIT

|Build Status| |Coverage Status| |Version|

Overview
========

Provides a polymorphic parent ``User`` model and several child models.

You can enable and disable child models without affecting foreign keys
to the the parent model, and avoid complicated schema and data
migrations.

You can even have multiple child models active at the same time!

How It Works
============

The polymorphic parent model contains the bare minimum required by
Django for a user model. This is where your foreign keys will point to
(via the ``AUTH_USER_MODEL`` setting), and this allows you to avoid
schema migrations when changing child models.

Check out the
`django-polymorphic <https://django-polymorphic.readthedocs.org/en/latest/index.html>`__
docs for more information on the underlying system that makes this
possible.

Plugins
=======

Several child models are also provided as ``usertype`` plugins for
common use cases (email login, username login, etc.), along with a
number of abstract models and mixin classes that you can use to create
your own plugins.

For example:

::

    # myproject/usertypes/foo/models.py

    from django.utils.translation import ugettext_lazy as _
    from polymorphic_auth.models import AbstractUser

    class FooUser(AbstractUser):
        foo = models.CharField(unique=True)

        USERNAME_FIELD = 'foo'

        class Meta:
            verbose_name = _('user with foo login')
            verbose_name_plural = _('users with foo login')

Then just add your plugin to the ``INSTALLED_APPS`` setting and point to
your model in the ``POLYMORPHIC_AUTH['DEFAULT_CHILD_MODEL']`` setting:

::

    # myproject/settings.py

    AUTH_USER_MODEL = 'polymorphic_auth.User'
    INSTALLED_APPS += ('myproject.usertypes.foo', )
    POLYMORPHIC_AUTH = {'DEFAULT_CHILD_MODEL': 'foo.FooUser'}

ADMINS and MANAGERS Settings
============================

The default app contains a ``post_migrate`` signal handler that will
create superuser and staff accounts for each name and email in the
``ADMINS`` and ``MANAGERS`` settings, and write the credentials to
``sys.stdout`` (configurable).

Say goodbye to ``./manage.py createsuperuser``!

To add support to your custom plugins, override the
``AbstractUser.try_create`` classmethod and have it derive values for
required fields from the ``name`` and ``email`` kwargs.

For example:

::

    # myproject/usertypes/foo/models.py

    import re

    class FooUser(AbstractUser):
        ...

        @classmethod
        def try_create(self, **kwargs):
            email = kwargs.get('email', '')
            kwargs.setdefault('foo', re.sub(r'@.+', '', email))
            return super(FooUser, cls).try_create(**kwargs)

Admin
=====

If more than one plugin is installed, you will be asked which type of
user you want to create when adding a new user via the admin. If there
is only one plugin installed, it will take you directly to the change
form for that plugin.

You can customise the admin class for your plugins:

::

    # myproject/usertypes/foo/admin.py

    from myproject.usertypes.foo.forms import FooForm
    from polymorphic_auth.admin import UserChildAdmin

    class EmailUserAdmin(UserChildAdmin):

        # define custom features here

TODO
====

-  Registration system for plugins, instead of hard coding the provided
   ones and checking ``INSTALLED_APPS``.
-  Authentication backend that checks all registered plugins, not just
   the one assigned to ``POLYMORPHIC_AUTH['DEFAULT_CHILD_MODEL']``.
-  Make ``email`` field case insensitive.

.. |Build Status| image:: https://img.shields.io/travis/ixc/django-polymorphic-auth.svg
   :target: https://travis-ci.org/ixc/django-polymorphic-auth
.. |Coverage Status| image:: https://img.shields.io/coveralls/ixc/django-polymorphic-auth.svg
   :target: https://coveralls.io/github/ixc/django-polymorphic-auth
.. |Version| image:: https://img.shields.io/pypi/v/django-polymorphic-auth.svg
   :target: https://pypi.python.org/pypi/django-polymorphic-auth