即使在“保存”调用之后,Django 对象也没有保存

Posted

技术标签:

【中文标题】即使在“保存”调用之后,Django 对象也没有保存【英文标题】:Django object not saving even after "save" call 【发布时间】:2013-06-22 19:16:28 【问题描述】:

我真的很茫然,因为这根本没有意义。我调用保存/创建一个对象,它不会出现在管理站点中。我什至用 SQLite Viewer 程序检查了 SQLite 数据库,它再次显示该项目尚未保存。

这是保存Data对象的代码:

        data = Data(represents=field, for_entry=entry, value="This can be anything")
        # field is a DataField db object and entry is a Entry db object (see model below and paragraph)
        print("B4", data) #<---- Shows that Data has not been assigned an ID/pk
        data.save()
        print("8ER: ", data) #<--- Shows that Data has been assigned an ID/pk

从我的 cmets 中可以看出,我知道在 save 调用之后为 Data 对象分配了一个 ID,我认为这意味着它有效。任何地方都不会抛出错误。 fieldentry 都是。每一个似乎都很好,因为它们有正确的 ID,用[table name].objects.get(id=...) 检索,我可以保存/编辑它们并且它们的保存更改。

更奇怪的是,这个函数中的确切代码在这个函数工作之前就被调用了。

这是我的model.py(我取出了一些函数让它更短):

class Entry(models.Model):
    parent = models.ForeignKey('Entry', blank = True, null = True, default=None) #  The entry this subs. Is left blank for top level entries.
    id_number = models.CharField(max_length=20)
    visible = models.BooleanField()
    data_field = models.ForeignKey('DataField', default=1)  # The field that this entire entry falls under. REDUNDANT BUT NECISSARY

    def __str__(self):
        return str(self.id)+ "-" + str(self.id_number) 

class DataField(models.Model):
    parent = models.ForeignKey('DataField', related_name='parent field', null=True, blank=True, default=1)
    order = models.IntegerField()
    multiple_entries = models.BooleanField(default=True)
    DATA_TYPES = (('t', 'Text'), ('d', 'Date'), ('l', 'List'), ('o', 'Option'), ('b', 'Boolean'), ('f', 'Foreign Key'), ('r', 'Root'), ('bb', 'Branch'), ('i', 'Image'), ('ff', 'File'), ('h', 'Holder'), ('bt', 'Big Text'))  # A number means it is a foreign key. Should go off title.
    foreign_source = models.ForeignKey('DataField', null=True, blank=True) #  Points to DATA FIELD WHO'S MATCHING DATA WILL MAKE UP THE OPTIONS
    data_type = models.CharField(max_length=2, choices=DATA_TYPES, default='t', null=True, blank=True)
    title = models.CharField(max_length=100, null=True, blank=True)
    visibility = models.BooleanField(default=False)

    def __str__(self):
        return str(self.id) + "-" + str(self.title)

    def __eq__(self, other):
        if not isinstance(other, DataField):
            return False
        if self.data_type == 'h':
            return self.title == other.title
        return self.id == other.id


class Data(models.Model):
    represents = models.ForeignKey('DataField')
    for_entry = models.ForeignKey('Entry', null=True)
    value = models.CharField(max_length=1000000)

    def __str__(self):
        return self.represents.title + "-" + str(self.for_entry.id) + "-" + str(self.value) + "-" + str(self.id)

我可能遗漏了一些明显的东西,或者您可能需要比我提供的更多信息来修复它。如果信息不足,请发表评论并索取更多信息,或仅列出可能发生的问题。

【问题讨论】:

AUTOCOMMIT 是否偶然设置为 false,而另一个函数正在执行显式提交? 请提供您正在执行的代码,即 save() 方法失败的 sn-p。如果我们能看到 save() 的确切参数是什么,那就更容易了。 @pkacprzak 不幸的是,它们被设置在程序的一个完全不同的部分(与其他几个部分交互。因此,可能有 60 多行代码)。从我能够做的每一个测试来看,它们似乎是 DateField 和 Entry 类的有效数据库对象。最后一个参数(值)可以是基本字符串,但它仍然不起作用。 我的建议是启用日志记录并检查日志文件,因为生成的每个 SQL 语句都可以记录在那里。然后你可以看到 Django 是如何尝试保存的。 docs.djangoproject.com/en/dev/topics/logging 这没有意义。你检查过日志吗?正在生成的语句是什么?你是说它没有被生成还是没有被发送到数据库? 【参考方案1】:

我有同样的问题。我通过将对象分配给一个新变量来解决它,进行更改并保存新变量:

    location = self.location  # self.location is set by other methods
    location.is_active = True
    location.save()

【讨论】:

【参考方案2】:

在需要更新的对象中使用django refresh_from_db()函数。

【讨论】:

格式化您的代码并进行更多描述,以便您的答案更清晰【参考方案3】:

我在进行单元测试时遇到了类似的问题,并且遇到了一个错误,似乎保存方法不起作用 --> 如下

p = MyModel.objects.get(pk=myparam)
self.assertEqual(p.my_attr, value) 
myfunc()  # Code that changed the same object p is referencing
self.assertEqual(p.my_attr, new_value)

即使我将引用的对象更改为新值,然后对对象执行 .save(),上述操作也失败了。

为了解决这个问题,我不得不将 p 重新分配给 MyModel 对象。我在单元测试中的固定代码看起来像这样。

p = MyModel.objects.get(pk=myparam)
self.assertEqual(p.my_attr, value) 
myfunc()  # Code that changed the same object p is referencing
p = MyModel.objects.get(pk=myparam)
self.assertEqual(p.my_attr, new_value)

变量指向内存中的旧位置似乎是一个问题,但我 5 个月前才开始编程,所以我有点过头了 :) 如果有人能解释原因,我将非常感谢反馈这正在发生,因为我仍然很难过。

如果您真的不认为 save 方法正在执行,您可以通过覆盖 save 方法并添加打印语句来进行完整性检查。它可能类似于以下内容:

class MyModel(models.Model):
    attr = models.IntegerField(default=0)

    def save(self, *args, **kwargs):
        super(MyModel, self).save(*args, **kwargs)
        print('Did this attribute update? (attr):', self.attr)
        print('Save method executed!')

编辑:根据内存位置理论,我做了这个简单的例子:

In [3]: a = 1
In [4]: b = a
In [5]: hex(id(a))
Out[5]: '0x100240280'
In [6]: hex(id(b))
Out[6]: '0x100240280'
In [7]: a = 2
In [8]: b
Out[8]: 1
In [9]: hex(id(a))
Out[9]: '0x1002402a0'
In [10]: hex(id(b))
Out[10]: '0x100240280'

仍然很想听听任何人的想法。

【讨论】:

【参考方案4】:

尝试手动提交。我不知道还有什么建议。

from django.db import transaction

@transaction.commit_manually
def viewfunc(request):
    ...
    data.save()
    transaction.commit()

【讨论】:

感谢您的所有帮助。我刚刚使用最新版本的python(我使用python3.2)卸载并重新安装django到一个新的vertualenv。然后我复制了我所有的代码。我不知道为什么,但它奏效了。也许我在设置文件中搞砸了。再次感谢! 嗯,我很高兴它对你有用。猜猜我们永远不会知道为什么它不起作用......

以上是关于即使在“保存”调用之后,Django 对象也没有保存的主要内容,如果未能解决你的问题,请参考以下文章

Django 给出“CSRF 令牌丢失或不正确”。即使在 POST 调用中传递它之后也会出错

保存文件时没有过早关机的可能性会破坏它

即使在成功消息之后,单选按钮的数据也没有保存在 Postgres DB 中

即使在安装 cors-headers 之后,Django cors 也会出错

即使在 [[UIPickerView alloc] init] 之后设置了委托,也没有调用 UIPickerView 委托方法

即使缺少所需的值,Django 验证也会调用 clean()