【问题标题】:django rest framework multiple databasedjango rest框架多数据库
【发布时间】:2014-09-05 17:07:58
【问题描述】:

我有一个视图用于 GET 和 POST 到不是默认数据库的数据库。

class DeployResourceFilterView(generics.ListAPIView):
    serializer_class = ResourceSerializer

    def get(self, request, format=None):
        resname = self.request.GET.get('name')
        queryset = Resmst.objects.db_manager('Admiral').filter(resmst_name=resname)
        serializer = ResourceSerializer(queryset)
        if queryset:
            return Response(serializer.data)
        else:
            raise Http404

    def post(self, request, format=None):
        serializer = ResourceSerializer(data=request.DATA, many=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

GET 工作得非常好,但在 POST 上它总是失败,抱怨表不存在。我的假设是这样做的原因是因为它试图使用默认数据库而不是我定义为辅助数据库的“海军上将”数据库。如何分配 POST 以使用特定数据库而不是默认数据库?

【问题讨论】:

    标签: django django-rest-framework


    【解决方案1】:

    请参阅此文档链接:https://docs.djangoproject.com/en/1.7/topics/db/multi-db/#selecting-a-database-for-save

    您可以指定要保存到的数据库,只需将其作为参数传递:

    my_object.save(using='database-name')
    

    在你的情况下是:

    serializer.save(using='Admiral')
    

    您还应该像这样在queryset 中使用它:

    queryset = Resmst.objects.using('Admiral').filter(resmst_name=resname)
    

    因为它是一个查询集,而不是一个像创建对象那样需要db_manager 的命令。

    【讨论】:

    • 谢谢你,但它似乎仍在强制默认数据库不知道为什么。
    • 我用 Django-Database-Routers 解决了这个问题。 Django - Using routers
    【解决方案2】:

    在操作提供的代码中,当序列化程序尝试保存时出现问题,即在线

    serializer.save()
    

    -正在使用默认数据库。不能像公认的答案所建议的那样使用形式 serializer.save(using='database_name') ,因为序列化程序类(在本例中为 ResourceSerializer 类)不会理解/预期 kwarg“using='database_name”。

    django 文档指出,如果您有模型 (model.Model),那么可以使用 my_object.save(using='database_name') 请参阅此处以获取报价:https://docs.djangoproject.com/en/2.1/topics/db/multi-db/#selecting-a-database-for-save .但是序列化器显然不是模型实例。

    在上述情况下,您可以继承(或修改 - 我更喜欢在我自己创建序列化程序时修改)ResourceSerializer 并更改创建和更新方法以使用 db_manager('Admiral')。例如:

    class MyResourceSerializer(ResourceSerializer):
        def create(self, validated_data):
            """
            copy the create from ResourceSerializer and amend it here, with code such as
            follows in the try section.
            """
            ModelClass=Resmst  # or whichever desired model you are acting on
            try:
                instance = ModelClass.objects.db_manager('Admiral').create(**validated_data)
            except TypeError: # or whatever error type you are mitigating against, if any
                raise TypeError()
            return instance
    

    一个不错的选择(正如 elim 在该问题的一个 cmets 中提到的那样)是添加一个路由器并处理这一切,而无需在整个代码中插入“使用”或“db_manager”:https://docs.djangoproject.com/en/2.1/topics/db/multi-db/#using-routers

    【讨论】:

      【解决方案3】:

      比如说你正在使用ListCreateAPIView

      您也许可以在视图级别使用get_queryset

      class YourModelDRFGetView(generics.ListCreateAPIView):
          serializer_class = YourModelDRFViewSerializer
      
          def get_queryset(self):
              return YourModel.objects.using('your_read_replica').all()
      

      your_read_replicasettings.py 中定义:

      replica_database_url = os.environ.get("DATABASE_REPLICA_URL") or database_url
      DATABASES["your_read_replica"] = dj_database_url.parse(replica_database_url)
      

      【讨论】:

        猜你喜欢
        • 2015-10-10
        • 1970-01-01
        • 2016-08-11
        • 2013-11-07
        • 1970-01-01
        • 2017-02-13
        • 2020-04-24
        • 2014-12-22
        • 1970-01-01
        相关资源
        最近更新 更多