Here’s a proposal (django-components) for the API for configuring <head>. It’s inspired by unhead. I wonder if you had similar issues with populating the <head> tag, or other suggestions?
-–
For context, when you render your templates / HTML, you usually populate the <head> to include CSS, metadata like page title, or SEO metadata, and more.
When you render the entire page as a single template, you can just update the directly, because you know exactly what to put there.
But when you break the template down into smaller reusable parts, it gets trickier. Maybe there’s a “ProfileCard” component, and you want to set the page title and SEO metadata based on the contents of the user profile.
Currently you’d have to lift the metadata up
user = Users.object.get(pk=id)
context = Context({
"user": user,
"user_name": user.name
})
template = Template("""
<html>
<head>
<meta property="og:title" content="{{ user_name }}" />
<meta property="og:type" content="profile" />
</head>
<body>
{% component "ProfileCard" user=user / %}
</body>
</html>
""")
Downsides:
- You have to repeat this for each page where you want to use `ProfileCard`
- If your colleague replaces `ProfileCard` with something else in the future, they might forget to update the metadata
Instead, the proposal is to define the metadata next to what they belong to. In django-components you define templates as classes, so it’s on this class where you’d define the head metadata:
class ProfileCard(Component):
class Kwargs:
user: User
class Head:
title = "User profile"
# Or dynamically
title = lambda c: f"User profile: {c.kwargs.user.name}"
meta = [
{"property": "og:title", content="User profile"},
{"property": "og:type", content="profile"},
]
This way, whenever you would render ProfileCard in a template, the would be automatically set to contain this metadata.
Then, the page template could be simplified to:
<html>
<body>
{% component "ProfileCard" user=user / %}
</body>
</html>