Metadata-Version: 1.1
Name: swapper
Version: 0.3.0
Summary: The unofficial Django swappable models API.
Home-page: https://github.com/wq/django-swappable-models
Author: S. Andrew Sheppard
Author-email: andrew@wq.io
License: MIT
Description: Swapper
        =======
        
        Django Swappable Models - No longer only for auth.User!
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        
        Swapper is an unofficial API for the
        `undocumented <https://code.djangoproject.com/ticket/19103>`__ but very
        powerful Django feature: swappable models. Swapper facilitates
        implementing arbitrary swappable models in your own reusable apps.
        
        |Latest PyPI Release| |Release Notes| |License| |GitHub Stars| |GitHub
        Forks| |GitHub Issues|
        
        |Travis Build Status| |Python Support| |Django Support|
        
        Motivation
        ----------
        
        Suppose your reusable app has two related tables:
        
        .. code:: python
        
            from django.db import models
            class Parent(models.Model):
                name = models.TextField()
        
            class Child(models.Model):
                name = models.TextField()
                parent = models.ForeignKey(Parent)
        
        Suppose further that you want to allow the user to subclass either or
        both of these models and supplement them with their own additional
        fields. You could use Abstract classes (e.g. ``BaseParent`` and
        ``BaseChild``) for this, but then you would either need to:
        
        1. Avoid putting the foreign key on ``BaseChild`` and tell the user they
           need to do it.
        2. Put the foreign key on ``BaseChild``, but make ``Parent`` a concrete
           model that can't be swapped
        3. Use swappable models, together with ``ForeignKeys`` that read the
           swappable settings.
        
        This third approach is taken by Django to facilitate `swapping the
        auth.User
        model <https://docs.djangoproject.com/en/1.7/topics/auth/customizing/#auth-custom-user>`__.
        The ``auth.User`` swappable code was implemented in a generic way that
        allows it to be used for any model. Although this capability is
        currently `undocumented <https://code.djangoproject.com/ticket/19103>`__
        while any remaining issues are being sorted out, it has proven to be
        very stable and useful in our experience.
        
        Swapper is essentially a simple API wrapper around this existing
        functionality.
        
        Real-World Example
        ------------------
        
        Swapper is used extensively in the `vera <http://wq.io/vera>`__
        extension to `wq.db <http://wq.io/wq.db>`__. vera provides `7
        inter-related models <https://github.com/wq/vera#models>`__, each of
        which can be swapped out for custom implementations. (Swapper actually
        started out as part of
        `wq.db.patterns <http://wq.io/docs/about-patterns>`__, but was extracted
        for more general-purpose use.)
        
        Getting Started
        ---------------
        
        .. code:: bash
        
            pip3 install swapper
        
        Usage
        -----
        
        Extending the above example, create abstract base classes and default
        implementations:
        
        .. code:: python
        
            # reusableapp/models.py
            from django.db import models
            import swapper
        
            class BaseParent(models.Model):
                # minimal base implementation ...
                class Meta:
                    abstract = True
        
            class Parent(BaseParent):
                # default (swappable) implementation ...
                class Meta:
                   swappable = swapper.swappable_setting('reusableapp', 'Parent')
        
            class BaseChild(models.Model):
                parent = models.ForeignKey(swapper.get_model_name('reusableapp', 'Parent'))
                # minimal base implementation ...
                class Meta:
                    abstract = True
        
            class Child(BaseChild):
                # default (swappable) implementation ...
                class Meta:
                   swappable = swapper.swappable_setting('reusableapp', 'Child')
        
        User Customization
        ~~~~~~~~~~~~~~~~~~
        
        With the above setup, the user of your app can override one or both
        models in their own app:
        
        .. code:: python
        
            # myapp/models.py
            from reusableapp.models import BaseParent
            class Parent(BaseParent):
                # custom implementation ...
        
        The user then specifies the appropriate setting to trigger the swap:
        
        .. code:: python
        
            # myproject/settings.py
            REUSABLEAPP_PARENT_MODEL = "myapp.Parent"
        
        Loading Swapped Models
        ~~~~~~~~~~~~~~~~~~~~~~
        
        In your views and other functions, always use the swapper instead of
        importing swappable models directly.
        
        .. code:: python
        
            # reusableapp/views.py
        
            # Might work, might not
            # from .models import Parent
        
            import swapper
            Parent = swapper.load_model("reusableapp", "Parent")
            Child = swapper.load_model("reusableapp", "Child")
        
            def view(request, *args, **kwargs):
                qs = Parent.objects.all()
                # ...
        
            Note: ``swapper.load_model()`` is the general equivalent of
            `get\_user\_model() <https://docs.djangoproject.com/en/1.7/topics/auth/customizing/#referencing-the-user-model>`__
            and subject to the same constraints: e.g. it should not be used
            until after the model system has fully initialized.
        
        Migration Scripts
        ~~~~~~~~~~~~~~~~~
        
        Swapper can also be used in Django 1.7+ migration scripts to facilitate
        dependency ordering and foreign key references. To use this feature,
        generate a migration script with ``makemigrations`` and make the
        following changes:
        
        .. code:: diff
        
              # reusableapp/migrations/0001_initial.py
        
              from django.db import models, migrations
            < from django.conf import settings
            > import swapper
        
              class Migration(migrations.Migration):
        
                  dependencies = [
            <          migrations.swappable_dependency(settings.REUSABLEAPP_PARENT_MODEL),
            >          swapper.dependency('reusableapp', 'Parent')
                  ]
        
                  operations = [
                      migrations.CreateModel(
                          name='Child',
                          fields=[
                              ('id', models.AutoField(auto_created=True, serialize=False, primary_key=True, verbose_name='ID')),
                          ],
                          options={
            <                 'swappable': 'REUSABLEAPP_CHILD_MODEL',
            >                 'swappable': swapper.swappable_setting('reusableapp', 'Child'),
                          },
                          bases=(models.Model,),
                      ),
                      migrations.CreateModel(
                          name='Parent',
                          fields=[
                              ('id', models.AutoField(auto_created=True, serialize=False, primary_key=True, verbose_name='ID')),
                          ],
                          options={
            <                 'swappable': 'REUSABLEAPP_PARENT_MODEL',
            >                 'swappable': swapper.swappable_setting('reusableapp', 'Parent'),
                          },
                          bases=(models.Model,),
                      ),
                      migrations.AddField(
                          model_name='child',
                          name='parent',
            <             field=models.ForeignKey(to=settings.REUSABLEAPP_PARENT_MODEL),
            >             field=models.ForeignKey(to=swapper.get_model_name('reusableapp', 'Parent')),
                          preserve_default=True,
                      ),
                  ]
        
        API Documentation
        -----------------
        
        +---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
        | function                                          | purpose                                                                                                                                                                                                                                                                                                 |
        +===================================================+=========================================================================================================================================================================================================================================================================================================+
        | ``swappable_setting(app_label, model)``           | Generates a swappable setting name for the provided model (e.g. ``"REUSABLEAPP_PARENT_MODEL"``)                                                                                                                                                                                                         |
        +---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
        | ``is_swapped(app_label, model)``                  | Determines whether or not a given model has been swapped. (Returns the model name if swapped, otherwise ``False``)                                                                                                                                                                                      |
        +---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
        | ``get_model_name(app_label, model)``              | Gets the name of the model the swappable model has been swapped for (or the name of the original model if not swapped.)                                                                                                                                                                                 |
        +---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
        | ``get_model_names(app_label, models)``            | Match a list of model names to their swapped versions. All of the models should be from the same app (though their swapped versions need not be).                                                                                                                                                       |
        +---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
        | ``load_model(app_label, model, required=True)``   | Load the swapped model class for a swappable model (or the original model if it hasn't been swapped). If your code can function without the specified model, set ``required = False``.                                                                                                                  |
        +---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
        | ``dependency(app_label, model)``                  | Generate a dependency tuple for use in Django 1.7+ migrations.                                                                                                                                                                                                                                          |
        +---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
        | ``set_app_prefix(app_label, prefix)``             | Set a custom prefix for swappable settings (the default is the upper case ``app_label``). Used in `wq.db <http://wq.io/wq.db>`__ to make all of the swappable settings start with ``"WQ"`` (e.g. ``WQ_FILE_MODEL`` instead of ``FILES_FILE_MODEL``). This should be set at the top of your models.py.   |
        +---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
        | ``join(app_label, model)``, ``split(model)``      | Utilities for splitting and joining ``"app.Model"`` strings and ``("app", "Model")`` tuples.                                                                                                                                                                                                            |
        +---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
        
        .. |Latest PyPI Release| image:: https://img.shields.io/pypi/v/swapper.svg
           :target: https://pypi.python.org/pypi/swapper
        .. |Release Notes| image:: https://img.shields.io/github/release/wq/django-swappable-models.svg
           :target: https://github.com/wq/django-swappable-models/releases
        .. |License| image:: https://img.shields.io/pypi/l/swapper.svg
           :target: https://github.com/wq/django-swappable-models/blob/master/LICENSE
        .. |GitHub Stars| image:: https://img.shields.io/github/stars/wq/django-swappable-models.svg
           :target: https://github.com/wq/django-swappable-models/stargazers
        .. |GitHub Forks| image:: https://img.shields.io/github/forks/wq/django-swappable-models.svg
           :target: https://github.com/wq/django-swappable-models/network
        .. |GitHub Issues| image:: https://img.shields.io/github/issues/wq/django-swappable-models.svg
           :target: https://github.com/wq/django-swappable-models/issues
        .. |Travis Build Status| image:: https://img.shields.io/travis/wq/django-swappable-models.svg
           :target: https://travis-ci.org/wq/django-swappable-models
        .. |Python Support| image:: https://img.shields.io/pypi/pyversions/swapper.svg
           :target: https://pypi.python.org/pypi/swapper
        .. |Django Support| image:: https://img.shields.io/badge/Django-1.6%2C%201.7%2C%201.8%2C%201.9-blue.svg
           :target: https://pypi.python.org/pypi/swapper
        
Platform: UNKNOWN
Classifier: Framework :: Django
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: License :: OSI Approved :: MIT License
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
