Cassandra用户定义类型上的Django Queryset引发类型错误

问题描述 投票:1回答:1

我正在使用DataStax Python DriverDjango Cassandra Engine的组合,通过Django应用与Cassandra通信。

这是我如何使用“用户定义的类型”列定义模型(仅示例):

from cassandra.cqlengine import columns
from cassandra.cqlengine.usertype import UserType
from django_cassandra_engine.models import DjangoCassandraModel

class UserAddress(UserType)
    street = columns.Text()
    number = columns.Integer()

class User(DjangoCassandraModel):
    __table_name__ = 'users'

    user_id = columns.UUID(primary_key=True)
    name = columns.Text()
    address = columns.UserDefinedType(UserAddress)


class Meta:
    managed = False
    get_pk_field = 'user_id'

我正在尝试通过以下调用查询此模型:

User.objects.filter(user_id=user_id)

引发此错误:

File "/usr/local/lib/python3.8/site-packages/cassandra/cqlengine/columns.py", line 1043, in to_python

if copied_value[name] is not None or isinstance(field, BaseContainerColumn):

TypeError: tuple indices must be integers or slices, not str

此错误源自UserDefinedType类声明,特别是此函数:

    def to_python(self, value):
    if value is None:
        return

    copied_value = deepcopy(value)
    for name, field in self.user_type._fields.items():
        if copied_value[name] is not None or isinstance(field, BaseContainerColumn):
            copied_value[name] = field.to_python(copied_value[name])

    return copied_value

[在我看来,包含DjangoCassandraQuerySet类的Django Cassandra Engine在UserDefinedType类上的表现不佳,尽管我不确定为什么。

到目前为止,我对这些库都没有任何问题,但我发现奇怪的是,不支持此类操作。我希望我错过了某个地方的配置,或者至少该问题是可以解决的。

谢谢您的时间。

python django cassandra django-queryset datastax
1个回答
0
投票

感谢Django Cassandra Engine问题页面上的this comment,以解决此问题。

[DataStax Python驱动程序似乎将未注册的类型解释为普通字典,导致将它们反序列化为一系列元组而不是适当的字典,从而解释了错误消息。

解决方法是在每次启动连接时注册UDT。必须每次都执行此操作,因为它似乎不会持续存在。

这里是注册UDT的示例:

from cassandra.cqlengine import columns
from cassandra.cqlengine.usertype import UserType    
from django.db import connections
from cassandra.cluster import UserTypeDoesNotExist

class UserAddress(UserType)
    street = columns.Text()
    number = columns.Integer()

user_types = [ UserAddress ]
database_name = 'DjangoDBName'
keyspace = 'CassandraKeyspace'
connection = connections[database_name]

for udt in user_types:
  try:
    connection.connection.cluster.register_user_type(keyspace, udt.type_name(), udt)
  except UserTypeDoesNotExist:
    pass

我已将此添加到我的UDT包的__init__.py文件中。或者,如果所有UDT声明都在一个文件中,则将其添加到该文件的末尾也将起作用,如上面的示例所示。

为什么Django Cassandra Engine无法自动注册这些类型,我不知道。

© www.soinside.com 2019 - 2024. All rights reserved.