Buttons - Django | Lookaway CMS

Documented by kbruder tech✞ᵀᵀᴹ on Apr 29, 2021
Last updated on Jul 24, 2021


Screenshot_from_2021-04-10_18-33-25

Introduction

In order to ensure a secure and seamless experience, the logic of when and how interactive buttons appear in a graphical user interface should play out before the HTML is rendering begins. Django templates allow for conditional logic and it is tempting or necessary to use it early in the development of a project. Yet consider the long view where you may have separate developers or teams working on views and templates respectively.

You've heard of "skinny views, fat models". Deciding whether or not to show a button on a page, for example can be passed as a context variable from a class based view with the get_context_data() method. Even though we are fattening the views with many lines of code, we are making a new rule, "skinny templates, fat views". This way, python developers can provide the logic so front end developers can focus on the layout.


  1. Custom Dictionary Lookup Filter for Django

    This is one of those things that is right on the edge of what Django provides. Some have said that Django's template system is lacking and substandard. However, when it comes to needing to create a custom template filter, it can be done with very few lines of code.

    lookaway/context_processors.py
    from django.template.defaulttags import register
    ...
    @register.filter
    def lookup(dictionary, key):
        return dictionary.get(key)
    ...
    

    Source: culebrón

  2. The Base Button Template

    This is one of many base templates (one for each style). Keep them in the project's base template directory so all app can use them.

    The button only needs to know three things:

    1. The URL
    2. Parameters (optional)
    3. The button text

    Styling of the buttons can be changed in CSS and is implemented by changing the button class in the base template or by adding new templates and changing the corresponding include tags.

    Tip: Less is better.

    templates/edit_button.html
    <a href="{{ button_url }}{{ button_parameters }}"><button type="button" class="btn btn-sm btn-warning">{{ button_text }}</button></a>
    

    Source: kbruder Tech

  3. The Template

    This looks like a lot compared to a single lined nestted anchor and button, but it will save needless rendering and lower the chance of a button showing up on the wrong page.

    foo/templates/foo/bar_detail.html
    {% if show_profile_edit_button %} 
      {% with profile_edit_button as button %}
        {% with button|lookup:"url" as button_url and button|lookup:"parameters" as parameters and button|lookup:"text" as button_text %}
          {% include 'edit_button.html' %}
        {% endwith %}
      {% endwith %}
    {% endif %}
    

    Source: kbruder Tech

  4. The View

    Here we have a detail view that shows a profile. We only want the show the 'Edit Profile' button to users that have permission to make changes to the profile. For the purposes of demonstration, URL parameters are included in the button's URL.

    foo/views.py
    class BarProfileView(DetailView):
        ...
        def get_context_data(self, **kwargs):
            # Update Profile button
            if self.request.user.has_perm('foo.change_profile'):
                context = super().get_context_data(**kwargs)
                context['show_profile_edit_button'] = True
                context['profile_edit_button'] = {
                    'url': reverse('posts:posts_app_profile_update',
                        kwargs={'pk': 1},
                    ),
                'parameters': "?foo=bar&baz=quz",
                'text': "Edit App"
                }
            ...
            return context
    ...
    

    Source: kbruder Tech

Conclusion

Hopefully this helps avoid embarrassing or costly bugs on your site. If a legitimate user of a site needs a button, it needs to be there. If a sensitive page or form needs to stay private, only authorized users of the the site should know it exists. These are things that can and do lead to incidents that happen all the time. By sticking to a design pattern (doesn't need to be this one), and avoiding using button logic in the templates, you can lower the risk of catastrophe.


bitcoin:3MnhNRKgrpTFQWstYicjF6GebY7u7dap4u
Bitcoin Accepted Here

3MnhNRKgrpTFQWstYicjF6GebY7u7dap4u

Please donate some Bitcoin to our site. We can use it to keep improving the site and open up to more members. Any amount will help. Thank you.


litecoin:MT61gm6pdp9rJoLyMWW5A1hnUpxAERnxqg
Litecoin Accepted Here

MT61gm6pdp9rJoLyMWW5A1hnUpxAERnxqg

Please donate some Lite to our site. We can use it to keep improving the site and open it up to more members. Any amount will help. Thank you.