Micheal J. Roberts
Micheal J. Roberts

Reputation: 4180

Django REST Framework: Using the Accept-Language header to set an instance's "locale"

So, I have a model with the following attribute:

locale = models.CharField(max_length=10, choices=get_locale_choices(), default='en-gb')

The associated serializer for this model is currently:

class MyModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyModel
        fields = '__all__'

I then call a create endpoint:

serializer = self.get_serializer(data=request.data)

serializer.is_valid(raise_exception=True)

self.perform_create(serializer)

I was wondering, how best to modify the above to allow the locale attribute of MyModel to be updated by the Accept-Language header en-GB,en;q=0.5.

I get my locale choices from django.conf.locale.LANG_INFO:

from django.conf.locale import LANG_INFO

def get_locale_choices():
    return [(k, v['name']) for k, v in LANG_INFO.items() if 'name' in v]

I guess I need to pass in the request.headers as some sort of extra context...? But I'm thinking, what if the Accept-Language is not set, etc? I know it is here:

request.headers['Accept-Language'] 

So, I guess request.headers.get('Accept-Language', 'en-gb') would be acceptable ...

But then, what would be the best way to then set the attribute in the serialzier as this?

N.B. I also believe get_serializer_context() can return the request object?

I also feel this could be robust enough:

data = request.POST.copy()

serializer = self.get_serializer(data=data.update({'locale': request.headers.get('Accept-Language', 'en')}))

But is this, "good practise"?

Opinions are warmly welcome!

Upvotes: 2

Views: 4020

Answers (1)

JPG
JPG

Reputation: 88589

Without "much considering the locale" try this method to save any data from request.

  1. First you need to set the locale field to read_only
class MyModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyModel
        fields = '__all__'
        read_only_fields = ('locale',)
  1. override the perform_create(...) method of the ModelViewset or similar viewclass
class MyModelViewSet(viewsets.ModelViewSet):
    # other code
    def perform_create(self, serializer):
        serializer.save(locale=self.request.headers.get('Accept-Language', 'en-gb'))

Upvotes: 2

Related Questions