Django如何为单个模型导出数据?

182

我能否在Django中仅对单个模型执行dumpdata,而不是整个应用程序?如果可以,如何操作?

对于一个应用程序,操作方式如下:

python manage.py dumpdata myapp

然而,我想要一些特定的模型被转储,例如"myapp.mymodel"。原因是,我在同一个应用程序中有一些巨大的数据集(超过300万条记录),我不想进行转储。


1
我觉得你的问题不太容易理解。你想要将一个 SQL 转储加载到你的数据库中吗?还是你想对一个模型实例执行某种 toString() 操作? - Leonard Ehrenfried
13个回答

301

从1.1版本开始,Django dumpdata管理命令允许你从单个表中导出数据:

./manage.py dumpdata myapp1 myapp2.my_model

你也可以在命令行上分开多个应用程序和模型。以下是规范定义:

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

20
聚集,不理解针对几乎两年的帖子的负面投票。此外,即使在v1.1中也可以正常使用上述代码。新版本中的新功能并不意味着旧版答案无效。 - simplyharsh
1
我该如何将这些数据添加到应用程序的另一个实例中? - aguilarpgc
5
使用dumpdata命令后加上标志--indent 4可以生成易读的JSON格式。 - Valery Ramusik

118

正如所指出的,你不能通过 Django 1.0 中的 manage.py 命令来完成此操作。但你可以使用脚本导出 JSON 文件,并使用 loaddata 加载它:

from django.core import serializers
from myproject.myapp import models
data = serializers.serialize("json", models.MyModel.objects.all())
out = open("mymodel.json", "w")
out.write(data)
out.close()

7
这是一个很棒的脚本,因为如果你愿意,你甚至可以更加细致地筛选。如果你在上面第三行使用.filter(...),你就可以仅仅输出你想要的具体记录。 - Gringo Suave
有没有办法使用此方法转储多个对象的多对多字段值? - dfrankow
我想我会尝试使用https://github.com/davedash/django-fixture-magic。 - dfrankow

21

针对特定文件的特定模型:

python manage.py dumpdata app_label.ModelName > specific_file.json

并将其加载到另一个应用程序中:首先将文件移动或复制到您想要处理它的应用程序中,然后:

python manage.py loaddata specific_file.json

12

从Django模型中以JSON格式获取所有数据。

语法:

python manage.py dumpdata app_name.model_name

比如说,在 Django 中从默认的认证应用程序中的 group_permission 模型中转储数据。

python manage.py dumpdata auth.group_permission

请查看控制台以获取输出。


6

我认为你在问题中已经提供了解决方案。你可以按照以下方式转储单个模型:

./manage.py dumpdata myapp.my_model

我在发布前尝试过,但没有成功。我使用的是Django 1.0版本。我还尝试了myapp.models.mymodel。 - nategood

5

为了成功,我必须重复说两遍,并且两次指定模型,例如:

./manage.py dumpdata myapp2.my_model myapp2.my_model

如果我只说了这段话
./manage.py dumpdata myapp2 myapp2.my_model

尽管我已经指定了my_model,但是所有的模型都淹没在了我的app2中。


3

对于像我这样的Django和Python新手,这可能会很有用:

如果你只想转储单个行(显然是单个表的),例如你的应用程序名为"merchant",模型也被命名为“Merchant”,通常使用全限定名称导入它就像这样: merchant.models.Merchant ; 不要试图使用这个名称。语法如下:

# only dumps the merchant with id = 123, pretty printed
python manage.py dumpdata merchant.Merchant --pks 123 --indent 2

2
如果您只想转储模型的特定对象,可以使用dumpdata命令的--pks可选参数。

--pks PRIMARY_KEYS 仅输出由逗号分隔的主键列表指定的对象。仅在转储一个模型时可用。默认情况下,输出模型的所有记录。


2

将其写入特定文件:

python manage.py dumpdata app_label.ModelName app_label.ModelName2 > fixtures/specic.json

1

我认为接受的答案已经过时了,需要在2023年进行详细的更新。

我曾经遇到过类似的问题,需要为来自不同应用程序的特定模型创建固定装置,并具有特定的ID。此外,我只需要为所有模型创建一个装置,这样我们就不必加载单独的装置,而是只需加载一个装置即可。

我通过创建自定义命令来完成所有这些操作,该命令在内部调用dumpdata以获取每个特定模型的特定ID,如下所示:

products/models.py

class Product(models.Model):
    name = models.CharField(max_length=200)
    price = models.DecimalField(max_digits = 5, decimal_places = 2)

reviews/models.py

class Review(models.Model):
    title = models.CharField(max_length=200)        
    text = models.TextField()
    timestamp = models.DateTimeField(auto_now_add=True)
    rating = models.PositiveIntegerField(default=0)
    product = models.ForeignKey(Product, on_delete=models.CASCADE)

    def natural_key(self):
       return self.title, self.timestamp


class Response(models.Model):
    text = models.TextField()
    timestamp = models.DateTimeField(auto_now_add=True)

以下是创建特定应用程序中不同模型的一个fixtures并具有特定ID的命令:

generate_fixture.py

from django.core.management import BaseCommand, call_command
from io import StringIO
import json

class Command(BaseCommand):
    def add_arguments(self, parser):
        parser.add_argument('id', type=int, help='Primary Key Of Product')

    def handle(self, *args, **options):
        id = options.get('id')

        if product := Product.objects.filter(id=id).first():
            product_fixture = self.get_fixture('products.Product', str(id))

            review_ids = list(
                Review.objects.filter(product__id=id).values_list('id',flat=True)
            )
            review_ids = ','.join([str(review_id) for review_id in review_ids])
            review_fixture = self.get_fixture('reviews.Review', review_ids)

            output = [json.loads(product_fixture)]
            output.extend(json.loads(review_fixture))
            with open('model_fixtures.json', "w") as file:
                json.dump(output, file)
        else:
            print(f"Product with id {id} does not exists!")

    def get_fixture(self, label, pks):
        args = ['dumpdata', '--natural-foreign', '--natural-primary', label]
        with StringIO() as buffer:
            call_command(*args, pks=pks, stdout=buffer)
            data = buffer.getvalue()
        return data

现在你可以像这样使用id运行命令:

python manage.py generate_fixture 50

模型的fixture将会生成一个fixture文件,可以通过以下方式加载:

python manage.py loaddata model_fixtures.json

注意:代码未经过测试。


这很有用,谢谢!我从中修改的代码基本上是有效的,除了get_fixture的第一个参数需要是“self”,我们还需要注意输出的格式,以便它能够与loaddata命令一起使用。https://dev59.com/HrHma4cB1Zd3GeqPQL-r#54617472 - Mike S
感谢 @MikeS 指出了拼写错误。如果您认为还有其他需要更改的地方,请随意编辑答案。 - Ahtisham

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