Rendering components
Our calendar component can accept and pre-process data, defines its own CSS and JS, and can be used in templates.
...But how do we actually render the components into HTML?
There's 3 ways to render a component:
- Render the template that contains the
{% component %}tag - Render the component directly with
Component.render() - Render the component directly with
Component.render_to_response()
As a reminder, this is what the calendar component looks like:
from django_components import Component, register
@register("calendar")
class Calendar(Component):
template_file = "calendar.html"
js_file = "calendar.js"
css_file = "calendar.css"
def get_template_data(self, args, kwargs, slots, context):
return {
"date": "1970-01-01",
}
1. Render the templateยค
If you have embedded the component in a Django template using the {% component %} tag:
{% load component_tags %}
<div>
{% component "calendar" date="2024-12-13" / %}
</div>
You can simply render the template with the Django tooling:
With django.shortcuts.render()ยค
from django.shortcuts import render
context = {"date": "2024-12-13"}
rendered_template = render(request, "my_template.html", context)
With Template.render()ยค
Either loading the template with get_template():
from django.template.loader import get_template
template = get_template("my_template.html")
context = {"date": "2024-12-13"}
rendered_template = template.render(context)
Or creating a new Template instance:
from django.template import Template
template = Template("""
{% load component_tags %}
<div>
{% component "calendar" date="2024-12-13" / %}
</div>
""")
rendered_template = template.render()
2. Render the componentยค
You can also render the component directly with Component.render(), without wrapping the component in a template.
You can pass args, kwargs, slots, and more, to the component:
from components.calendar import Calendar
calendar = Calendar
rendered_component = calendar.render(
args=["2024-12-13"],
kwargs={
"extra_class": "my-class"
},
slots={
"date": "<b>2024-12-13</b>"
},
)
Info
Among other, you can pass also the request object to the render method:
from components.calendar import Calendar
calendar = Calendar
rendered_component = calendar.render(request=request)
The request object is required for some of the component's features, like using Django's context processors.
3. Render the component to HttpResponseยค
A common pattern in Django is to render the component and then return the resulting HTML as a response to an HTTP request.
For this, you can use the Component.render_to_response() convenience method.
render_to_response() accepts the same args, kwargs, slots, and more, as Component.render(), but wraps the result in an HttpResponse.
from components.calendar import Calendar
def my_view(request):
response = Calendar.render_to_response(
args=["2024-12-13"],
kwargs={
"extra_class": "my-class"
},
slots={
"date": "<b>2024-12-13</b>"
},
request=request,
)
return response
Response class of render_to_response
While render method returns a plain string, render_to_response wraps the rendered content in a "Response" class. By default, this is django.http.HttpResponse.
If you want to use a different Response class in render_to_response, set the Component.response_class attribute:
4. Rendering slotsยค
Slots content are automatically escaped by default to prevent XSS attacks.
In other words, it's as if you would be using Django's escape() on the slot contents / result:
from django.utils.html import escape
class Calendar(Component):
template = """
<div>
{% slot "date" default date=date / %}
</div>
"""
Calendar.render(
slots={
"date": escape("<b>Hello</b>"),
}
)
To disable escaping, you can wrap the slot string or slot result in Django's mark_safe():
Calendar.render(
slots={
# string
"date": mark_safe("<b>Hello</b>"),
# function
"date": lambda ctx: mark_safe("<b>Hello</b>"),
}
)
Info
Read more about Django's format_html and mark_safe.
5. Component views and URLsยค
For web applications, it's common to define endpoints that serve HTML content (AKA views).
You can define the view endpoints directly on your component class by using the nested Component.View class.
This is a great place for:
-
Web pages - Page components can use
Component.View.get()to return the entire web page upon GET request. -
Fragments - Fragment components (partials) can use
Component.View.get()to return HTML fragments upon GET request (to be used with HTMX or similar libraries). -
Form submission - Define
Component.View.post()to handle a POST requests.
Read more on Component views and URLs.
from django_components import Component, ComponentView, register
@register("calendar")
class Calendar(Component):
template = """
<div class="calendar-component">
<div class="header">
{% slot "header" / %}
</div>
<div class="body">
Today's date is <span>{{ date }}</span>
</div>
</div>
"""
class View:
# Handle GET requests
def get(self, request, *args, **kwargs):
# Return HttpResponse with the rendered content
return Calendar.render_to_response(
request=request,
kwargs={
"date": request.GET.get("date", "2020-06-06"),
},
slots={
"header": "Calendar header",
},
)
Info
The View class supports all the same HTTP methods as Django's View class. These are:
get(), post(), put(), patch(), delete(), head(), options(), trace()
Each of these receive the HttpRequest object as the first argument.
Next, define the URL route which will trigger these handlers.
You can either:
-
Use automatically generated component URL using
get_component_url():This HTTP endpoint is automatically registered in Django's
urlpatternswhen you define a handler.To explicitly enable/disable the component's URL, use
Component.View.public: -
Manually assign the URL by setting
Component.as_view()to yoururlpatterns:
And with that, you're all set! When you visit the URL, the component will be rendered and the content will be returned.
The get(), post(), etc methods will receive the HttpRequest object as the first argument. So you can parametrize how the component is rendered for example by passing extra query parameters to the URL:
Customizing component URLs
By default, the component URL is components/{component.class_id}/.
You can customize the auto-generated component URL path by overriding Component.View.get_route_path().
This allows you to use route parameters in your component URLs, e.g.:
Read more about modifying component URLs.