【问题标题】:Django fixtures with specific data具有特定数据的 Django 固定装置
【发布时间】:2018-07-30 21:24:14
【问题描述】:

我有一个包含 3 个模型的应用,它们以父子方式相互引用:

class A(Model):
    # ...

class B(Model):
    a = ForeignKey(A)
    # ...

class C(Model):
    b = ForeignKey(B)
    # ...

在我的生产数据库中,我有数百个 A 类型的对象,下面还有数千个子对象。我现在只想为(特定的)少数对象创建一个固定装置。如果我运行这个命令,我的输出会变得很大:

python manage.py dumpdata ca_myapp -o /tmp/my_app_dump.json

但是,当我使用此命令限制输出时:

python manage.py dumpdata ca_myapp.A -o /tmp/myapp_dump.json --pks pk1, pk2, pk3

那么只有 A 对象被反序列化,而不是它们的子对象。如何轻松创建包含少量对象及其子对象的夹具文件?

【问题讨论】:

    标签: django fixtures django-fixtures


    【解决方案1】:

    我现在编写了一个 Django 命令,它首先检查我想要获取哪些 pks,以及它们有哪些子项,以获取所有相关对象。

    import logging
    import os
    
    from django.core.management import BaseCommand, call_command
    
    logger = logging.getLogger(__name__)
    
    A = {'pk1', 'pk2', 'pk3'}
    
    class Command(BaseCommand):
        def __init__(self, stdout=None, stderr=None, no_color=False):
            super().__init__(stdout, stderr, no_color)
            self.settings = None
            self.a = set()
    
        @property
        def tmp_dir(self):
            return '/tmp'
    
        def handle(self, *args, **options):
            self.settings = options.get('settings')
    
            # TODO: Make list of A an optional argument
            a_pks = A
            self.dump_objects('ca_myapp.A', pks=a_pks)
    
            b_pks = B.objects.filter(a_id__in=a_pks).values_list('pk', flat=True)
            self.dump_objects('ca_myapp.B', pks=b_pks)
    
            c_pks = C.objects.filter(b_id__in=b_pks).values_list('pk', flat=True)
            self.dump_objects('ca_myapp.C', pks=c_pks)
    
        def dump_objects(self, model_name: str, pks: set):
            if pks:
                call_command('dumpdata', model_name,
                             '--pks', ','.join(pks),
                             '--indent', '2',
                             '-o', os.path.join(self.tmp_dir, '{}.json'.format(model_name)),
                             '--settings', self.settings)
            else:
                logger.warning('No objects for model {} found'.format(model_name))
    

    【讨论】:

      【解决方案2】:

      来自Django documentation regarding dumpdata

      转储数据

      django-admin dumpdata [app_label[.ModelName] [app_label[.ModelName]...]]

      所以你的情况

      python manage.py dumpdata ca_myapp.A ca_myapp.B ca_myapp.C
      

      其他方法是使用排除

      --exclude 排除,-e 排除

      防止特定应用程序或模型(以 app_label.ModelName 的形式指定)被转储。如果 您指定模型名称,输出将限制为该模型, 而不是整个应用程序。您还可以混合应用程序名称 和型号名称。

      如果要排除多个应用程序,通过 --exclude 多个 一次


      如果我没有正确理解问题并且您询问是否可以只选择几个 pk 并遵循它们目前无法使用 dumpdata 的关系, 但您可以轻松地准备好您的数据库,以仅保存必要的数据。

      【讨论】:

      • 感谢 iklinac。我已经看到了这些选项,但它们并不能满足我的需要。我确实只需要选择几个 pk 并关注他们的关系。
      • @physicalattraction 请阅读我回复的第二部分,最简单的方法是在转储数据之前准备您的数据库,还有一个实用程序github.com/davedash/django-fixture-magic 似乎可以将转储数据扩展到您的要求,不确定是否它仍然被维护。
      • 不幸的是,在转储之前准备我的数据库是不可能的,因为它是一个生产数据库。我目前编写了一个脚本来获取我需要的所有 uuid,并使用正确的 --pks 标志调用这个命令,这个列表可以增长到数千个。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-29
      • 2011-04-29
      • 2013-09-02
      • 1970-01-01
      • 1970-01-01
      • 2012-02-18
      相关资源
      最近更新 更多