Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Django尝试在save()上插入而不是更新_Django_Django Models - Fatal编程技术网

Django尝试在save()上插入而不是更新

Django尝试在save()上插入而不是更新,django,django-models,Django,Django Models,我有一个模型 class DeviceAdmin(models.Model): dev_id = models.AutoField(db_column='dev_id', primary_key=True) ... 视图可定位对象: device = DeviceAdmin.objects.get(uuid=uuid) 然后它会做出一些改变(或者可能不会) 然后尝试保存任何更改: device.save() device = DeviceAdmin.objects.get(uuid

我有一个模型

class DeviceAdmin(models.Model):
    dev_id = models.AutoField(db_column='dev_id', primary_key=True)
...
视图可定位对象:

device = DeviceAdmin.objects.get(uuid=uuid)
然后它会做出一些改变(或者可能不会)

然后尝试保存任何更改:

device.save()
device = DeviceAdmin.objects.get(uuid=uuid)
device.save()
这里是Django尝试插入另一行而不是更新的地方,导致DB错误

django.db.utils.IntegrityError: duplicate key value violates unique constraint 
有一种类似的解决方案:

一旦我将主键字段设置为自动字段,问题就消失了

但是,我的主键已经是一个自动字段

因此,我使用调试器逐步完成了django代码,并在文件
…site packages\django\models\base.py
中为其提供资金:

    # If possible, try an UPDATE. If that doesn't update anything, do an INSERT.
    if pk_set and not force_insert:
        base_qs = cls._base_manager.using(using)
        values = [(f, None, (getattr(self, f.attname) if raw else f.pre_save(self, False)))
                  for f in non_pks]
        forced_update = update_fields or force_update
        updated = self._do_update(base_qs, using, pk_val, values, update_fields,
                                  forced_update)
        if force_update and not updated:
            raise DatabaseError("Forced update did not affect any rows.")
        if update_fields and not updated:
            raise DatabaseError("Save with update_fields did not affect any rows.")
    if not updated:
        if meta.order_with_respect_to:
            # If this is a model with an order_with_respect_to
            # autopopulate the _order field
            field = meta.order_with_respect_to
            filter_args = field.get_filter_kwargs_for_object(self)
            order_value = cls._base_manager.using(using).filter(**filter_args).count()
            self._order = order_value

        fields = meta.local_concrete_fields
        if not pk_set:
            fields = [f for f in fields if f is not meta.auto_field]

        update_pk = meta.auto_field and not pk_set
        result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
        if update_pk:
            setattr(self, meta.pk.attname, result)
    return updated
看起来,如果没有任何更改(因此更新不起任何作用),那么它将尝试插入一条重复的记录

我通过在
get
之后添加一个save来测试这一点:

device = DeviceAdmin.objects.get(uuid=uuid)
device.save()
它正试图插入一个副本

这是否意味着,我的代码需要跟踪对象是否必须保存到DB

解决这个问题最简单的方法是什么


更新:

作为测试,我在找到带有
get
的对象后立即进行
save
,没有任何更改:

device.save()
device = DeviceAdmin.objects.get(uuid=uuid)
device.save()
Django应该知道该对象是一个现有对象。然而,它试图插入一个副本

同样,创建一个新对象并调用
save
两次:

device = DeviceAdmin(...) # create a new object (it has null `dev_id`)
device.save()             # insert the new object into DB; get 'dev_id'
                          #   for the newly inserted record
device.save()             # This shouldn't do anything!

第二次
保存
尝试插入一个副本-我可以看到,如果我使用调试器单步执行django代码。

您肯定在字段定义方面有一些问题(可能出于某种原因,您应该添加
unique=True
)。但是,如果您仍然无法确定更新失败的原因(
INSERT
如果
UPDATE
返回“未更新行”),那么您可以使用
.save(force\u UPDATE=True)
作为最后手段

您的代码中也存在一些不一致之处:

  • 字段名为
    dev\u id
    ,但您正在筛选中使用
    uuid
    .get(uuid=uuid)
    )。是否确定已正确设置主键字段的名称
  • AutoField
    假设使用
    Integer
    字段,因此在
    get_prep_value
    期间,它会执行
    int(self.pk)
    操作,不会在
    uuid.uuid
    实例上抛出任何错误,但如果db内部使用
    varchar
    字段,则会将其转换回具有错误值的str(例如,
    str(int(uuid.uuid('579aea21-49a4-4819-90ec-a192014b4a44'))=='1164471980706669671892400511866020514372'
    ),这就是问题的原因。请尝试使用
    UUIDField
    CharField
    ):
导入uuid
类模型(models.Model):
dev_id=models.UUIDField(主键=True,空白=True,默认=uuid.uuid4)
#或者,如果您的列是varchar:
类模型(models.Model):
def dev_id_default():
如果需要具有以下参数的值,请返回uuid.uuid4().hex#或str(uuid.uuid4())`-`
dev\u id=models.CharField(主键=True,空格=True,默认值=dev\u id\u默认值,最大长度=33\u或36)

看起来您正在使用DB中预先存在的表:尝试为生成的模型使用代码。

在我的例子中,我的类的顶部有一个唯一的CharField。在我看来,Django有时会将其视为主键,有时则不会——其结果是有时没有意识到它应该更新而不是插入


添加一个显式的
id=AutoField(primary\u key=True)
为我解决了这个问题。

你的序列有没有搞乱?你试过这种方法吗(尽管我不确定它是否能解决):
device.save(update\u fields=['field'])
或者你可以使用
device=DeviceAdmin.objects.filter(uuid=uuid.update(field=value)
序列很好。我检查过了。您的诊断不正确。
更新的
标志只有在没有行匹配的情况下才会为假,即PK不存在。如果PK存在,则不会为假,但值设置为与现在相同。从您的另一个问题中,我知道您在数据库中已经有表了。您能显示什么吗如果您为您的模型使用由
manage.py inspectdb
生成的代码,并且您可以始终退回到为.save使用
.save(force\u update=True)
for.save(force\u update=True),如果DB返回无更改,它仍将覆盖它,还是不会在幕后采取任何操作。