Skip to main content
 首页 » 编程设计

python之使用 Django 中的新用户字段获取并保存 QuerySet 的副本

2024年08月26日31softidea

我有很多模型,每个模型都有一个用户字段。每次注册新用户时,我都想复制这些模型的 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)