【问题标题】:How to get the id of a current object in Django serializers?如何在 Django 序列化程序中获取当前对象的 id?
【发布时间】:2019-10-17 23:44:02
【问题描述】:

我有一个模型,'Project'。这个想法是,用户将登录并创建一个项目。创建后,用户将随时在此项目上工作。某些细节将保存到我在 Serializers.py 中为其编写自定义函数的其他模型中。

为了解决我的想法,我需要在 Serializers.py 中检索用户当前正在处理的当前项目的 id。以下是我的代码:

View.py

class MaterialTagExcelViewSet(FilteredModelViewSet):
    queryset = MaterialTagExcel.objects.all()
    serializer_class = MaterialTagExcelSerializer
    permission_classes = (IsAuthenticated,)
    http_method_names = ('get', 'head', 'post', 'options', 'patch')

Serializers.py

class MaterialTagExcelSerializer(BaseSerializer):

    class Meta:
        fields = "__all__"
        model = MaterialTagExcel

    def create(self, validated_data):
        name = validated_data.get('name')  # get current material name

        if name is not None: 
            name_tag = MaterialTagExcel.objects.filter(name=name).first()  # filter name to check if it already exists

            client = self.context['request'].user.profile.client  # get current client details

            if name_tag is not None:  # if name exists
                objects = MaterialExcelClient.objects.filter(client_id=client.id, name_id=name_tag.id)

                if objects.count() == 0:
                    material_excel_client = MaterialExcelClient(client_id=client.id, name_id=name_tag.id)
                    material_excel_client.save()  # get current id and mat id and save to material_client_excel
                    return MaterialExcelClient.objects.filter(name_id=name_tag.id).order_by('-id')[0]
                else:
                    return MaterialExcelClient.objects.filter(client_id=client.id, name_id=name_tag.id).first()

            else:
                MaterialTagExcel.objects.create(**validated_data)
                MaterialTagExcel.objects.all()  # save if material is new and does not exist

                # return the id of this newly created material
                obj = MaterialTagExcel.objects.filter(name=name).order_by('-id')[0]
                # save the id of the newly created material and current client id into material_excel_client
                material_excel_client = MaterialExcelClient(client_id=client.id, name_id=obj.id)
                material_excel_client.save()
                return MaterialExcelClient.objects.filter(name_id=obj.id).order_by('-id')[0]

通过上面的序列化程序,我可以在 CurrentUserDefault 的帮助下获取 client.id。在我的表中,用户与配置文件相关,而配置文件与客户相关,但与项目无关。我尝试使用自定义 CurrentProjectDefault,但没有成功。我尝试使用许多在线资源来解决我的问题。

有什么方法可以从客户端获取当前对象的 id 吗? 如果我的问题的解决方案非常简单,我提前道歉。

如果您需要更多详细信息,请在评论中写下。

提前致谢。

Models.py

class MaterialTagExcel():
    name = models.CharField(max_length=255, verbose_name='name', null=False, blank=False) 

    def __str__(self):
        return "Material %s: %s" % (self.id, self.name)

    @classmethod
    def get_queryset_for_user(cls, user):
        return cls.objects.all()

class Project():
    client =    models.ForeignKey(Client, related_name='projects', on_delete=models.PROTECT)

    name =                models.CharField(max_length=255)

class ToDo(BaseModel):
    project = models.ForeignKey(Project, related_name='todos', on_delete=models.CASCADE)
    owner_client = models.ForeignKey(Client, related_name='todos', on_delete=models.CASCADE)




【问题讨论】:

  • 您可以发布您的Project 模型吗? Project 链接到什么模型?一个用户?个人资料?
  • 您好 frankie567,项目未链接到用户或个人资料,客户已链接到项目,我试图过度使用其反向关系但出现错误。
  • 请发布您的模型,因为很难理解它们的结构。
  • 你好,我刚刚做了,谢谢
  • 好的,我现在看到了。问题是一个客户可以有多个项目。我看到你正确定义了related_name。因此,您可以通过client.projects.all() 获取客户所有项目的列表。但是你怎么知道哪一个是你逻辑中的“默认”?

标签: django-rest-framework python-3.6 django-serializer django-1.11


【解决方案1】:

您希望检索用户正在处理的当前项目。 REST API 的目标是无状态,这大致意味着请求包含执行其操作所需的所有必要信息,而不依赖于外部上下文。

这意味着您必须在每个请求中提供当前项目 ID。

因此,在您的示例中,当您想要发布新的MaterialTagExcel 时,您必须提供Project。您可以像这样修改您的序列化程序:

class MaterialTagExcelSerializer(BaseSerializer):
    project = serializers.PrimaryKeyRelatedField(write_only=True, queryset=Project.objects.all())

    class Meta:
        fields = "__all__"
        model = MaterialTagExcel

    def create(self, validated_data):

        name = validated_data.get('name')  
        project = validated_data.pop('project') # A Project object

现在,当您发出请求时,您必须使用 id 指定属性 project。用户在菜单中选择的项目。

【讨论】:

  • 这个想法是在后端更新,而不在客户端提供任何 client_id 或 project_id。就像,用户在 MaterialTagExcel 中输入一个名称,该名称将保存在一个表 MaterialTagExcel 中,然后将该名称的 id 和 project_id 保存到后端的另一个名为“MaterialExcelProject”的表中。我已经通过获取其 id 和名称 id 并将其保存到 MaterialExcelClient 为客户端做了同样的事情。我已经添加了相同的序列化程序。请看一看。
猜你喜欢
  • 2021-11-21
  • 2022-11-22
  • 1970-01-01
  • 2022-11-22
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-26
相关资源
最近更新 更多