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_context_data(self):
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
Info
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:
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 mark_safe()
function on the slot content:
from django.utils.safestring import mark_safe
class Calendar(Component):
template = """
<div>
{% slot "date" default date=date / %}
</div>
"""
Calendar.render(
slots={
"date": mark_safe("<b>Hello</b>"),
}
)
To disable escaping, you can pass escape_slots_content=False
to Component.render()
or Component.render_to_response()
methods.
Warning
If you disable escaping, you should make sure that any content you pass to the slots is safe, especially if it comes from user input!
Info
If you're planning on passing an HTML string, check Django's use of format_html
and mark_safe
.
Component views and URLs¤
For web applications, it's common to define endpoints that serve HTML content (AKA views).
If this is your case, you can define the view request handlers directly on your component by using the nestedComponent.View
class.
This is a great place for:
-
Endpoints that render whole pages, if your component is a page component.
-
Endpoints that render the component as HTML fragments, to be used with HTMX or similar libraries.
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, you need to set the URL for the component.
You can either:
-
Automatically assign the URL by setting the
Component.Url.public
attribute toTrue
.In this case, use
get_component_url()
to get the URL for the component view. -
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: