Pratyush Mittal
Hobby coder and a stock investor.
Co-founder Screener.in

Recent posts

Design as (un)ethical illusion

Beautiful article about interfaces. One of the lines that stuck was:

All maps are lies. Useful lies, but lies all the same. They don’t tell you everything about the territory. If they did, they’d be totally useless and impossible to read. Maps show you a highly simplified model of the territory—an incomplete version of the truth based on your goals, context, zoom level, location, etc. They’re helpful because they leave stuff out.

That is so much true about applications. Good applications are like maps. "They're helpful because the leave stuff out." They make things simple.

Uberspace - Shared web hosting

I love Uberspace for hosting websites on a shared server.

While I use VPS (AWS, Linode or DigitalOcean) for larger projects, I still love shared hosting because they are batteries included. They are pre-configured with firewalls, databases, nginx, apache, memcache and SSL.

Shared servers also have much more (shared) CPU resources than a fixed CPU capacity in a VPS. My earlier websites on Webfaction.com (1GB ram - shared cpu - $5/month) performed much better than on DigitalOcean (2GB ram - 2CPU - $10/month). Primary reason was that though the CPU on Webfaction was shared with neighbours, it was of much much larger capacity.

Thus it all boils down to how a shared hosting provider allocates the neighbours. UberSpace rocks at this.

I didn't find the resource allocation part on UberSpace website. Here are the details of that: https://uberspace.de/en/

Disk space: 10 GB (can be expanded)
RAM: 1.5 GB
CPU: Shared as available. But restricted to 6 (https://manual.uberspace.de/changelog/#v7-10-0-short)

On pricing: they provide a pay what you want model :)

I love to write functions instead of classes. However, Django does not allow us to call functions inside templates.

Sometimes we want to postpone the function calls in templates because they might be expensive. Thus we might want to call them inside the template’s cache fragment or inside an if statement.

My way around them is to use a lazy_cache function to postpone and cache a function's result.

Thus the whole usage is something like this:

import datetime as dt
from utilities.functional import lazy_cached

def expensive_computation(result_date, page_number=1):
    # do some expensive stuff
    return results

def latest_results(request):
    result_date = dt.datetime.today()
    page_number = request.GET.get('page')
    results = lazy_cached(
        expensive_computation,
        result_date,
        page_number=request.GET,
    )

    return render(
        request,
        "latest-results.html",
        {
            "results": results,
            "page_number": page_number,
        },
    )

In templates we can now do:

{% load cache %}

{% block content %}
{% cache 30000 results_page page_number %}
{% for result in results %}
    <div>{ { result.name }}</div>
{% endfor %}
{% endcache %}

My recipe for lazy_cached function is:

def lazy_cached(func, *args, **kwargs):
    state = {"value": None, "realized?": False}

    def wrap():
        if state["realized?"]:
            return state["value"]
        state["value"] = func(*args, **kwargs)
        state["realized?"] = True
        return state["value"]

    return wrap
« first previous
Page 2 of 58.
next last »