更新Django模型对象的多个字段的有效方法

时间:2017-01-19 14:22:04

标签: python django

我正在尝试更新Django数据库中的用户。

提取的数据如下:

fetched_data = {
     'id': 1,
     'first_name': 'John',
     'last_name': 'Doe',
     'phone': '+32 12',
     'mobile_phone': '+32 13',
     'email': 'myemail@hotmail.com',
     'username': 'myusername'
}

我为用户提供了 id ,如下所示:

old_user = User.objects.get(pk=fetched_data['id'])

如果我按如下方式更新用户:

old_user.username = fetched_data['username']
old_user.first_name = fetched_data['first_name']
......
old_user.save()

它工作正常,但我不想为每条记录都这样做,因此我尝试了类似的东西:

for fetched_data_key in fetched_data:
    old_user.fetched_data_key = fetched_data['fetched_data_key']
    //old_user[fetched_data_key] = fetched_data['fetched_data_key'] --- I tried this way to
    old_user.save()

但这不起作用。任何想法如何在不对每条记录进行更新的情况下更新用户?

5 个答案:

答案 0 :(得分:13)

您可以更新数据库中的行而无需获取和反序列化它; update()可以做到。 E.g:

User.objects.filter(id=data['id']).update(email=data['email'], phone=data['phone'])

这将发出一个SQL update语句,并且比你帖子中的代码快得多。它永远不会获取数据或浪费时间创建User对象。

但是,您无法将大量更新数据发送到SQL数据库,并要求它一次性将其映射到不同的行。如果你需要一个非常快速的大规模更新,最好的办法是将数据插入一个单独的表中,然后update it form a select on that table。据我所知,Django ORM不支持这一点。

答案 1 :(得分:12)

如果使用.update()对象的QuerySet方法,则更简单:

my_id = fetched_data.pop('id')  # remove 'id' from `fetch_data`
                                # as it is not supposed to be updated

User.objects.filter(pk=my_id).update(**fetched_data)
#          unpack the content of `dict` ^

它将解包fetched_data dict的内容,并将User对象中的记录更新为{em> key 到fetched_data dict。由于您在pk上调用过滤器,因此它将始终返回单个记录。

答案 2 :(得分:5)

setattr(old_user, fetched_data_key, fetched_data['fetched_data_key'])

答案 3 :(得分:0)

如果您使用.update,则会出现问题,因为它不会发出 post_save pre_save 信号,因此,如果要使用任何信号数据发生任何变化,那么User.objects.filter(pk=fetched_data['id']).update(**kwargs)将无法正常工作。

因此,您可以使用setattr()更新字段,然后.save将保存该行,这将更新该行并发出信号。

old_user = User.objects.get(pk=fetched_data['id'])
for key, value in fetched_data.iteritems():
    setattr(old_user, key, value)
old_user.save()

答案 4 :(得分:0)

黑引号

def update_block(请求,ID):

a = RentedNumberBlock.objects.get(id=id)
b = RentedNumber.objects.filter(user=request.user)
c = a.rented_number.values_list('id', flat=True)
if request.POST:
    update = RentedNumberBlock.objects.get(id=id)
    update.name = request.POST['name']
    z = dict(request.POST)['rented_number']
    y = RentedNumber.objects.filter(id__in=z)
    update.rented_number.set(z)
    update.save()
    return HttpResponseRedirect('/block/')
return render(request, "block/update.html", {"a": a , "b": b, "c": c})