encode / django-rest-framework

Web APIs for Django. 🎸
https://www.django-rest-framework.org
Other
28.45k stars 6.84k forks source link

Make `URL_FIELD_NAME` setting customizable at the Serializer level #3106

Closed erikcw closed 9 years ago

erikcw commented 9 years ago

There are situations where being able to control the URL_FIELD_NAME setting at the Serializer level is desirable.

For example, I maintain a project with 2 APIs.

1) is a legacy tastypie API that has been migrated to DRF, but must use the same Serialization format as tastypie so that clients aren't broken. 2) an internal "admin" API that uses that standard DRF style.

The legacy API needs the URL field to be called resource_uri. However, since it is a global setting, I have to use it with my "admin" API as well. It also prevents me from releasing a future version of the the API (ie v2) that uses a different URL_FIELD_NAME.

Most of the other settings have fine-grained customizability. This one shouldn't be any different.

Here is the transcript from #restframework:

[9:45am] erikcw: Is it possible to override settings.URL_FIELD_NAME on a per view/serializer basis?
[3:10pm] linovia: erikcw: what is this setting for ?
[3:11pm] erikcw: linovia: It changes the Serializer.url field name to something else — ie Serializer.my_url…
[3:13pm] linovia: erikcw: looking at the sources, it doesn't look like you can do that
[3:14pm] erikcw: Any idea if a pull request would be accepted for this?
[3:16pm] linovia: erikcw: dunno. It looks like it would make the hyperlinked serializers inconsistent
[3:17pm] erikcw: linovia: You mean if you were mixing them in a single project?
[3:17pm] linovia: erikcw: if that wasn't the case, you wouldn't need a per view setting
[3:18pm] erikcw: My use case is that I have 2 APIs in a django project.  A legacy tastypie API that has been migrated to DRF (and hence uses the setting to turn “url” into “resource_uri”).  I also have an “admin” API that sticks to the standard DRF style
[3:19pm] erikcw: Besides, we already allow tweaks of the lookup_field for instance...
[3:20pm] linovia: erikcw: then I think the way to go would be to bring that to an issue so we can discuss it further before putting work in it
[3:20pm] erikcw: linovia: ok
xordoquy commented 9 years ago

You already convinced me on IRC so I'm for this new feature. Waiting for other's feeling about it.

tomchristie commented 9 years ago

No objection from me. Go for it :smile:

k4nar commented 9 years ago

I think this is already quite simple, as you can add a HyperlinkedIdentityField with the name you want. However, you must not use a HyperlinkedModelSerializer but a ModelSerializer, as it would add the url field.

Something like that:

class FooSerializer(ModelSerializer):
    relation_uri = HyperlinkedIdentityField(view_name='foo')
    ...

    class Meta:
        fields = ('relation_uri', ...)

Another way would be to override this method. EDIT: I don't actually think that would work, as ModelSerializer would not have any way to find out that this should be an url. Nevermind.

tomchristie commented 9 years ago

@k4nar True tho I've no great problem with including url_field_name = api_settings.URL_FIELD_NAME on the serializer class, and then referencing self.url_field_name instead of api_settings.URL_FIELD_NAME everywhere.

k4nar commented 9 years ago

Yup, that would work too :) .

jpadilla commented 9 years ago

How would mixins.py#L28 look?

tomchristie commented 9 years ago

@jpadilla I think you'd probably need to override that if you wanted to support per-serializer url fields. I wouldn't really want us to start trying to get too clever there. We could have the class level attribute be a bit of private API, and include a comment re. get_success_headers against it.