我更新了 Django 2.2 及更高版本的 OmriToptix答案。
在 Django 2.0 中:
Model._meta.virtual_fields 属性被移除。
所以,新的序列化器和反序列化器:
import json
from django.contrib.contenttypes.fields import GenericForeignKey
from django.utils import six
from django.core.serializers.json import Serializer as JSONSerializer
from django.core.serializers.python import Deserializer as \
PythonDeserializer, _get_model
from django.core.serializers.base import DeserializationError
import sys
class Serializer(JSONSerializer):
def get_dump_object(self, obj):
dumped_object = super(JSONSerializer, self).get_dump_object(obj)
if hasattr(obj, 'natural_key'):
dumped_object['pk'] = obj.natural_key()
for field in obj._meta.get_fields():
if type(field) == GenericForeignKey:
content_object = getattr(obj, field.name)
dumped_object['fields'][field.name + '_natural_key'] = content_object.natural_key()
return dumped_object
def Deserializer(stream_or_string, **options):
if not isinstance(stream_or_string, (bytes, six.string_types)):
stream_or_string = stream_or_string.read()
if isinstance(stream_or_string, bytes):
stream_or_string = stream_or_string.decode('utf-8')
try:
objects = json.loads(stream_or_string)
for obj in objects:
Model = _get_model(obj['model'])
if isinstance(obj['pk'], (tuple, list)):
o = Model.objects.get_by_natural_key(*obj['pk'])
obj['pk'] = o.pk
for field in Model._meta.get_fields():
if type(field) == GenericForeignKey:
natural_key_field_name = field.name + '_natural_key'
if natural_key_field_name in obj['fields']:
content_type = getattr(o, field.ct_field)
content_object_by_natural_key = content_type.model_class().\
objects.get_by_natural_key(*obj['fields'][natural_key_field_name])
obj['fields'][field.fk_field] = content_object_by_natural_key.pk
del obj['fields'][natural_key_field_name]
for obj in PythonDeserializer(objects, **options):
yield obj
except GeneratorExit:
raise
except Exception as e:
six.reraise(DeserializationError, DeserializationError(e), sys.exc_info()[2])
然后,在您的 settings.py 中,设置此配置:
SERIALIZATION_MODULES = {
"json": "path.to.serializer_file"
}
现在,您可以使用:
python3 manage.py dumpdata --natural-foreign --natural-primary > dump.json
其他方式,如果您需要转储一些数据(过滤查询集),您可以从代码中进行:
from path.to.serializers import Serializer, Deserializer
# Serialize
registers = YourModel.objects.filter(some_attribute=some_value)
dump = Serializer().serialize(registers, use_natural_foreign_keys=True, use_natural_primary_keys=True)
# Deserialize
for deserialized_object in Deserializer(dump, use_natural_foreign_keys=True, use_natural_primary_keys=True):
print(deserialized_object.object) # See here https://docs.djangoproject.com/en/2.2/topics/serialization/