【问题标题】:Using django orm to update a table without deleting relations使用 django orm 更新表而不删除关系
【发布时间】:2018-06-29 03:17:22
【问题描述】:

我有这两个相关的 django 模型

class Item(models.Model):
    item_nbr = models.IntegerField(primary_key=True)
    created = models.DateTimeField(auto_now_add=True)
    item_nbr_desc = models.CharField(max_length=155)

class SetItem(models.Model):
    set_id = models.CharField(primary_key=True, default='', max_length=12)
    set_nbr = models.IntegerField()
    items = models.ForeignKey(Item)

我正在运行一个脚本(定期)从另一个数据库中读取Item,并使用该数据框来更新 django 数据库项表。我正在使用 django orm 框架来制作与 django 数据库的接口

script.py

from app.models import Item

item_table = pd.read_sql(__) 
item_table = some_transformations(item_table.copy())
#I remove all the Items that will be updated 
Item.objects.filter(item_nbr__in=item_table.item_nbr.unique()).delete()
item_table_records = item_table.to_dict('records')
item_instances = []
fields = item_table.keys()
for record in item_table_records:
    kwargs = {
             field: record[field] for field in fields
             }
    item_instances.append(Item(**kwargs))
Item.objects.bulk_create(item_instances) # update the new rows 

问题是setItem 表在我每次删除相关项目时都会被删除(因为on_delete=models.CASCADE 行为)。我想更新items 而不是删除setItem 相关行,并且我不想更改on_delete 默认行为,因为只有在这个脚本中我需要上传整个表,我可能想要在另一个上下文中删除Item,我希望级联行为有效。我能做些什么?是否有批量更新功能可以对表执行非破坏性更新?

【问题讨论】:

    标签: python mysql sql django orm


    【解决方案1】:

    您可以一一更新项目:

    items_by_pk = Item.objects.in_bulk(item_table.item_nbr.values)
    for record in item_table.to_dict('records'):
        item = items_by_pk[record['item_nbr']]
        for field, value in record:
            setattr(item, field, value)
        item.save()
    

    【讨论】:

    • items_by_pk = Item.objects.in_bulk(item_table.item_nbr) 给了我一个ValueErrorValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
    • 性能真的很差!!考虑到我的Item 表有超过 300K 的寄存器。我需要一个“批量”解决方案:(
    • 我刚刚修复了 ValueError。您需要确保在事务中将查询批处理在一起,但它仍然会很慢。你能写一个更快的原始 SQL 查询吗?
    • 我正在尝试阅读这个问题的答案stackoverflow.com/questions/12661253/…
    【解决方案2】:

    添加@transaction.atomicdecorator,并使用save() 方法,您将获得“批量”更新,而无需删除项目表。

    from django.db import transaction
    
    @transaction.atomic
    def item_update(item_table):
        items_by_pk = Item.objects.in_bulk(item_table.item_nbr.values)
        for record in item_table.to_dict('records'):
            item = items_by_pk[record['item_nbr']]
            for field, value in record:
               setattr(item, field, value)
            item.save()
    

    source

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-27
      • 1970-01-01
      • 2010-11-04
      • 1970-01-01
      相关资源
      最近更新 更多