django-components/docs/concepts/fundamentals/component_views_urls.md
Juro Oravec ccf02fa316
chore: util to manage URLs in the codebase (#1179)
* chore: util to manage URLs in the codebase

* docs: mentiion validate_links and supported_versions in docs

* refactor: fix linter errors
2025-05-11 14:59:34 +02:00

6.2 KiB

New in version 0.34

Note: Since 0.92, Component is no longer a subclass of Django's View. Instead, the nested Component.View class is a subclass of Django's View.


For web applications, it's common to define endpoints that serve HTML content (AKA views).

django-components has a suite of features that help you write and manage views and their URLs:

  • For each component, you can define methods for handling HTTP requests (GET, POST, etc.) - get(), post(), etc.

  • Use Component.as_view() to be able to use your Components with Django's urlpatterns. This works the same way as View.as_view().

  • To avoid having to manually define the endpoints for each component, you can set the component to be "public" with Component.View.public = True. This will automatically create a URL for the component. To retrieve the component URL, use get_component_url().

  • In addition, Component has a render_to_response() method that renders the component template based on the provided input and returns an HttpResponse object.

Define handlers

Here's an example of a calendar component defined as a view. Simply define a View class with your custom get() method to handle GET requests:

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`](https://docs.djangoproject.com/en/5.2/ref/class-based-views/base/#django.views.generic.base.View) class. These are:

`get()`, `post()`, `put()`, `patch()`, `delete()`, `head()`, `options()`, `trace()`

Each of these receive the [`HttpRequest`](https://docs.djangoproject.com/en/5.2/ref/request-response/#django.http.HttpRequest) object as the first argument.

!!! warning

**Deprecation warning:**

Previously, the handler methods such as `get()` and `post()` could be defined directly on the `Component` class:

```py
class Calendar(Component):
    def get(self, request, *args, **kwargs):
        return self.render_to_response(
            kwargs={
                "date": request.GET.get("date", "2020-06-06"),
            }
        )
```

This is deprecated from v0.137 onwards, and will be removed in v1.0.

Acccessing component instance

You can access the component instance from within the View methods by using the View.component attribute:

class Calendar(Component):
    ...

    class View:
        def get(self, request):
            return self.component.render_to_response(request=request)

!!! note

The [`View.component`](../../../reference/api#django_components.ComponentView.component) instance is a dummy instance created solely for the View methods.

It is the same as if you instantiated the component class directly:

```py
component = Calendar()
component.render_to_response(request=request)
```

Register URLs manually

To register the component as a route / endpoint in Django, add an entry to your urlpatterns. In place of the view function, create a view object with Component.as_view():

from django.urls import path
from components.calendar.calendar import Calendar

urlpatterns = [
    path("calendar/", Calendar.as_view()),
]

Component.as_view() internally calls View.as_view(), passing the component instance as one of the arguments.

Register URLs automatically

If you don't care about the exact URL of the component, you can let django-components manage the URLs for you by setting the Component.View.public attribute to True:

class MyComponent(Component):
    class View:
        public = True

        def get(self, request):
            return self.component.render_to_response(request=request)
    ...

Then, to get the URL for the component, use get_component_url():

from django_components import get_component_url

url = get_component_url(MyComponent)

This way you don't have to mix your app URLs with component URLs.

!!! info

If you need to pass query parameters or a fragment to the component URL, you can do so by passing the `query` and `fragment` arguments to [`get_component_url()`](../../../reference/api#django_components.get_component_url):

```py
url = get_component_url(
    MyComponent,
    query={"foo": "bar"},
    fragment="baz",
)
# /components/ext/view/components/c1ab2c3?foo=bar#baz
```