Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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
like image 675
StringsOnFire Avatar asked Jul 24 '16 20:07

StringsOnFire


People also ask

What is the difference between ModelSerializer and HyperlinkedModelSerializer?

The HyperlinkedModelSerializer class is similar to the ModelSerializer class except that it uses hyperlinks to represent relationships, rather than primary keys. By default the serializer will include a url field instead of a primary key field.

Can Django create REST API?

Django REST framework (DRF) is a powerful and flexible toolkit for building Web APIs. Its main benefit is that it makes serialization much easier. Django REST framework is based on Django's class-based views, so it's an excellent option if you're familiar with Django.

Why do we use Serializers in Django REST framework?

Serializers in Django REST Framework are responsible for converting objects into data types understandable by javascript and front-end frameworks. Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data.

What is renderers in Django REST framework?

The rendering process takes the intermediate representation of template and context, and turns it into the final byte stream that can be served to the client. REST framework includes a number of built in Renderer classes, that allow you to return responses with various media types.


2 Answers

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()
like image 77
StringsOnFire Avatar answered Sep 28 '22 08:09

StringsOnFire


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)

like image 23
Qumber Avatar answered Sep 28 '22 09:09

Qumber