Skip to main content

2017 OOAO DRY BUZZWORDS FOR DJANGO 2.0 with Material design

Project description

CRUDLFA+ stands for Create Read Update Delete List Form Autocomplete and more.

This package provides a more DRY way to rapidely develop modern web applications by thinking differently:

  • Composition over inheritance with an intermediary layer to use in urls.py,

  • JavaScript is a first class citizen,

  • Integration with external Django apps more than welcome,

Consider this as a brand new framework with a lot of modern features, except you don’t have to learn a new framework because this is still Django, with a 2017 feels.

Try

This should start the example project in src/crudlfap_example where each documented example lives:

pip install --user crudlfap[django,tables2,filter,dal,reversion,debug]; crudlfap dev

Install

To add crudlfap to your project, first copy over settings from crudlfap_example.settings.TEMPLATES or enable jinja2 manually. Also set LOGIN_REDIRECT_URL = '/' for now.

Then add crudlfap to your settings.INSTALLED_APPS. You can find other crudlfap apps you can add with the following commmand:

echo 'from django.conf import settings; settings.INSTALLED_APPS' | crudlfap shell | grep crud

You will also need a context processor that sets the base template context, ie. crudlfap.context_processors.base, but then again, just copy over the TEMPLATES .

Examples

Let’s hack a modern CRUD for your Server model where you can override default templates, add this to your app’s urls.py:

from crudlfap import crudlfap
from .models import Server

# Use fields='__all__' to allow read/write on all model fields for
# everybody for now, also show Server Router views in main menu
urlpatterns = crudlfap.Router(Server, fields='__all__', menus=['main']).urlpatterns()

Then, add it to your project’s urls.py:

urlpatterns = [
    url(r'^yourapp/', include('yourapp.urls')),  # what you created above
    url(r'^crudlfap/', include('crudlfap.urls')),  # for debug views
    # for auth views, we haz material templates
    url(r'^auth/', include('django.contrib.auth.urls')),
    url(r'^$', generic.TemplateView.as_view(template_name='crudlfap/home.html')),  # for free

    # Also, remove django.contrib.admin from ehere and INSTALLED_APPS, not
    # that it's not compatible, but CRUDLFA+ provides better features so do
    # yourself a favor in 2017 and use CRUDLFA+'s modern router instead
]

Now, open your browser and learn to love CRUDFA+ and look at your material design website. Don’t forget to check the registered url list which was generated for you.

Let’s setup the default queryset per user for views and forms etc and set some permissions on views and fields, all OOAO:

class ServerCreateView(crudlfap.CreateView):
    @classmethod
    def allow(cls, user):
        return True if user.is_authenticated() else False


class ServerOwnerRequired(crudlfap.FormViewMixin):
    @classmethod
    def allow(cls, user, model):
        return user.is_staff or model.owner == user


class ServerUpdateView(ServerOwnerRequired, crudlfap.UpdateView):
    pass


class ServerDeleteView(ServerOwnerRequired, crudlfap.UpdateViewView):
    pass


class ServerRouter(Router):
    menus = ['main']  # Yes Django can make menus
    fa_icon = 'server'  # Yes with icons

    views = [
        ServerCreateView,
        crudlfap.DetailView,
        crudlfap.ListView,
        ServerUpdateView,
        ServerDeleteView,
    ]

    readable_fields = ['name', 'owner', 'created']  # yes per attr authorization

    def get_writable_fields(self, user):  # yes per user attr authorization
        if request.user.is_staff:
            return ['name', 'owner']
        else:
            return ['name']

    # yes django allows OOAO for viewland, and you can invent words too
    def get_queryset(self, user):
        if not user.pk:
            return Server.objects.filter(is_public=True)

        if not request.user.is_staff:
            return self.model.objects.filter(
                Q(is_public=True)|Q(owner=request.user)
            )

        return self.model.objects.all()
urlpatterns = ServerRouter(Server).urlpatterns()

Example checking security in template (Jinja2):

{% if crulfap_router(object).get_view_by_slug('update').allow(request.user, object) %}

Example checking security in Python:

if crudlfap.routers['yourapp.server']['update'].allow(user, server):
    # User has permission to update on the default router for yourapp.Server

Now if you want to make your own link to an object update modal because you are in 2017 then you could use this Jinja2 function:

{% cruldfap_modal object 'update' %}

Note that the above won’t render anything if the user doesn’t have the permission to execute the update view.

Now if you want to render a particular model field attribute after checking user permission:

{% if 'created' in crudlfap_router(object).get_writable_fields(request.user) %}
    {% crudlfap_attribute_label object 'created' %}: {% crudlfap_attribute_value object 'created' %}
{% endif %}

Or just:

{% crudlfap_attribute object 'created' %}

Check the default templates for moar 2017 DRY fun !

Now, if you think this pattern is too 2017 for you, wait until we add some custom actions on this model:

from django import forms
from django.contrib import messages

class ServerRefreshView(crudlfap.FormView):
    menus = ['object_actions']  # show in detail and list view
    fa_icon = 'refresh'  # icon for this view / menu links
    style = 'warning'  # view style variable

    def allow(self, user, model=None):
        return model.is_public or model.owner == user

    def form_valid(self, form):
        try:
            self.object.refresh_from_your_cloud()
        except YourCloudException as e:
            if self.request.user.is_staff:
                messages.error(unicode(e))
            else:
                messages.error(_('Server {} refresh fail').format(self.object))
            logger.exception('Failed to refresh server')
        else:
            messages.success(_('Server {} refreshed').format(self.object))
        return self.object.get_absolute_url()


class ServerRouter(crudlfap.Router):
    views = [
        ServerCreateView,
        crudlfap.DetailView,
        crudlfap.ListView,
        ServerUpdateView,
        ServerDeleteView,
        ServerRefreshView,
    ]
urlpatterns = ServerRouter(Server).urlpatterns()

Refresh your browser and you will see a new “refresh” button with the ‘fa-refresh’ icon in the list view and the detail view

Ok so you want to integrate django-reversion and django-tables2 then please dear knock yourself out:

class ServerRouter(crudlfap.Router):
    views = [
        ServerCreateView,
        # yes you can haz type() on the fly
        dict(_cls='crudlfap.DetailView', fields=['name']),
        'crudlfap.Tables2ListView',
        'crudlfap.ReversionView',
        ServerUpdateView,
        ServerDeleteView,
        ServerRefreshView,
    ]
urlpatterns = ServerRouter(Server).urlpatterns()

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

crudlfap-0.0.8.tar.gz (17.8 kB view hashes)

Uploaded Source

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page