django-rest-framework icon indicating copy to clipboard operation
django-rest-framework copied to clipboard

Add custom_many_related_field to RelatedField

Open ByK95 opened this issue 1 year ago • 1 comments

Note: Before submitting this pull request, please review our contributing guidelines.

Description

I was using PrimaryKeyRelatedField with source='item.services' but item is a nullable entity in database when its null endpoint is raising 500 error on serialization. In order to fix that I have created custom SafeManyRelatedField wrapped get_attribute and returned empty_list in case attribute exceptions (Happens when accessing multiple relations). In implementation below you can see that Many init is copied from source directly so in order to make it dry I have opened this pr. I think this way would be easier to override with CustomManyRelatedField.

implementation:

class SafeManyRelatedField(ManyRelatedField):
    """
    A custom ManyRelatedField that safely retrieves related fields.
    This field is designed to handle cases where the related field might not exist,
    returning an empty list when the related field is nullable or doesn't exist.
    """

    def get_attribute(self, instance):
        try:
            return super().get_attribute(instance)
        except AttributeError:
            return []


class SafePrimaryKeyRelatedField(PrimaryKeyRelatedField):
    """
    A custom PrimaryKeyRelatedField that safely retrieves related fields.
    This field is designed to handle cases where the related field might not exist,
    ensuring that it can be used safely without raising exceptions.
    """

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    @classmethod
    def many_init(cls, *args, **kwargs):
        list_kwargs = {'child_relation': cls(*args, **kwargs)}
        for key in kwargs:
            if key in MANY_RELATION_KWARGS:
                list_kwargs[key] = kwargs[key]
        return SafeManyRelatedField(**list_kwargs)

and usecase

services = SafePrimaryKeyRelatedField(
        source='item.services',
        many=True, read_only=True,
    )

ByK95 avatar Aug 27 '23 11:08 ByK95

I'm not super sure about the approach or implementation so I will be waiting to know the insights from other maintainers

auvipy avatar Aug 30 '23 07:08 auvipy

My view on almost all incoming PRs at the moment... https://github.com/encode/django-rest-framework/discussions/9270#discussioncomment-8828323

  • What are the clearest ways we can update our contribution guidelines, and start minimizing code churn?
  • How can we ensure that maintainers feel comfortable with helping us to say "no" as a default response?

(@ByK95 thanks for being invested in the project, it is appreciated even tho I'm trying to help us put the brakes on here.)

tomchristie avatar Mar 18 '24 14:03 tomchristie