In a Django serializer, how to set a foreign key field based on a view argument?

Using the Django REST Framework, I would like to allow users to create and save instances of the Django model using ListCreateAPIView(via POST). One of the fields (the foreign key field, called domain) must be determined from the view parameter defined in urls.py.

In addition, the user can later modify the model instance using queries PUTor an PATCHendpoint RetrieveUpdateDestroyAPIView(using the same serializer). I do not want the user to be able to change the field domainat this point.

As long as I have the code for the model and the structure of the view / serializer, I'm not sure how to tell the serializer to determine the value of the field domainbased on the view parameter. Here is what I got:

class RRset(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(null=True)
    domain = models.ForeignKey(Domain, on_delete=models.CASCADE, related_name='rrsets')
    subname = models.CharField(max_length=255, blank=True)
    type = models.CharField(max_length=10)

... and direct ListCreateAPIView:

class RRsetsDetail(generics.ListCreateAPIView):
    serializer_class = RRsetSerializer
    permission_classes = (permissions.IsAuthenticated,)

    def get_queryset(self):
        name = self.kwargs['name']
        return RRset.objects.filter(domain__name=name, domain__owner=self.request.user.pk)

urls.py contains the following line:

url(r'^domains/(?P<name>[a-zA-Z\.\-_0-9]+)/rrsets/$', RRsetsDetail.as_view(), name='rrsets')

This allows the user to list and create objects RRsetusing a serializer RRsetsSerializer(the field is nameindicated for completeness only, but I do not consider this important in this context):

class RRsetSerializer(serializers.ModelSerializer):
    name = serializers.SerializerMethodField()

    def get_name(self, obj):
        return '.'.join(filter(None, [obj.subname, obj.domain.name])) + '.' # returns 'subname.name.'

    class Meta:
        model = RRset
        fields = ('created', 'updated', 'domain', 'name', 'type',)
        read_only_fields = ('created', 'updated', 'domain', 'type',)

Questions:

  • What do I need to change for the serializer to take the name domainfrom the view parameter name?
  • read_only_fields domain . , , - , ( , )?

: , , - - "write-once" , ".

+4
1

, HiddenField CreateOnlyDefault

HiddenField

, , , .

CreateOnlyDefault

, . .

, .

, , Class-based, .

class DomainDefault(object):
    def set_context(self, serializer_field):
        view = serializer_field.context['view']
        request = serializer_field.context['request']
        self.domain = ...#determine the domain based on request+view

    def __call__(self):
        return self.domain


class RRsetSerializer(serializers.ModelSerializer):
    domain = serializers.HiddenField(default=serializers.CreateOnlyDefault(DomainDefault()))
0

Source: https://habr.com/ru/post/1676672/


All Articles