drf-extensions icon indicating copy to clipboard operation
drf-extensions copied to clipboard

Nested Relations get_url patch

Open alexmakeev opened this issue 10 years ago • 8 comments

Привет, перепробовал кучу вещей в инете для nested drf routing, остановился на твоем пакете. У тебя отсутствует генератор полей-ссылок на nested-urls (у базового не хватает kwargs для reverse).

class HyperlinkedNestedIdentityField(HyperlinkedIdentityField):

    def __init__(self, view_name=None, additional_reverse_kwargs={}, **kwargs):
        self.additional_reverse_kwargs = additional_reverse_kwargs
        super(HyperlinkedNestedIdentityField, self).__init__(view_name, **kwargs)

    def get_url(self, obj, view_name, request, format):
        """
        Given an object, return the URL that hyperlinks to the object.

        May raise a `NoReverseMatch` if the `view_name` and `lookup_field`
        attributes are not configured to correctly match the URL conf.
        """
        # Unsaved objects will not yet have a valid URL.
        if obj.pk is None:
            return None

        kwargs = {}
        for k, v in self.additional_reverse_kwargs.iteritems():
            kwargs[k] = getattr(obj, v, v)
        kwargs.update({self.lookup_url_kwarg: getattr(obj, self.lookup_field)})
        return self.reverse(view_name, kwargs=kwargs, request=request, format=format)

Пример использования:

class MealRecordSerializer(serializers.HyperlinkedModelSerializer):
    url = HyperlinkedNestedIdentityField(view_name='mealrecord-detail', read_only=True,
                                         additional_reverse_kwargs={"parent_lookup_user_id": "user_id"})

    class Meta:
        model = MealRecord
        fields = ('id', 'url', 'user', 'date', 'time', 'title', 'calories_count')

alexmakeev avatar Jan 08 '15 16:01 alexmakeev

great, that helped me a lot. The only thing I found is that only works for one level depth.

spac3-monk3y avatar Feb 18 '15 18:02 spac3-monk3y

with that in mind I modified it a little bit so I could used like object1.object2.object3_id.

    def get_url(self, obj, view_name, request, format):
        if obj.pk is None:
            return None

        kwargs = {}
        for k, v in self.additional_reverse_kwargs.iteritems():
            args = v.split('.')
            source = obj
            for arg in args:
                source = getattr(source, arg, arg)
            kwargs[k] = source

        kwargs.update({self.lookup_url_kwarg: getattr(obj, self.lookup_field)})
        return self.reverse(view_name, kwargs=kwargs, request=request, format=format)

use example:

    url = HyperlinkedNestedIdentityRelatedField(view_name='entity-department-role-people-detail',
                                                additional_reverse_kwargs={
                                                    "parent_lookup_role__department__entity": "role.department.entity_id",
                                                    "parent_lookup_role__department": "role.department_id",
                                                    "parent_lookup_role": "role_id",

                                                    })

spac3-monk3y avatar Feb 18 '15 19:02 spac3-monk3y

I think the idea for drf-extensions to support nested urls like /users/1/posts/1/ and /users/1/posts/ with out-of-the box serializer fields is great. Would rename additional_reverse_kwargs to something shorter though, like lookup_kwargs.

maryokhin avatar Feb 19 '15 00:02 maryokhin

Agree, I keep it this way following the @alexmakeev pattern.

spac3-monk3y avatar Feb 19 '15 00:02 spac3-monk3y

Also, I think HyperlinkedIdentityField is only for pointing to the object itself, so it should be HyperlinkedNestedRelatedField.

maryokhin avatar Feb 19 '15 10:02 maryokhin

Agree also

spac3-monk3y avatar Feb 19 '15 14:02 spac3-monk3y

I've had a go at having this fixed, taking the original patch and the recommendations above. What do you think about this? https://gist.github.com/gnarea/1a2bd805237400cb37ef

I'm using this in my own project, and seems to work just fine.

gnarea avatar May 15 '15 14:05 gnarea

would love to see this in this project.

auvipy avatar Mar 31 '16 07:03 auvipy