# Route overrides

{% hint style="success" %}
This is the official documentation of the `forestadmin-agent-django` and `forestadmin-agent-flask` Python agents.
{% endhint %}

[Route overrides](https://docs.forestadmin.com/documentation/reference-guide/routes/override-a-route) allowed customizing the behavior of the routes exposed by the agent.

This very low-level feature was used to implement many use cases:

* Attach handlers to events in the UI
* Customize filtering, search and sort behaviors
* Other advanced use cases.

Because our new agent API is higher-level, the protocol used to communicate between the agent and the application can no longer be manipulated.

## Code cheatsheet

| What was the route override used for?   | How to migrate it?                                                                                                                                                                    |
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Add custom permissions                  | Use [.add\_hook](https://docs.forestadmin.com/developer-guide-agents-python/agent-customization/hooks) and throw `forbidden errors`                                                   |
| Add validation to fields                | Use [.add\_field\_validation](https://docs.forestadmin.com/developer-guide-agents-python/agent-customization/fields/validation) instead                                               |
| Add validation to whole records         | Use [.add\_hook](https://docs.forestadmin.com/developer-guide-agents-python/agent-customization/hooks) and throw `validation errors`                                                  |
| Run code on UI events                   | Use [.add\_hook](https://docs.forestadmin.com/developer-guide-agents-python/agent-customization/hooks) to perform custom logic                                                        |
| Change the search behavior              | Use [.replace\_search](https://docs.forestadmin.com/developer-guide-agents-python/agent-customization/search) to implement your custom search logic                                   |
| Change the filtering behavior of fields | Use [.replace\_field\_operator](https://docs.forestadmin.com/developer-guide-agents-python/agent-customization/fields/filter)                                                         |
| Change the sort behavior of fields      | Use [.replace\_field\_sorting](https://docs.forestadmin.com/developer-guide-agents-python/agent-customization/fields/sort)                                                            |
| Other use case                          | If you are stuck or think that this guide can be improved, please [expose your use case in the community forums](https://community.forestadmin.com/) and we will be happy to help you |

## Examples

### Add custom permissions

{% hint style="warning" %}
Custom permissions would better be implemented by using the [Roles](https://docs.forestadmin.com/user-guide/project-settings/teams-and-users/manage-roles) feature from the UI.
{% endhint %}

{% tabs %}
{% tab title="Before" %}

* Define a new route into your `urls.py` file:
* Add a new method in your controller.

```python
from django.http import  HttpResponse
from django.views import generic

from app.models import Book

class BooksView(generic.ListView):
    def delete(self, request, pk, *args, **kwargs):
        Book.objects.filter(id=pk).delete()

        return HttpResponse(status=204)
```

{% endtab %}

{% tab title="After" %}

```python
from forestadmin.datasource_toolkit.decorators.hook.context.delete import (
    HookBeforeDeleteContext
)

def before_delete_hook(context: HookBeforeDeleteContext):
    is_allowed = True  # Your logic here

    if is_allowed is False:
        context.throw_forbidden_error(
            "This collection is protected, you cannot remove from it."
        )

agent.customize_collection('Book').add_hook('Before', 'Delete', before_delete_hook)
```

{% endtab %}
{% endtabs %}

### Add validation to fields

{% tabs %}
{% tab title="Before" %}

* Define a new route into your `urls.py` file.
* Add a new method to your controller.

```python
import re

from django.http import  HttpResponse
from django_forest.resources.views.detail import DetailView
from django_forest.resources.views.list import ListView

from app.models import Book

class CompanyView(ListView):
    def post(self, request, pk, *args, **kwargs):
        patch = self.get_body(request.body)["data"]["attributes"]

        if "name" in patch and re.search(r'^Forest', patch["name"]):
            return self.error_response(
                "All company names should begin with 'Forest'."
            )

        return super().post(request, pk, *args, **kwargs)

class CompanyDetailView(DetailView):
    def put(self, request, pk):
        patch = self.get_body(request.body)["data"]["attributes"]

        if "name" in patch and re.search(r'^Forest', patch["name"]):
            return self.error_response(
                "All company names should begin with 'Forest'."
            )

        return super().put(request, pk)
```

{% endtab %}

{% tab title="After" %}

```python
agent.customize_collection('companies').add_field_validation(
    'name', 'match', r'^Forest'
)
```

{% endtab %}
{% endtabs %}

### Run code on UI events

{% tabs %}
{% tab title="Before" %}

* Define a new route into your `urls.py` file:
* Add a new method to your controller.

```python
from django_forest.resources.views.list import ListView

class CustomerView(ListView):
    def post(self, request, pk, *args, **kwargs):
        try:
            superagent.post('https://my-company/create-card').set(
                'X-API-Key', '**********'
            ).end()
        finally:
            return super().post(request, pk, *args, **kwargs)

```

{% endtab %}

{% tab title="After" %}

```python
from forestadmin.datasource_toolkit.decorators.hook.context.create import (
    HookBeforeCreateContext
)

def before_create_hook(context: HookBeforeCreateContext):
    superagent.post('https://my-company/create-card').set(
        'X-API-Key', '***********'
    ).end()

agent.customize_collection('customers').add_hook(
    'Before', 'Create', before_create_hook
)
```

{% endtab %}
{% endtabs %}
