I’ve been testing out some custom Python classes for Django templating, due to 
Python 3.6’s addition of F-strings. In addition, templates now have the full 
capability to be programmed in Python itself, with the possibility of creating 
smart templates and components based on Python classes.

Instead of the template language (copying and pasting just a typical Django 
template here):

{% extends "base.html" %}

{% block content %}


      <!--Section: Products v.3-->
      <section class="text-center mb-4">

        <!--Grid row-->
        <div class="row wow fadeIn">
{% for item in items %}

          <!--Grid column-->
          <div class="col-lg-3 col-md-6 mb-4">

            <!--Card-->
            <div class="card">

              <!--Card image-->
              <div class="view overlay">
                <img 
src="https://mdbootstrap.com/img/Photos/Horizontal/E-commerce/Vertical/12.jpg"; 
class="card-img-top"
                  alt="">
                <a>
                  <div class="mask rgba-white-slight"></div>
                </a>
              </div>
              <!--Card image-->

              <!--Card content-->
              <div class="card-body text-center">
                <!--Category & Title-->
                <a href="" class="grey-text">
                  <h5>Shirt</h5>
                </a>
                <h5>
                  <strong>
                    <a href="" class="dark-grey-text">{{item}}
                      <span class="badge badge-pill danger-color">NEW</span>
                    </a>
                  </strong>
                </h5>

                <h4 class="font-weight-bold blue-text">
                  <strong>120$</strong>
                </h4>

              </div>
              <!--Card content-->

            </div>
            <!--Card-->

          </div>
          <!--Grid column-->
{% endfor %}

        </div>
        <!--Grid row-->

      </section>
      <!--Section: Products v.3-->

{% endblock content %}

I have something like (example from a different project):


base_css = """
body {
    margin: 2% auto 5% auto;
    background: #fdfdf2;
    color: #111;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, 
Helvetica, Arial, sans-serif;
    font-size: 16px;
    line-height: 1.8;
    text-shadow: 0 1px 0 #ffffff;
    max-width: 73%;
    }
h1, h2, h3, h4 {
    line-height:1.2
    }
h2, h3 {
    color: #777
    }
code {
    background: white;
    }
a {
    border-bottom: 1px solid #444444;
    color: #444444;
    text-decoration: none;
    }
a:hover {
    border-bottom: 0;
    }
.fixed {
    white-space: nowrap;
    vertical-align:top;
    }
"""

class viewIndexHead(Block):

    css = base_css

    vary = []

    def generateHTML(self,page):
        return f'<title>Bobby Mozumder Homepage</title></head><body><h4><a 
href="/">mozumder.net</a></h4>'

class viewArticleHead(Block):

    css = base_css

    vary = ['id']

    def generateHTML(self,page):
        return f'<title>{page.data.title}</title></head><body><h4><a 
href="/">mozumder.net</a></h4>'


class article_body(Block):
    vary = ['id']

    def generateHTML(self,page):
        html = 
f'<h1>{page.data.headline}</h1><h2>{page.data.subheadline}</h2><h3>{page.data.date_published:%B
 %d, %Y}</h3>{page.data.body}'
        return html

class article_list(Block):
    sql = 'get_view_headlines_fragment'
    components = [
        table()
    ]
    def generateHTML(self,page):
        page.articles_list = self.fetchall(page.request.session.session_key)
        return super().generateHTML(page)
    def fetchall(self,session):
        self.c.execute('EXECUTE ' + self.sql + '(%s);', [session])
        result = self.c.fetchall()
        return result

With blocks generated from components:
class tableHTML(code):
    def __iter__(self,page=None):
        yield "<table>"
        if page:
            if page.request.user.is_authenticated:
                for row in page.articles_list:
                    yield f'<tr><td class="fixed">{row.date_published:%B %d, 
%Y}</td><td><a href="/{row.slug}">{row.title}</a></td><td><a 
href="edit">edit</a><td><a href="delete">delete</a></td></tr>'
            else:
                for row in page.articles_list:
                    yield f'<tr><td>{row.date_published:%B %d, %Y}</td><td><a 
href="/{row.slug}">{row.title}</a></td></tr>'
        yield "</table>"

class tableCSS(code):
    def __iter__(self,page=None):
        yield "table {border:0};"

class table(Component):
    def __init__(self):
        super().__init__()
        self.html = tableHTML()
        self.css = tableCSS()


With pages created by combining these block classes:


class viewArticle(UnchainedTemplate):

    blocks = [viewArticleHead, article_body]

class index(UnchainedTemplate):

    blocks = [viewIndexHead, article_list]


There are lots of properties of each class that I don’t show. Each Block class 
has properties for SQL, CSS, Header JS, Body initial JS, Body after JS. The 
UnchainedTemplate page classes do things like generate the HTML by combining 
each blocks from classes as well as reading in common HTML header/closer 
fragments from files.

It also calculates things like Content Security Policy headers for each piece 
of JS/CSS, and GZip compress each block BEFORE it goes to Redis cache - 
increasing my Redis cache size by 10x and speeding up page reads by not having 
to recompress it for every lookup. I also minimize CSS/JS from the class 
properties.

In the very long term, it’s entirely possible to create smart component-based 
UI classes that not only generate HTML/CSS/JS, but also things like iOS Swift 
UI classes, if you wanted to make a native iOS app from this, or a desktop UI 
app. Ideally there would be a library of pre-built smart components that a 
developer could use to rapidly make an app. I was inspired by Qt, which I loved 
and programmed in 10+ years ago. Qt has an interesting sockets/slots mechanism 
for event modeling.

Anyways is this something that’s interesting for a long-term Django goal?

This is an idea I’ve been lightly exploring a little bit for a couple of years, 
and is probably several years away from being usable by anyone else.

-bobby

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/9256593B-4480-408C-8876-FBB1F7A72A2E%40gmail.com.

Reply via email to