StringsOnFire
StringsOnFire

Reputation: 2776

Automatic 'created by user' field using django-rest-framework?

models.py

class Nugget(TimeStampedModel):
    added_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, related_name='added_by', blank=True, null=True)

serializers.py

class NuggetSerializer(TaggitSerializer, serializers.ModelSerializer):
    added_by = serializers.CreateOnlyDefault(default=serializers.CurrentUserDefault())

views.py

class NuggetList(generics.ListCreateAPIView):
    queryset = Nugget.objects.all()
    serializer_class = NuggetSerializer

    def perform_create(self, serializer):
        serializer.save(added_by=self.request.user)

What I'm trying to achieve:

added_by should:

  1. Be set on create of a Nugget
  2. Default to the user who created the Nugget, with no way to override this default
  3. Be included and shown when a Nugget is retrieved
  4. Not be shown as an option for create/POST in the browsable API
  5. Not be editable after create

Upvotes: 7

Views: 3862

Answers (3)

Qumber
Qumber

Reputation: 14569

I did it the following way (no need to make the field nullable):

models.py

class Nugget(models.Model):
    added_by = models.ForeignKey(to=User, related_name='added_by', on_delete=models.DO_NOTHING)

serializers.py

class NuggetSerializer(serializers.ModelSerializer):
    added_by = serializers.StringRelatedField(default=serializers.CurrentUserDefault(), read_only=True)

    class Meta:
        model = Nugget
        fields = ['added_by']

views.py

class NuggetList(viewsets.ModelViewSet):
    queryset = Nugget.objects.all()
    serializer_class = NuggetSerializer

    def perform_create(self, serializer):
        request = serializer.context["request"]
        serializer.save(added_by=request.user)

Upvotes: 3

suhailvs
suhailvs

Reputation: 21710

I have to update views.py to make it work:

class NuggetList(generics.ListCreateAPIView):
    queryset = Nugget.objects.all()
    serializer_class = NuggetSerializer
    permission_classes = (IsAuthenticated,)


    def perform_create(self, serializer):
        req = serializer.context['request']
        serializer.save(added_by=req.user)

Upvotes: 1

StringsOnFire
StringsOnFire

Reputation: 2776

Changed added_by in serializers.py (wasn't using a field, and set to read_only) and .save() in views.py to stop overriding the default.

CurrentUserDefault() requires request within the context dict. In this case generics.ListCreateAPIView already does that.

models.py

class Nugget(TimeStampedModel):
    added_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, related_name='added_by', blank=True, null=True)

serializers.py

class NuggetSerializer(TaggitSerializer, serializers.ModelSerializer):
        added_by = serializers.StringRelatedField(default=serializers.CurrentUserDefault(), read_only=True)

views.py

class NuggetList(generics.ListCreateAPIView):
    queryset = Nugget.objects.all()
    serializer_class = NuggetSerializer

    def perform_create(self, serializer):
        serializer.save()

Upvotes: 5

Related Questions