Metadata-Version: 1.1
Name: singleurlcrud
Version: 0.21
Summary: Django CRUD using a single view and hence a single URL.
Home-page: https://www.github.com/harikvpy/crud/
Author: Hari Mahadevan
Author-email: hari@hari.xyz
License: BSD-3
Description-Content-Type: UNKNOWN
Description: Django CRUD through a single view
        =================================
        
        A single view implementation of table CRUD operations for Django. Single view 
        means single URL to be registered in URL namespace. All CRUD operations are
        invoked with the same URL but with URL arguments to distinguish them. This allows
        less crowded and a simpler URL namespace.
        
        ## PROJECT NO LONGER MAINTANED ##
        I don't maintain or use this project anymore. I have since moved to a new CRUD that leverages Django's class based views. This is more modular and reuses all the good bits from core Django code. You can find it [here](https://github.com/harikvpy/django-popupcrud.git).
        
        # Introduction
        
        Django comes with an excellent admin framework that provides a sophisticated 
        interface for table CRUD operations. However, the admin framework is closely 
        tied to Django's default user management and its permission management systems.
        If your project bypasses either of these, employing the CRUD in the admin 
        framework can get a little tricky. 
        
        Secondly, django admin also implicitly adds a number urls to your url 
        namespace. These urls list the apps whose models are are registered with it
        and for each app, the models in the app that have an admin CRUD interface. While
        these can be forcefully removed by overriding the ModelAdmin class and using
        it to create your own admin based CRUD classes, managing and getting around
        its various dependencies can quickly get tedious to manage. And when Django gets
        upgraded, you have the job of reviewing the new admin interface to make sure
        that it did not introduce any new 'holes' into your url namespace.
        
        This project is aimed at addressing the above shortcomings by developing a pure 
        django view that provides basic table CRUD operations. To use, derive from this 
        view class providing it with the appropriate initialization parameters and then 
        hook it up to the url namespace yourself explicitly.
        
        # Installation
        
        1. Easiest way to install crud is to get it from PyPi using pip. Do this by:: 
        
            `pip install singleurlcrud`
        
        2. Add it to INSTALLED_APPS in projects ``settings.py``::
        ```
        INSTALLED_APPS = (
            ...
            'singleurlcrud',
            ...
            )
        ```
        # Dependencies
        
          * django-bootstrap3
          * django-pure-pagination
        
        # Quickstart
        
        Consider the following model (taken from `polls` app, which is bundled with the 
        source code):
        ```
        from django.db import models
        
        class Question(models.Model):
            question_text = models.CharField(max_length=200)
            pub_date = models.DateTimeField('Date published')
            author = models.ForeignKey(Author, null=True, default=None)
        ```
        
        To get a fully functional CRUD for this table, declare a view like below:
        ```
        from singleurlcrud.views import CRUDView
        from .models import Question
        
        QuestionCRUDView(CRUDView):
            model = Question
            list_display = ('question_text', 'pub_date', 'author')
        ```
        
        Thereafter, hook this view to the desired url through urls.py:
        ```
        from django.conf.urls import url
        from .views import *
        
        urlpatterns = [
                url(r'^questions/$', QuestionCRUDView.as_view(), name='questions')
                ]
        ```
        
        That's it! You get a fully functional CRUD that will allow you to create,
        update and delete records from Question table, all rooted at 
        `yoursite.com/questions/`.
        
        # Usage examples
        This section documents the various common use case scenarios and how to 
        implement them using the CRUDView.
        
        ## Custom multi-row actions
        To enable action on a group of selected rows, override `get_actions()` method
        and return from it a list of 2-tuples where each tuple is of the form `(label,
        handler,)`. Label is the label that will be displayed on the Actions drop down
        menu and handler is the derived class method that will be invoked when user
        selects the corresponding action item.
        
        Handler method should be of the format
        ```
        def action_handler(self, request, qs):
            '''
                Parameters:
                    request - the HttpRequest object
                    qs - queryset containing the selected rows upon which the action
                         is to be performed.
        
                Return:
                    None - for view to refresh itself
                    HttpResponse - to explicitly return a response object
            '''
            # do some action
        
        ```
        Note that actions dropdown menu button (placed next to `Create New..` button) 
        will only be shown when there is at least one multi-row action item defined.
        
        To illustrate with an example:
        ```
        class MyTableCRUDView(CRUDView):
            ...
            ...
            def get_actions(self):
                return [
                        (_('Mark as done'), mark_as_done, ),
                        ]
            
            def mark_as_done(self, request, qs):
                for obj in qs:
                    obj.mark_as_done()
                return None # can be omitted for implicit return None
        ```
        
        ## Custom per-row actions
        Per row custom actions are supported through the callback `get_item_actions()`.
        The return value from this method is a list of objects, one for each action,
        of the prototype ItemAction. When user selects the action, the corresponding
        ItemAction object's doAction() method is invoked. This method is given the
        selected row as an argument.
        
        ItemAction object has three class variables that need to initialized:
        
        Variable | Purpose 
        -------- | ------- 
        `title` | The `alt' text displayed for the action icon
        `key` | A unique string (amongst other actions) to identify this action
        `css` | CSS class for the icon <i> element for this action
        
        The following code example should make the options above clearer:
        ```
        class MyTableCRUD(CRUDView):
        
            class VoteAction(CRUDView.ItemAction):
                '''Per item custom action definition'''
               title = _('Mark as done')
               key = 'mark_as_done'
               css = 'glyphicon glyphicon-ok'
        
                def doAction(self, obj):
                    obj.mark_as_done()
        
        ```
        ## Editing child models using formset
        Singleurlcrud supports editing child table rows using the Django FormSet
        mechanism. To facilitate this, override `get_formset_class()` method in your
        CRUDView derived class and return the `inline_formset` for the child model from
        this method. 
        
        For our example project, `polls`, Author table's CRUD view is a good candidate
        to introduce inline formset editing as one author can create many questions
        and therefore the models are related by a foreign key. In order to achieve this 
        we just have to override `get_formset_class()` as below:
        
        ```
        class AuthorCRUDView(CRUDView):
            '''Author table CRUD'''
            model = Author
            list_display = ('name', 'email')
        
            def get_formset_class(self):
                return inlineformset_factory(
                        Author,     # parent model
                        Question,   # child model
                        fields=['question_text', 'pub_date'], # fields for inline edit
                        can_delete=True,    # can rows be deleted?
                        extra=1)    # number of extra forms for adding new child entries
        ```
        Note that here we're not using any custom forms and are leaving all the work to
        the excelleng inlineformset_factory(). It builds a formset with individual
        forms for each child model instance and an extra form for entering new child
        model instance.
        
        # Reference
        
        ## Options
        CRUDView provides many options which allows customizing its behavior. These are
        documented below:
        
        ### `template_name`
        Specifies the template that is used to render the list of items. This defaults to
        `singleurlcrud/list.html` and is rarely necessary to be customized.
        
        ### `form_class`
        The form class to be use for create and update operations. This is optional and
        if not spefified, CRUD will create a form using `modelform_factory` using the
        fields specified in `form_fields` option. If `form_fields` is not spefified,
        CRUDView will try to use the fields in `list_display`.
        
        ### `allow_create`
        A boolean value, this controls whether the create operation is allowed. 
        By default it is allowed, that is, this is set to True. 
        
        ### `allow_edit`
        A boolean value, this controls whether the update operation is allowed. 
        By default it is allowed, that is, this is set to True. 
        
        ### `allow_delete`
        A boolean value, this controls whether the delete operation is allowed. 
        By default it is allowed, that is, this is set to True. 
        
        ### `context_object_name`
        The context variable name that will be set to the object list for the list view.
        Defaults to `object_list`. You only need to customize this if you have a custom
        template that want to use a different template variable name (for some reason).
        
        ### `pagetitle`
        Title of the list view page.
        
        ### `table_css_classes`
        CSS classes applied to the table in list view. Defaults to 
        `table table-striped table-condensed table-bordered`.
        
        ### `list_display_labels`
        A dictionary that contains the labels to be used for each column in the list 
        view. If not specified, column names will default to the field name specified
        in `list_display`. For callable column entries, attribute value
        `<callable>.short_description` is used as the column title.
        
        ### `allow_multiple_item_delete`
        A boolean value, this controls whether multiple item deletion is allowed. 
        Multiple item deletion is implemented using a checkbox against each item row
        and then selecting a dropdopwn menu item at the top. Set to `False` by default.
        
        ### `related_field_crud_urls`
        A dictionary that has the CRUD url for each foreign key field of the model for
        which create and update operation through a popup window is to be enabled.
        
        Note that the view urls for the foreign key field models should also be 
        implemented using CRUDView for this to work.
        
        ## Overridable methods
        Like options, CRUDView also provides many methods that can be overridden by the
        client class to customize the CRUD behavior. Many of these methods are simple
        wrappers around class variables, provided to allow dynamic values to be 
        returned for the relevant options.
        
        ### `get_form_class()`
        Returns the form class that will be instantiated for create and update 
        operations. By default returns the value of `form_class` option, if it's 
        defined. If `form_class` is not defined, a `ModelForm` class for the model with
        fields set to either of the value of `form_fields` or `list_display` will be
        returned.
        
        ### `get_form(form_class, **kwargs)`
        Returns the form object to be used for create and update operations. 
        `form_class` will be set to the return value of `get_form_class`. `**kwargs` 
        will contain additional arguments, such as form initial data for the update
        operation of CRUD, that are to be passed to the form constructor.
        
        ### `get_form_fields()`
        Return a tuple, that lists the fields of form used in create and update 
        operations. Note that this method will only be called if a `form_class` is not
        specified and `get_form()` is not overridden.
        
        ### `get_formset_class()`
        CRUDView supports editing of child models using a formset. To activate this 
        feature, override this method and return the formset class to be used for inline
        editing of the child model instances. 
        
        Typically one can use one of the django factory methods `inlineformset_factory`
        or `modelformset_factory()` to create this class.
        
        By default this method returns `None` which disables child model editing.
        
        ### `get_formset(formset_class, **kwargs)`
        Return the formset class instance to be used for editing child model instances.
        
        ### `get_related_field_crud_urls()`
        Wrapper around the class option `related_field_crud_urls`. By default returns
        the value assigned to option variable `related_field_curd_urls`.
        
        ### `get_add_item_custom_url()`
        Return a custom url, presumably with its own view that you write, that you want 
        to use for the create operation. By default returns `None`.
        
        ### `get_edit_item_custom_url()`
        Return a custom url, presumably with its own view that you write, that you want 
        to use for the update operation. By default returns `None`.
        
        ### `get_delete_item_custom_url()`
        Return a custom url, presumably with its own view that you write, that you want 
        to use for the delete operation. By default returns `None`.
        
        ### `get_item_template(self)`
        Returns the template used to render each item in list view. Template returned 
        by this method is used to render each row of the model in list view. You can 
        override this to customize per item rendering.
        
        For example, by default each row of the table is given on table row. But for 
        your model, you might want to render additional rows listing the child model
        instances associated with the model row. You can acheive this by overriding this
        method to return a custom template.
        
        ### `get_pagetitle()`
        Wrapper for `pagetitle` class options variable.
        
        ### `get_allow_create()`
        Wrapper for `allow_create` class option. Method allows for determining this
        value during runtime rather than static definition in the code.
        
        ### `get_allow_edit()`
        Wrapper for `allow_edit` class option.  Method allows for determining this
        value during runtime rather than static definition in the code.
        
        ### `get_allow_delete()`
        Wrapper for `allow_delete` class option. Method allows for determining this
        value during runtime rather than static definition in the code.
        
        ### `get_allow_multiple_item_delete()`
        Wrapper for `allow_multiple_item_delete` class option. Method allows for determining this
        value during runtime rather than static definition in the code.
        
        ### `get_disallowed_create_message()`
        Often times you might want to control the number of rows that a user can
        create on a table. Or you might want to limit row creation based on user roles.
        When such logic is determined dyanamically and the creation operation is 
        disallowed, you can display an alert message when the table CRUD is activated.
        
        This method allows you to specify the custom message that will be displayed on
        top of the list view (where the Create New.. button would've been) 
        informing the user that row creation is disallowed.
        
        ### `get_breadcrumbs()`
        If your site supports breadcrumbs, override this method to return a list of
        breadcrumbs that depicts the navigation path to the CRUD url. Each item of
        this list is a 2-tuple of the form `(text, url)` where `text` is to be added to
        the breadcrumbs hyperlinking it to `url`.
        
        Breadcrumbs returned from this method are passed to the context through the 
        context variable `breadcrumbs`. Ideally, your project's base template should 
        handle this list by rendering each item in the list as an appropriately
        styled `<li>` or something similar.
        
        ### `get_actions()`
        Return a list of tuples where each tuple consists of `(label, handler,)` where
        `label` will be displayed in the action dropdown and `handler` is a method
        in the derived class that is to be invoked when the user selects the action.
        
        ### `get_item_actions()`
        Return a list of ItemAction derived objects that represent the additional item 
        specific action to be invoked for each item in the itemlist. When the action is
        selected, the corresponding ItemAction object's `doAction()` method will be 
        invoked. ItemAction has the following prototype:
        
        ```
        class ItemAction(object):
            title = ''
            key = ''
            css = ''
        
            def doAction(self, item):
                pass
        ```
        
        ### `item_deletable(object)`
        Return a boolean to indicate if the object can be deleted. By default, True is 
        returned by the base class.  If False is returned for any object, the delete 
        option for that item will be disabled.
        
        This method, alongwith `item_editable` below, allows controlling per item delete
        and edit operations based on the row or some other dynamic property.
        
        ### `item_editable(object)`
        Same as `item_deletable` above, but works for updating an item.
        
        ## Helper methods
        ### `return_as_href(label, urlname, kwargs)`
        This helper method return a well formed anchor element composed of its three
        arguments of the form:
        ```
            <a href="reverse(urlname, kwargs=kwargs)">label<a>
        ```
        This helper can be used to conveniently return an anchor element from a method
        that is listed as one of the columns in list view.
        
        
        License
        -------
        
        Modified BSD
        
        Author
        ------
        
        `Hari Mahadevan <http://hari.xyz/>`_
        
        
        History
        -------
        
        0.21 - 2017/10/16
        ++++++++++++++++
        - Update for project status. Add link to ``django-popupcrud``.
        
        0.20 - 2016/1/30
        ++++++++++++++++
        - Add support for specifying list column titles through a dictionary specified
          as the class variable - list_display_lables
        
        0.19 - 2016/1/24
        ++++++++++++++++
        - Fix mispelt context variable item_actions (was referred to as itemactions)
        
        0.18 - 2016/1/22
        ++++++++++++++++
        - Fix formatting errors in README.rst.
        
        0.17
        ++++
        - Move changelog to HISTORY.rst and include it in setup long_description
          through embedded script.
        
        0.16
        ++++
        - Fix more errors in setup.py that stopped pip install from working
        
        0.15
        ++++
        - Fix errors in setup.py that stopped pip install from working
        
        0.14
        ++++
        - Fix errors in setup.py.
        - Update status to '4 - Beta'.
              
        0.13
        ++++
        - Use django-pure-pagination for pagination. This provides margin page
          numbers which provides a nice UX for listing tables with very large
          amounts of data, number of pages for which exceed the available 
          width in the screen.
        
        0.12
        ++++
        - Move delete operation into an independent GET action through the 
          '?o=delete' parameter.
        
        0.11
        ++++
        - Action buttons changed to use buttons grouping them into a btn-group.
        - Added colors to the buttons indicating the severity of the action's outcome.
        
        0.10
        ++++
        - Changed table css classes to be specified as view setting provided
          through RequestContext.
              
        0.9
        +++
        - Refactor cryptic flag names to more friendly names. Eg.: can_delete() has
          been changed to item_deletable(). 
        - Global flags can_create, can_edit and can_delete has been replaced by 
          enable_create, enable_edit & enable_delete respectively.
        
        0.8
        +++
        - Add support for view to customize page titles by specifying a class
          variable 'pagetitle'. This title will be used by default and if not
          specified the model's verbose_name_plural will be set as the title
          in the context.
        
        0.7
        +++
        - Fix media property such that it only returns media fragments necessary
          for the current CRUD operation.
        
        0.6
        +++
        - Fix incorrect arguments to can_delete() method call.
        
        0.5
        +++
        - When the derived class specifies a custom form by overriding the
          get_form() method, inline editing/addition of RelatedField objects
          is not available. This version includes a fix for this.
        
        0.4
        +++
        - Support for per item editing control through the item property
          item.can_edit, which should return a boolean indicating if editing
          is allowed. Defaults to True, if the property is missing.
        
        0.3
        +++
        - Support for per item deletion control through the item property
          item.can_delete, which should return a boolean indicating if deletion
          is allowed. Defaults to True, if the property is missing.
        
        0.2
        +++
        - Support for inline editing/addition of RelatedField objects through
          a popup window. Note that base template has to be designed
          to accommodate this feature by removing the embellishments that adorn a 
          regular page.
        
        0.1
        +++
        - Initial release
        
        
Keywords: django,crud,singleurlcrud
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Web Environment
Classifier: Framework :: Django
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 2.7
