Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OPTIONS request with TranslatedFieldsField #34

Open
MehdiDRISSIB opened this issue Jun 15, 2021 · 1 comment
Open

OPTIONS request with TranslatedFieldsField #34

MehdiDRISSIB opened this issue Jun 15, 2021 · 1 comment

Comments

@MehdiDRISSIB
Copy link

Hello,

Is there is any way to show all details of each field in TranslatedFieldsField in serializer in OPTIONS request ?

Currently, when calling OPTIONS request, I have :

{
    "name": "Dispute List",
    "description": "",
    "renders": [
        "application/json",
        "text/html"
    ],
    "parses": [
        "application/json",
        "application/x-www-form-urlencoded",
        "multipart/form-data"
    ],
    "actions": {
        "GET": {
            "id": {
                "type": "integer",
                "required": false,
                "read_only": true,
                "label": "ID"
            },
            "translations": {
                "type": "field",
                "required": true,
                "read_only": false,
                "label": "Translations"
            },
            "created_on": {
                "type": "datetime",
                "required": false,
                "read_only": true,
                "label": "Created on"
            }, .....

But I want also all the description of each field in 'translations' (TranslatedFieldsField)

Many thanks for your answers

@MehdiDRISSIB
Copy link
Author

MehdiDRISSIB commented Jun 22, 2021

Hello,

After some works, I just created this class to show Options request with all fields in translations.
I override get_serializer_info to show the fields in the related_model

import types
from collections import OrderedDict
from rest_framework.metadata import SimpleMetadata
from django.core.exceptions import PermissionDenied
from django.http import Http404
from rest_framework import exceptions, serializers
from rest_framework.request import clone_request
from parler.models import TranslatedFieldsModelBase
from parler_rest.fields import TranslatedFieldsField
from typing import Type
from django.db import models


#@lru_cache
def model_serializer(model: Type[models.Model]) -> Type[serializers.ModelSerializer]:
    meta_class = types.new_class("Meta")
    setattr(meta_class, "model", model)
    setattr(meta_class, "fields", "__all__")
    result = types.new_class(
        model.__name__ + "Serializer", (serializers.ModelSerializer,), {}
    )
    setattr(result, "Meta", meta_class)
    return result


class Metadata(SimpleMetadata):

    def determine_actions(self, request, view):
        actions = {}
        for method in {'PUT', 'POST', 'GET'} & set(view.allowed_methods):
            view.request = clone_request(request, method)
            try:
                # Test global permissions
                if hasattr(view, 'check_permissions'):
                    view.check_permissions(view.request)
                # Test object permissions
                if method == 'PUT' and hasattr(view, 'get_object'):
                    view.get_object()
            except (exceptions.APIException, PermissionDenied, Http404):
                pass
            else:
                # If user has appropriate permissions for the view, include
                # appropriate metadata about the fields that should be supplied.
                serializer = view.get_serializer()
                actions[method] = self.get_serializer_info(serializer)

            finally:
                view.request = request

        return actions
        #return super(Metadata, self).determine_actions(request, view)

    def get_serializer_info(self, serializer):
        """
        Given an instance of a serializer, return a dictionary of metadata
        about its fields.
        """
        if hasattr(serializer, 'child'):
            # If this is a `ListSerializer` then we want to examine the
            # underlying child serializer instance instead.
            serializer = serializer.child

        serializer_info = OrderedDict()
        for field_name, field in serializer.fields.items():
            if not isinstance(field, serializers.HiddenField):
                if isinstance(field, (TranslatedFieldsField)):
                    translatable_fields = field.shared_model._parler_meta.get_all_fields()

                    for _field in serializer.Meta.model._meta.get_fields():
                        if isinstance(_field.related_model, TranslatedFieldsModelBase):
                            TranslatableModelSerializer = model_serializer(_field.related_model)
                            TranslatableSerializer = TranslatableModelSerializer()
                            for translatable_field in translatable_fields:
                                translatable_serializer_field = TranslatableSerializer.fields.get(translatable_field)
                                serializer_info.update({translatable_field: self.get_field_info(translatable_serializer_field)})
                else:
                    serializer_info.update({field_name: self.get_field_info(field)})
        return serializer_info

This class is added to REST_FRAMEWORK variable in settings.py:

REST_FRAMEWORK = {
    'DEFAULT_METADATA_CLASS': 'apps.utils.metadata.Metadata',
    ....

I hope this will help someone

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant