Home Features Docs Blog Security Examples Quick Start

Full Django Template Compatibility: URL Tags, Comparison Operators, and Auto-Serialization

djust Team | | 4 min read
Code blocks showing Django template syntax transforming into high-performance rendering

Making Migration Effortless

One of djust's core promises is seamless migration from traditional Django. With v0.1.6, we've taken a major step forward by adding full support for Django's most commonly used template features. Your existing Django templates now work with djust's Rust rendering engine with minimal or no changes.

Let's explore the five key improvements that make this possible.

1. {% url %} Tag Support

Django's URL reversing is essential for maintainable templates. Previously, you had to manually resolve URLs in your views. Now, djust handles this automatically.

Before (workaround required):

# views.py - manual URL resolution
from django.urls import reverse

class MyView(LiveView):
    def mount(self, request):
        self.home_url = reverse('home')
        self.profile_url = reverse('user_profile', kwargs={'username': 'john'})

After (just works):

<!-- template.html - standard Django syntax -->
<a href="{% url 'home' %}">Home</a>
<a href="{% url 'user_profile' username='john' %}">Profile</a>
<a href="{% url 'post_detail' post.slug %}">Read More</a>

djust now supports:

  • Named URLs: {% url 'view_name' %}
  • Positional arguments: {% url 'post_detail' post.slug %}
  • Keyword arguments: {% url 'search' category='tech' query='djust' %}
  • Variable assignment: {% url 'home' as home_link %}

2. {% include %} Tag Fix

Template includes are fundamental to DRY template design. The previous version had issues resolving include paths when templates were in subdirectories. This is now fixed.

Before (broken with directories):

<!-- This failed if _header.html was in a different directory -->
{% include 'components/_header.html' %}

After (works correctly):

<!-- All your includes just work -->
{% include 'components/_header.html' %}
{% include 'partials/_sidebar.html' with user=request.user %}
{% include '_footer.html' only %}

The fix ensures template directories are properly passed to the Rust rendering engine, supporting both absolute and relative include paths.

3. urlencode Filter

Building URLs with dynamic content requires proper encoding. The new urlencode filter matches Django's behavior exactly.

<!-- Encode search queries -->
<a href="/search?q={{ query|urlencode }}">Search</a>

<!-- Build dynamic URLs safely -->
<a href="/tag/{{ tag_name|urlencode }}">{{ tag_name }}</a>

The filter properly encodes:

  • Spaces as %20
  • Special characters like &, =, ?
  • Unicode characters (multi-byte UTF-8)
  • Preserves safe characters: alphanumeric, -, _, ., ~

4. Comparison Operators in {% if %} Conditions

Numeric comparisons are now fully supported. Previously, you could only use equality checks. Now you can write natural conditional logic.

Before (limited to equality):

{% if count == 0 %}Empty{% endif %}

After (full comparison support):

{% if count > 0 %}
    {{ count }} item{{ count|pluralize }}
{% endif %}

{% if price >= 100 %}
    <span class="premium">Premium Product</span>
{% endif %}

{% if stock < 5 %}
    <span class="warning">Low Stock!</span>
{% endif %}

{% if score <= threshold %}
    <span class="alert">Below target</span>
{% endif %}

Supported operators:

  • Greater than: >
  • Less than: <
  • Greater than or equal: >=
  • Less than or equal: <=
  • Equal: == (already supported)
  • Not equal: != (already supported)

These work with integers, floats, and even cross-type comparisons (comparing an integer to a float).

5. Automatic Django Type Serialization

This is perhaps the most developer-friendly improvement. Django models often contain types that aren't natively JSON-serializable: datetime, Decimal, UUID, and file fields. Previously, you had to manually serialize these.

Before (manual serialization):

# views.py - tedious conversion
class OrderView(LiveView):
    def mount(self, request):
        order = Order.objects.get(pk=1)
        self.created_at = order.created_at.isoformat()
        self.total = float(order.total)  # Decimal to float
        self.order_id = str(order.uuid)  # UUID to string
        self.invoice_url = order.invoice.url if order.invoice else None

After (automatic):

# views.py - just pass the data
class OrderView(LiveView):
    def mount(self, request):
        self.order = Order.objects.get(pk=1)
<!-- template.html - use directly -->
<p>Order ID: {{ order.uuid }}</p>
<p>Created: {{ order.created_at|date:"F j, Y" }}</p>
<p>Total: ${{ order.total }}</p>
<a href="{{ order.invoice }}">Download Invoice</a>

djust now automatically serializes:

  • datetime/date/time: ISO format strings
  • Decimal: Float values
  • UUID: String representation
  • FieldFile/ImageField: URL string (or None if empty)
  • Nested dicts and lists: Recursively processed

Migration Made Simple

These improvements mean your existing Django templates are more likely to "just work" with djust. The goal is zero friction migration: install djust, point it at your templates, and enjoy 10-100x faster rendering.

Try it today:

pip install djust==0.1.6

Check out our documentation for the complete list of supported template tags and filters, and join our GitHub community to report any compatibility issues.

Share this post

Related Posts