Home > Blockchain >  DRF multiple ManyToOne relations serializer
DRF multiple ManyToOne relations serializer

Time:07-12

sorry my english is not good.

Get request book_id(pk)

How to I serialize ManyToOne fields using BookSerializer to retrieve something

class Book(TimeStampedModel):
    name = models.CharField(max_length=25, null=False)
    owner = models.ForeignKey(User, on_delete=models.DO_NOTHING,unique=True)
    ...
    
    class Meta:
        db_table = 'books'


class BookMember(TimeStampedModel):
    user = models.ForeignKey(User, on_delete=models.DO_NOTHING, null=False)
    book = models.ForeignKey(Book, on_delete=models.CASCADE, null=False)
    
    class Meta:
        db_table = 'book_member'


class User(AbstractBaseUser, PermissionsMixin):
    username = models.CharField(max_length=20, unique=True)
    email = models.EmailField(verbose_name=_('email'))
    ...

    class Meta:
        db_table = 'user'


class BookSerializer(serializers.ModelSerializer):
    user = UserDetailSerializer(read_only=True, many=True, required=False)
    owner = UserDetailSerializer(read_only=True, many=True, required=False)

    class Meta:
        model = Book
        fields = '__all__'

I need to book retrieve

class BookViewSet(ModelViewSet):
    permission_classes = [AllowAny]
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    renderer_classes = [JSONRenderer]

    def retrieve(self, request, *args, **kwargs):
        instance = get_object_or_404(self.queryset, many=True)
        serializer = self.get_serializer(instance)
        return serializer.data

CodePudding user response:

You can span a ManyToManyField [Django-doc] over you BookMember model:

from django.conf import settings

class Book(TimeStampedModel):
    # …
    owner = models.OneToOneField(
        settings.AUTH_USER_MODEL,
        on_delete=models.DO_NOTHING
    )
    members = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        through='BookMember'
    )
    # …
    
    class Meta:
        db_table = 'books'


class BookMember(TimeStampedModel):
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.DO_NOTHING
    )
    book = models.ForeignKey(
        Book,
        on_delete=models.CASCADE
    )
    
    class Meta:
        db_table = 'book_member'

Then you can serialize with:

class BookSerializer(serializers.ModelSerializer):
    user = UserDetailSerializer(read_only=True, many=True, required=False)
    members = UserDetailSerializer(read_only=True, many=True, required=False)

    class Meta:
        model = Book
        fields = '__all__'

Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.


Note: Usually it is better to work with a OneToOneField [Django-doc] instead of a ForeignKey that has unique=True. A OneToOneField is a ForeignKey with unique=True and some small modifications: for example it uses by default the name of the model in lowercase as related_name=… [Django-doc] and makes accessing the relation in reverse more convenient since that does not require a manager in between.


Note: Specifying null=False [Django-doc] is not necessary: fields are by default not NULLable.

  • Related