.. _Backend:

#######
Backend
#######

.. note::

   This guide assumes you have a working Django/DjangoRestFramework environment.
..


***********
Setup table
***********

Once **DjVue** is installed inside our Django project, we can start using it inside our API system starting from
creating serializers for those models we want to integrate with **DjVue**.

Let's assume we have a model like this in our project:

.. code-block:: python

    # models.py
    class ExampleModel(models.Model):
        char_field = models.CharField()
        bool_field = models.BooleanField()
        int_field = models.IntegerField()
        float_field = models.DecimalField()
        ...
..


In order to achieve an autogenerated table in one of ours template, which table reflects data residing in our database,
we'll need to perform these two following tasks:

- **Create a serializer** in order to:

    - Choose what information of the data to send to frontend
    - Manipulating data before it is sent to frontend

- **Create a ViewSet** in order to:

    - Accordingly to the request, query data from database to serialize
    - Send other additional information about how data will be handled by frontend
    - Enable/disable operations on data


So let's create the related serializer just like we always have done:

.. code-block:: python

    # serializers.py
    class ExampleSerializer(serializers.ModelSerializer):
        char_field = serializers.CharField(label='Char Field')

        class Meta:
            model = ExampleModel
            fields = [
                'char_field',
                'bool_field',
                'int_field',
                'float_field',
            ]
..

By default, **DjVue** assigns labels to fields reflecting the fields' name but we can assign custom labels as we have
just done for :code:`char_field` accordingly to their types.

At this point we'll need the ViewSet as end-point for the list requests, also here as we always have done but
extending :code:`DjVueGenericViewSet` before of :code:`ListModelMixin` (which is required) and all the others mixins:

.. code-block:: python

    class ExampleViewSet(DjVueGenericViewSet, ListModelMixin, ... ):
        serializer_class = ExampleSerializer
        list_fields = [
            'char_field',
            'int_field',
            'float_field'
        ]

        def get_queryset(self):
            return ModelExample.objects.all()
        ...
..

As we can see, just few of the field selected in the serializer are selected in the ViewSet as well, this is intended
because all the data selected in the serializer are sent to the frontend but only the fields listed in
:code:`list_fields` are displayed in the result table. This behaviour can be useful if we want to send some extra
information about the elements but we don't want to show them inside the table (for example if we want the element's id
within the javascript).

Finally we have to register the endpoint through the :code:`DjvueSimpleRouter` as we always have done with the
DjangoRestFramework's :code:`SimpleRouter`:

.. code-block:: python

    router = DjvueSimpleRouter()
    router.register(r'<url_path>', ProdottoViewSet, basename='<url_basename>')

    urlpatterns = [
        ...
        path('<djvue_api_url_path>/', include(router.urls)),
        ...
    ]
..

|

------------------------------------------------------------------------------------------------------------------------

|

******
Tuning
******

**DjVue** offers us some customizations to do backend side, in order to control some properties of the data sent to
frontend.

Filtering
=========

Among other things, **DjVue** offers us the possibility to filter the results inside the table.
We can specify which fields can be used in order to perform a filtering operation:

.. TODO

.. warning::

    Choose our search fields with awareness, keep in mind that fields serialized through :code:`SerializerMethodField`
    can not be used as search field.

    Possible workarounds :ref:`here<Avoid using SerializerMethodField>`.
..

.. code-block:: python

    class ExampleViewSet(DjVueGenericViewSet, ListModelMixin, ... ):
        serializer_class = ExampleSerializer
        list_fields = [
            'char_field',
            'int_field',
            'float_field'
        ]
        search_fields = [
            'char_field'
        ]

        def get_queryset(self):
            return ModelExample.objects.all()
        ...
..

This way, when we'll type something inside the serach input upon the table, the search will be performed considering only
the :code:`char_field`.


Sorting
=======

**DjVue** gives us te possibility to define on which fields we can toggle the sorting. We can customize this feature
this way:

.. TODO

.. warning::

    Choose our sorting fields with awareness, keep in mind that fields serialized through :code:`SerializerMethodField`
    can not be used as sorting field.

    Possible workarounds :ref:`here<Avoid using SerializerMethodField>`.
..

.. code-block:: python

    class ExampleViewSet(DjVueGenericViewSet, ListModelMixin, ... ):
        serializer_class = ExampleSerializer
        list_fields = [
            'char_field',
            'int_field',
            'float_field'
        ]
        ordering_fields = [
            'int_field'
        ]

        def get_queryset(self):
            return ModelExample.objects.all()
        ...
..

This way, we'll be able to click on the head of the column related to the :code:`int_field` and see the rows on the
table being sorted accordingly to the order we set.


Pagination
==========

**DjVue** also takes care of the pagination for us but we can both disable it or change the page size as we wish
this way:

.. TODO

|

------------------------------------------------------------------------------------------------------------------------

|

*****
Forms
*****

**DjVue** comes with a builtin module that gives us the ability to interact with the database in a similar way to
what we always did with standard Django's forms but instead of writing specific form classes and bind them in the view,
**DjVue** can do that automatically, using information found in serializers and ViewSets.

The frontend, on the other hand, contains a module which send some requests to backend and so retrieves information
about models and allowed CRUD operations. Afterwords these information are processed to render the form accordingly.

To accomplish this job, **DjVue** lets us focus the entire task on writing serializers and no more forms.
In order to get the full form features we should use the **DejVue**'s fields, which provide more information about
field's properties.
You can learn more about **DjVue** fields' wrappers in the :ref:`next section<djvuefields>`.

Let's get back on the example model we used for previous examples and suppose we want to use **DjVue** for managing both
the create operation on this model and the form generation as well:

.. code-block:: python

    # models.py
    class ExampleModel(models.Model):
        char_field = models.CharField()
        bool_field = models.BooleanField()
        int_field = models.IntegerField()
        float_field = models.DecimalField()
        ...
..

So we should revisit the serializer this way, using **DjVue** fields' wrappers:

.. code-block:: python

    # serializers.py
    class ExampleCreateSerializer(serializers.ModelSerializer):
        char_field = DVCharField()
        bool_field = DVBooleanField()
        int_field = DVIntegerField()
        float_field = DVDecimalField()

        class Meta:
            model = ExampleModel
            fields = [
                'char_field',
                'bool_field',
                'int_field',
                'float_field',
            ]
..

Finally we revisit the ViewSet as well, so we will make it extends the :code:`CreateModelMixin` in order to both make
the endpoint available for creation (POST HTTP requests) and make **DjVue** enable the form generation and send
the proper information to frontend.

.. code-block:: python

    class ExampleViewSet(DjVueGenericViewSet, ListModelMixin, CreateModelMixin... ):
        serializer_class = ExampleSerializer
        list_fields = [
            'char_field',
            'int_field',
            'float_field'
        ]

        def get_queryset(self):
            return ModelExample.objects.all()
        ...
..

Now this endpoint is ready to interact with a **DjVue** component within the frontend which will provide you also the
possibility to create model's instances with an autogenerated form.

In the same way you can enable both update and delete operations.

For the update operation we'll just make our view extends also the :code:`UpdateModelMixin` and the magic is done. The
frontend will provide for us a way for update model's instances.

.. code-block:: python

    class ExampleViewSet(DjVueGenericViewSet, ListModelMixin, CreateModelMixin, UpdateModelMixin... ):
        serializer_class = ExampleSerializer
        list_fields = [
            'char_field',
            'int_field',
            'float_field'
        ]

        def get_queryset(self):
            return ModelExample.objects.all()
        ...
..

Exactly the same thing for what concerns :code:`RetrieveModelMixin`. Making our ViewSet extends this
mixin, the frontend will provide us a way to visualize a detail view of the model's instances.

.. code-block:: python

    class ExampleViewSet(DjVueGenericViewSet, ListModelMixin, CreateModelMixin, UpdateModelMixin, RetrieveModelMixin... ):
        serializer_class = ExampleSerializer
        list_fields = [
            'char_field',
            'int_field',
            'float_field'
        ]

        def get_queryset(self):
            return ModelExample.objects.all()
        ...
..

For the delete operation as well, except we will not need a particular serializer, we'll just make our ViewSet extend
:code:`DestroyModelMixin` so our component within the frontend will give us the possibility to delete model's instances

.. code-block:: python

    class ExampleViewSet(DjVueGenericViewSet, ListModelMixin, CreateModelMixin, UpdateModelMixin, RetrieveModelMixin, DestroyModelMixin... ):
        serializer_class = ExampleSerializer
        list_fields = [
            'char_field',
            'int_field',
            'float_field'
        ]

        def get_queryset(self):
            return ModelExample.objects.all()
        ...
..