使用带有自然键的转储数据,Django对象不可序列化CommandError

问题描述

我正在尝试在“ manage.py dumpdata”命令中使用“自然键”进行序列化(docs):

python manage.py dumpdata --natural-primary --natural-foreign --indent 4 --format json --verbosity 1 > tests\test_fixtures\test_db2.json

当我在使用Project或Task模型(它们都必须设计)的其他应用上使用--natural-foreign时,出现以下错误:

CommandError: Unable to serialize database: Object of type Project is not JSON serializable
Exception ignored in: <generator object cursor_iter at 0x000001EF62481B48>
Traceback (most recent call last):
  File "C:\Users\Andrew\anaconda3\envs\Acejet_development\lib\site-packages\django\db\models\sql\compiler.py",line 1586,in cursor_iter
    cursor.close()
sqlite3.ProgrammingError: Cannot operate on a closed database.

如果我只是从中转储数据,则“项目”应用程序可以运行,但是其他应用程序是使用与项目或任务相关的实体构建的,因此--natural-foreign选项将失败。

当模型(例如问问题)从Task要求一个natural_key,而其中从Project要求一个natural_key时,就会出现问题。

如果我使用Pycharm Python控制台访问项目或任务的查询集(此处为“ q”),则可以使用:

serializers.serialize('json',q,indent=2,use_natural_foreign_keys=True,use_natural_primary_keys=True)

但是,如果“ w”是来自另一个具有Task外键的应用程序中的Question对象的列表,则会出现此错误:

    Traceback (most recent call last):
  File "<input>",line 1,in <module>
  File "C:\Users\Andrew\anaconda3\envs\Acejet_development\lib\site-packages\django\core\serializers\__init__.py",line 128,in serialize
    s.serialize(queryset,**options)
  File "C:\Users\Andrew\anaconda3\envs\Acejet_development\lib\site-packages\django\core\serializers\base.py",line 115,in serialize
    self.end_object(obj)
  File "C:\Users\Andrew\anaconda3\envs\Acejet_development\lib\site-packages\django\core\serializers\json.py",line 53,in end_object
    json.dump(self.get_dump_object(obj),self.stream,**self.json_kwargs)
  File "C:\Users\Andrew\anaconda3\envs\Acejet_development\lib\json\__init__.py",line 179,in dump
    for chunk in iterable:
  File "C:\Users\Andrew\anaconda3\envs\Acejet_development\lib\json\encoder.py",line 431,in _iterencode
    yield from _iterencode_dict(o,_current_indent_level)
  File "C:\Users\Andrew\anaconda3\envs\Acejet_development\lib\json\encoder.py",line 405,in _iterencode_dict
    yield from chunks
  File "C:\Users\Andrew\anaconda3\envs\Acejet_development\lib\json\encoder.py",line 325,in _iterencode_list
    yield from chunks
  File "C:\Users\Andrew\anaconda3\envs\Acejet_development\lib\json\encoder.py",line 438,in _iterencode
    o = _default(o)
  File "C:\Users\Andrew\anaconda3\envs\Acejet_development\lib\site-packages\django\core\serializers\json.py",line 104,in default
    return super().default(o)
  File "C:\Users\Andrew\anaconda3\envs\Acejet_development\lib\json\encoder.py",in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type Project is not JSON serializable

模型是:

# projects.models.py
class BaseModelWithHistory(models.Model):
    history = HistoricalRecords(inherit=True)
    natural_key_fields = ('id',)  # default

    class Meta:
        abstract = True

    def natural_key(self):
        fieldlist = [getattr(self,fieldname) for fieldname in self.natural_key_fields]
        return tuple(fieldlist)
 #  natural_key.dependencies = ['projects.Project','projects.Task']  # serialize these first.

class Project(BaseModelWithHistory):
    """
    'Projects' group Tasks.
    """
    project_name = models.CharField(max_length=200,default="development_project")
    project_short_description = models.CharField(
        max_length=500,default="This is the default text.")
    target_group = models.ManyToManyField(Group,blank=True)
    objects = ProjectDiscreteManager()

    natural_key_fields = ('project_name',)

class Task(BaseModelWithHistory):
    number = models.PositiveIntegerField(default=0)
    name = models.CharField(max_length=200,default='new task')
    project = models.ForeignKey(Project,on_delete=models.CASCADE)
    target_group = models.ManyToManyField(Group,blank=True)
    app_label = models.CharField(max_length=80,choices=app_choices(),null=True,blank=True)

    objects = discrete_manager_factory('project')
    natural_key_fields = ('project','name','number')

我没想到会导致此问题,但我肯定是错的:

  • 由Discrete_manager_factory()创建的ProjectDiscreteManager和其他对象的行为与默认管理器(models.Manager())完全相同,除非通过已标识用户的请求进行调用,在这种情况下,它将添加一个过滤器以查看该用户是否为在小组中。
  • 所有模型都定义了natural_keys元组,因为父类将其定义为('id',);大多数模型都用更具代表性的字段覆盖了这一点。
  • 为所有模型设置了natural_key.dependencies列表以对Project和Task进行优先排序,对于其他所有模型,我都会收到“无法解析依赖项”错误。我认为this ticket与之相关,但是不确定如何跟踪此修复程序是否已经在我使用的Django 3.0.6中,我应该将其调直并正确飞行,或者如果我的Han Solo'这应该wooork'将很快获得奖励。 [更新:我确定它会在Django 3.1.1中提供,但我不确定它是否会解决我为自己创建的“无法解决依赖关系”错误。]

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)