Metadata-Version: 1.1
Name: django-related
Version: 0.0.6
Summary: Class-based-views mixins for handling related objects
Home-page: https://bitbucket.org/monwara/django-related
Author: Monwara LLC
Author-email: branko@monwara.com
License: BSD
Download-URL: https://bitbucket.org/monwara/django-related/downloads
Description: ==============
        django-related
        ==============
        
        django-related is a set of class-based-view mixins that help with common
        scenarios that involves related objects. The generic class-based views like
        ``CreateView`` or ``UpdateView`` only deal with single objects. However, for
        nested resources, or in cases where we might want to use an existing object if
        avaialble, these views lack functionality. This is what django-related
        provides.
        
        .. contents::
        
        Installation
        ============
        
        Installation can be done using pip::
        
            pip install django-related
        
        There is no need to add ``related`` to installed apps. It can be used
        directly::
            
            from related.views import RedirectOnExistingMixin, CreateWithRelatedMixin
            ...
        
        GetExistingMixin
        ================
        
        This mixin is deprecated. It is currently just an alias for
        RedirectOnExistingMixin_ to provide backwards compatibility. It will be removed
        because of the confusing name.
        
        Only the class name has changed. All property and method names are left intact.
        
        
        RedirectOnExistingMixin
        =======================
        
        This mixin is used when an attempt to create an object that already exists in
        the database should result in a redirect. If the object does not exist in the
        database, it will not do anything.
        
        Basic usage::
        
            from related.views import RedirectOnExistingMixin
            from django.views.gneric import CreateView
        
            from models import Foo
        
            class MyView(RedirectOnExistingMixin, CreateView):
                model = Foo
                existing_redirect_url = '/bar'
        
        With the above view, if we submit a form that contains a ``pk`` or ``slug``
        field, and the ``Foo`` object with matching ``pk`` or ``slug`` field exists,
        user will be redirected to ``/bar`` path, and the model form for ``Foo`` will
        not even be processed. The redirect path can be customized using the options
        discussed further below.
        
        Note that this mixin _will_ result in extra database queries to determine
        whether an object exists.
        
        The view can be further customized using the following properties (and matching
        methods):
        
        ``existing_form_class`` (``get_existing_form_class()``)
            Uses the specified form to process the request rather than request
            parameters. Default is ``None`` (does no use forms).
        
        ``existing_form_field``
            Form field that contains data about existence of the object. Note that this
            field does not need to evaluate to an actual object. Any non-``False``
            value will be treated as signifying object's existence. The most common use
            case is to use a ``ModelChoiceField`` or some field that reads the database
            in advance, and provides a choice of values that are only available when
            objects exist.
        
        ``existing_form_initial`` (``get_existing_form_initial()``)
            Dictionary of initial values for the ``existing_form_class`` form (if form
            is used).
        
        ``existing_pk_field``
            The model field that contains the primary key. Default is ``'pk'``.
        
        ``existing_slug_field``
            The model field that contains the slug. Default is ``'slug'``
        
        ``existing_request_pk_key``
            The request parameter that represents the primary key. Default is ``'pk'``.
        
        ``existing_request_slug_key``
            The request parameter that represents the slug. Note that if primary key is
            specified (it is by default), and it is passed in request, slug will not be
            looked up.
        
        ``existing_redirect_url`` (``get_existing_redirect_url()``)
            Required attribute. The URL that client will be redirected to if the object
            exists.
        
        ``existing_form_name`` (``get_existing_form_name``)
            Customizes the name of the context object containing the form.
        
        RelatedObjectMixin
        ===============
        
        This mixin is a generic related object pre-fetching mixin. Before resorting to
        using this mixin, let's first discuss an approach that works well without the
        overhead of ``RelatedObjectMixin``, in cases where you are only fetching the
        related object, but doing nothing else. Consider this URL pattern::
        
            /posts/(?P<pk>\d+)/comments
        
        (Yes, there is a whole comment system included in Django, so, sorry for the
        corny example.) In the above case You would normally use a list view for the
        comments. But you might also want to fetch the post object as well. There is no
        need to use ``RelatedObjectMixin`` in this particular case, because you can
        combine Django's built-in ``SingleObjectMixin`` with ``ListView`` to achieve
        what you want.
        
        Another case where you *do not* want to use this mixin is if you can fetch the
        related object using Django's DB API. For example, if you have a ``book``
        object, you can probably get the related author as ``book.author``.
        
        This mixin is useful only if you need two physically unrelated objects (like
        using two ``SingleObjectMixin`` mixins in a view). If there is no actual
        relationship between the two objects via a foreign key, then you should use
        this mixin.
        
        For users of the previous versions of django-related, it has to be noted that
        this mixin is simply ripped out of what used to be a monolithic
        CreateWithRelatedMixin_. It therefore behaves more or less the same as that
        mixin.
        
        Here is an example::
        
            from related import RelatedObjectMixin
            from django.views.detail import SingleObjectMixin
            from django.views import FormView
        
            from cards.models import Card
            from cards.forms import MatchCardsForm
        
            # view for `/match/(?P<first_card_pk>\d+)/(?<second_card_pk>\d+)/`
        
            class ViewAttachment(RelatedObjectMixin, SingleObjectMixin, FormView):
                model = Card
                related_model = Card
                pk_url_kwarg = 'first_card_pk'
                related_pk_url_kwarg = 'second_card_pk'
                form_class = MatchCardsForm
                template_name = 'attachment.html'
                success_url = '/foo'
        
                def get_initial(self):
                    return {
                        'first_card': self.object.pk,
                        'second_card': self.related_object.pk,
                    }
        
                def form_valid(self, form):
                    # Do something with the form, etc
        
        Note that naming of properties is basically cloned from the
        ``SingleObjectMixin``, with a ``related_`` prefix. In most cases, you can guess
        the properties you need to set if you know what they are called in
        ``SingleObjectMixin``.
        
        ``RelatedObjectMixin`` is currently limited to fetching only one object, just
        like ``SingleObjectMixin``, and is therefore not suitable for complex nested
        structures. Again, using Django's DB API would be more reasonable in many of
        those cases.
        
        The view can be customized using the following attributes (and matching
        methods):
        
        ``related_model``
            Related model under which the current model is nested. This attribute is
            required.
        
        ``related_404_redirect_url`` (``get_related_404_url()``)
            If specified, the view will redirect instead of raising
            ``django.http.Http404`` or returning ``django.http.HttpResponseGone``. 
            Default is ``None``.
        
        ``related_404_message`` (``get_rlated_404_message()``)
            If ``related_404_redirect_url`` is used, the ``django.contrib.messages`` is
            used to display an error message. This attribute is used to customize this
            message. Default is ``'%s does not exist'`` where ``'%s'`` will evaluate to
            the ``related_model``'s verbose name.
            
        ``related_pk_field``
            The field on the ``related_model`` that contains the primary key. Defaults
            to ``'pk'``.
        
        ``related_pk_url_kwarg``
            The URL parameter that contains the primary key. Defaults to ``'pk'``.
        
        ``related_slug_field``
            The field on the ``related_model`` that contains the sulug field. Defaults
            to ``'slug'``.
        
        ``related_slug_url_kwarg``
            The URL parameter that contains the slug field. Defaults to ``'slug'``.
        
        ``related_object_name`` (``get_related_object_name()``)
            Customizes name of the context object that contains the related object.
        
        ``cache_backend`` (``get_cache_backend``)
            Specifies the object that implements the caching methods. This object is
            ``django.core.caching.cache`` by default. Any interface that you specify
            must provide the same methods as the default one.
        
        CreateWithRelatedMixin
        ======================
        
        This mixin is used when we are dealing with a ``CreateView`` for a nested
        resource. The main assumption is that higher levels of the path contains a slug
        or pk that points to the related model's object.
        
        As discussed in the RelatedObjectMixin_ section, this mixin is based on it, so
        the same customization options are available.
        
        The key difference between normal CreateView (which can be persuaded to give
        you the related object using the ``queryset`` attribute and ``get_object``
        method) and this mixin, lies in the form processing. This mixin does two things
        differently:
        
        1. It ensures that the related object exists (behavior similar to
           ``get_object`` is forced)
        2. It attaches the related object to the appropriate field in the submitted
           form.
        
        Here is an example::
        
            from related import CreateWithRelatedMixin
            from django.views import CreateView
        
            from models import Attachment, Post
            from forms import CustomAttachmentModelForm
        
        
            # View for `/posts/(?P<slug>[\w-]+)/attachments`
        
            class AttachmentCreateView(CreateWithRelatedMixin, CreateView):
                model = Attachment
                form_class = CustomAttachmentModelForm
                related_model = Post
        
        With the above setup, the ``django.http.Http404`` is raised if GET request is
        made to this view with the slug in the URL that points to a non-existent post.
        If POST request is made to the same URL, ``django.http.HttpResponseGone`` (410)
        is returned if post does not exist. Otherwise, the ``CustomAttachmentModelForm``
        is processed, and the ``Post`` object that was found based on the slug will be
        added to ``post`` field of the object resulting from the form processing.
        
        The view can be customized using the following attributes (and matching
        methods):
        
        ``related_model``
            Related model under which the current model is nested. This attribute is
            required.
        
        ``related_field``
            Field on the current model that must point to the related object. By
            default, lower-cased ``related_model``'s class name (e.g., ``'foo'`` for a
            model called ``Foo``).
        
        ``related_404_redirect_url`` (``get_related_404_url()``)
            If specified, the view will redirect instead of raising
            ``django.http.Http404`` or returning ``django.http.HttpResponseGone``. 
            Default is ``None``.
        
        ``related_404_message`` (``get_rlated_404_message()``)
            If ``related_404_redirect_url`` is used, the ``django.contrib.messages`` is
            used to display an error message. This attribute is used to customize this
            message. Default is ``'%s does not exist'`` where ``'%s'`` will evaluate to
            the ``related_model``'s verbose name.
            
        ``related_pk_field``
            The field on the ``related_model`` that contains the primary key. Defaults
            to ``'pk'``.
        
        ``related_pk_url_kwarg``
            The URL parameter that contains the primary key. Defaults to ``'pk'``.
        
        ``related_slug_field``
            The field on the ``related_model`` that contains the sulug field. Defaults
            to ``'slug'``.
        
        ``related_slug_url_kwarg``
            The URL parameter that contains the slug field. Defaults to ``'slug'``.
        
        ``related_object_name`` (``get_related_object_name()``)
            Customizes name of the context object that contains the related object.
        
        ``integritiy_error_message`` (``get_integrity_error_message()``)
            If there is an integrity error saving the object pointing to the related
            object, the view will rerender the form, but will also add an error message
            to the response object using ``django.contrib.messages``. This attribute
            customizes the message. Default is ``'Such record already exists'``.
        
        ``cache_backend`` (``get_cache_backend``)
            Specifies the object that implements the caching methods. This object is
            ``django.core.caching.cache`` by default. Any interface that you specify
            must provide the same methods as the default one.
        
        Reporting bugs
        ==============
        
        Please report bugs and feature requests to the Bitbucket `issue tracker`_.
        
        .. _issue tracker: https://bitbucket.org/monwara/django-related/issues
        
        
        
Platform: UNKNOWN
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Framework :: Django
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
