【问题标题】:How to create an object inside a GET request in a DRF APIview?如何在 DRF APIview 的 GET 请求中创建对象?
【发布时间】:2022-01-26 01:29:53
【问题描述】:

我正在使用 APIView 为视图编写游戏 API,我需要在 GET 请求中创建游戏回合和游戏会话对象。目标是当用户点击游戏时,每次都会创建一个包含几轮的游戏会话。假设一个游戏会话只包含一轮。

如何在 get 方法中正确创建这些对象?我是否为每个字段分配了一些东西?我应该使用 save 还是应该覆盖两者的 create() 方法?

这是我目前所拥有的:

views.py

    def get(self, request, *args, **kwargs):
controller = GameViewController()
        gametype = Gametype.objects.all().filter(name="imageLabeler")
        gametype_serializer = GametypeSerializer(gametype, many=True)

        # while duration is not None:
        random_resource = Resource.objects.all().order_by('?').first()
        resource_serializer = ResourceSerializer(random_resource)

                if request.user is None:
            current_user = '1'
        else:
            current_user = request.user

        current_score = 0

        gamesession = Gamesession.save({
            'id': controller.generate_random_id(Gamesession),
            'user': current_user,
            'gametype': gametype,
            'created': datetime.now(),
        })

        gameround = Gameround.save({
            'id': controller.generate_random_id(Gameround),
            'user': current_user,
            'gamesession': gamesession,
            'created': datetime.now(),
            'score': current_score,
        })

        return Response({'gametype': gametype_serializer.data,
                         'resource': resource_serializer.data
                         })

这些是我的模型: models.py

class Gamesession(models.Model):
    user = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True)
    gametype = models.ForeignKey(Gametype, on_delete=models.CASCADE)
    created = models.DateTimeField(editable=False)

    objects = models.Manager()

    def save(self, *args, **kwargs):
        if not self.id:
            self.created = timezone.now()

        return super().save(*args, **kwargs)


class Gameround(models.Model):
    user = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True)
    gamesession = models.ForeignKey(Gamesession, on_delete=models.CASCADE)
    created = models.DateTimeField(editable=False)
    score = models.PositiveIntegerField(default=0)

    objects = models.Manager()

    def save(self, *args, **kwargs):
        if not self.id:
            self.created = timezone.now()

        return super().save(*args, **kwargs)

【问题讨论】:

    标签: django-models django-rest-framework django-views


    【解决方案1】:

    我正在使用 APIView 为视图编写游戏 API,我需要在 GET 请求中创建游戏回合和游戏会话对象。

    这是违反 HTTP 规范的。 GET 请求应该创建、删除或更新实体。这是在safe methods section of the HTTP documentation [w3.org] 下指定的:

    特别是,已经确立了GET 和HEAD 方法不应具有采取除检索之外的操作的意义的约定。这些方法应该被认为是“安全的”。这允许用户代理以特殊的方式表示其他方法,例如 POST、PUT 和 DELETE,以便让用户意识到正在请求可能不安全的操作。

    允许产生副作用(更新实体)的方法是 POST、PUT、PATCH 和 DELETE。

    因此,这意味着浏览器应该进行 POST 调用以创建一个 Gamesession 例如。因此,Django REST 框架定义的标准APIViews 永远不会将get 方法映射到将创建、更新或删除项目的逻辑。

    【讨论】:

    • 我知道它违反了 HTTP 规范,但我需要它为我正在创建的游戏以这种方式工作。我无法再解决它了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-09
    • 2023-03-28
    • 2011-01-07
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    相关资源
    最近更新 更多