我有很多模型,每个模型都有一个用户字段。每次注册新用户时,我都想复制这些模型的 user.id = 1 实例,并在用户字段中使用新用户 ID 保存它们。我读过可以通过将 pk 设置为 None 来制作模型实例的副本,所以这是我首先尝试做的。我试图在 QuerySet 上执行此操作,因为某些表有很多实例(某些模型超过 1000 个,但大多数少于 100 个)。
def copy_tables(user):
# This approach fails with "Voice has no field named 'pk'"
voice = Voice.objects.filter(user=1).update(
pk=None, user=user.id, right_answers=0, wrong_answers=0)
我也试过使用 copy.deepcopy(Voice.objects.filter(user=1)) 但是调用 update() 仍然在改变数据库中的原始表。
def copy_tables(user):
copy.deepcopy(Voice.objects.filter(user=1)).update(
user=user.id, right_answers=0, wrong_answers=0)
# This test throws an error because the original models have been changed
assert Voice.objects.filter(user=1).first()
我是不是错过了一些其他的方式来做到这一点?另外,我认为所有模型实例都有一个主键,pk,它是由 Django 自动设置的。不是这样吗?
请您参考如下方法:
在模型实例上调用save 方法时,Django 通过检查它是否具有主键 (ref.) 来确定是否必须插入或更新它。
因此,如果您在模型实例上将 PK 设置为 None,Django 将尝试将其作为新行添加到数据库中。
演示:
# Retrieve the object belonging to the user whose ID is 1.
# Note that you cannot use "user=1", you need to tell Django you
# are querying by id, using "user__id=1" .
obj = MyModel.objects.get(user__id=1)
# Set PK to None so that Django thinks it is not save in the database.
obj.pk = None
# Save to insert it.
obj.save()
如果你有多个对象,你可以使用 bulk_create获得性能:
voices = Voice.objects.filter(user__id=1)
new_voices = []
for voice in voices:
voice.pk = None
voice.user = user
right_answsers = 0
wrong_anwsers = 0
new_voices.append(voice)
Voice.objects.bulk_create(new_voices)
