首页 > 解决方案 > 将 create_or_get 与 DRF 一起使用的正确方法

问题描述

我有以下型号

class Word(models.Model):
    """Word object"""
    word = models.CharField(max_length=255, unique=True)

    def __str__(self):
        return self.word


class Category(models.Model):
    """Category object"""
    category = models.CharField(max_length=255, unique=True)

    def __str__(self):
        return self.category


class Group(models.Model):
    """Group object"""
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
    )
    group = models.CharField(max_length=255)
    categories = models.ManyToManyField("Category")
    words = models.ManyToManyField("Word")

    def __str__(self):
        return self.group


class Puzzle(models.Model):
    """Puzzle object"""
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
    )
    puzzle = models.CharField(max_length=255)
    groups = models.ManyToManyField("Group")

    def __str__(self):
        return self.puzzle

以下观点

class WordViewSet(viewsets.ModelViewSet):
    """Manage words in the database"""
    search_fields = ["word"]
    filter_backends = (filters.SearchFilter,)
    queryset = Word.objects.all()
    serializer_class = serializers.WordSerializer
    http_method_names = ["get", "post"]


class CategoryViewSet(viewsets.ModelViewSet):
    """Manage categories in the database"""
    search_fields = ["category"]
    filter_backends = (filters.SearchFilter,)
    queryset = Category.objects.all()
    serializer_class = serializers.CategorySerializer
    http_method_names = ["get", "post"]


class GroupViewSet(viewsets.ModelViewSet):
    """Manage groups in the database"""
    queryset = Group.objects.all()
    serializer_class = serializers.GroupSerializer
    permission_classes = [IsOwner, ]

    def get_serializer_class(self):
        """Return appropriate serializer class"""
        if self.action == "retrieve":
            return serializers.GroupDetailSerializer
        return self.serializer_class

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


class PuzzleViewSet(viewsets.ModelViewSet):
    """Manage puzzles in the database"""
    queryset = Puzzle.objects.all()
    serializer_class = serializers.PuzzleSerializer
    permission_classes = [IsOwner, ]

    def get_queryset(self):
        queryset = Puzzle.objects.all()
        user = self.request.query_params.get("user")
        if user is not None:
            queryset = Puzzle.objects.filter(user=user)
        return queryset

    def get_serializer_class(self):
        """Return appropriate serializer class"""
        if self.action == "retrieve":
            return serializers.PuzzleDetailSerialzer
        return self.serializer_class

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

...以及以下序列化程序

class WordSerializer(serializers.ModelSerializer):
    """Serializer for Word objects"""
    class Meta:
        model = Word
        fields = ("id", "word",)
        read_only_fields = ("id",)


class CategorySerializer(serializers.ModelSerializer):
    """Serializer for Category objects"""
    class Meta:
        model = Category
        fields = ("id", "category",)
        read_only_fields = ("id",)


class GroupSerializer(serializers.ModelSerializer):
    """Serializer for Group objects"""

    def validate(self, data):
        if len(data["words"]) != 4:
            raise ValidationError("Groups require exactly 4 words.")
        return data

    class Meta:
        model = Group
        fields = ("id", "group", "user", "categories", "words",)
        read_only_fields = ("id", "user",)


class GroupDetailSerializer(GroupSerializer):
    """ Detail Serializer for Group object"""
    words = WordSerializer(many=True, read_only=True)
    categories = CategorySerializer(many=True, read_only=True)


class PuzzleSerializer(serializers.ModelSerializer):
    """Serializer for Puzzle object"""

    def validate(self, data):
        if len(data["groups"]) != 4:
            raise ValidationError("Puzzles require exactly 4 groups.")
        return data

    class Meta:
        model = Puzzle
        fields = ("id", "puzzle", "user", "groups")
        read_only_fields = ("id", "user",)


class PuzzleDetailSerialzer(PuzzleSerializer):
    """Detail Serializer for Puzzle object"""
    groups = GroupDetailSerializer(many=True, read_only=True)

我希望能够在不需要知道单词对象或类别对象的 id 的情况下对拼图对象进行发布请求。如果没有现有对象,则应将其创建并添加到组中,否则应将现有对象添加到组中。我的前端搜索这些单词和类别对象并使用单独的帖子请求创建它们似乎毫无意义。我希望能够一口气完成所有工作。我想我需要使用 create_or_get 但我正在寻找一些关于如何在这种情况下这样做的指导。

{
    "puzzle": "my puzzle",
    "groups": [
        {
            "group": "my animals",
            "categories": ["animals"],
            "words": ["cat", "dog", "turtle", "fish", ]
        },
        {
            "group": "my kitchen",
            "categories": ["kitchen"],
            "words": ["cup", "plate", "fork", "knife"]
        },
        {
            "group": "my people",
            "categories": ["people"],
            "words": ["man", "woman", "boy", "girl"]
        },
        {
            "group": "my clothes",
            "categories": ["clothes"],
            "words": ["shirt", "pants", "jacket", "hat"]
        }
    ]
}

标签: djangodjango-rest-framework

解决方案


推荐阅读