Django Rest Framework 多数据库

7

我有一个视图,用于对一个非默认数据库进行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请求一直失败,并抱怨表不存在。我的假设是,原因是它正在尝试使用默认数据库而不是我定义为辅助数据库的“Admiral”数据库。如何将POST请求分配给使用特定数据库而不是默认数据库?

3个回答

4
请查看此链接到文档: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)

由于它是一个 queryset,而不是需要使用 db_manager 来创建对象的命令。


谢谢您的回复,但似乎仍在强制使用默认数据库,不确定原因。 - whoisearth
1
我使用Django-Database-Routers解决了这个问题。Django - 使用路由器 - elim

4
在提供的代码中,问题出现在序列化程序尝试保存时,即在该行上:
serializer.save()

-正在使用默认数据库。不能像接受的答案建议的那样使用表单序列化器.serializer.save(using='database_name'),因为serializer类(在此情况下是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并更改create和update方法以利用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在这个问题的评论中提到的那样)是添加一个路由器,这样所有的处理都可以在不必在代码中插入“using”或“db_manager”的情况下完成:https://docs.djangoproject.com/en/2.1/topics/db/multi-db/#using-routers

0

比如说你正在使用一个 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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接