在 Django 中使用内联保存模型
Saving a model with inlines in Django
这似乎是一个很简单的问题,但我真的想不通这是怎么回事。我在理解 Django 管理站点上的保存过程时遇到了一些问题。情况是这样的,尽量简化:
models.py
import uuid
from django.conf import settings
from django.db import models
class BaseModel(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=settings.IS_DEV)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
class Order(BaseModel):
[various properties and functions]
class Article(BaseModel):
order = models.ForeignKey(Order, null=True, on_delete=models.CASCADE, related_name='articles')
[various properties and functions]
class PaymentOperation(BaseModel):
order = models.ForeignKey(Order, null=True, on_delete=models.CASCADE)
[various properties and functions]
admin.py
from django.conf import settings
from django.contrib import admin
from models import Order, Article, PaymentOperation
class BaseModelAdmin(admin.ModelAdmin):
readonly_fields = ['created', 'modified']
if not settings.IS_DEV:
readonly_fields.append('id')
class ArticleInline(admin.TabularInline):
fields = ['id', ...]
readonly_fields = ['id', ...]
can_delete = False
extra = 0
max_num = 0
[more code]
class PaymentOperationInline(admin.TabularInline):
fields = ['id', ...]
readonly_fields = ['id', ...]
can_delete = False
extra = 0
max_num = 0
[more code]
class OrderAdmin(BaseModelAdmin):
readonly_fields = BaseModelAdmin.readonly_fields + [...]
fieldsets = [...]
inlines = [ArticleInline, PaymentOperationInline]
[more code]
class ArticleAdmin(BaseModelAdmin):
readonly_fields = BaseModelAdmin.readonly_fields + [...]
fieldsets = [...]
[more code]
这是主要结构,但我不确定它是否足以产生问题。我不想用数百行代码来解决这个问题。如有必要,我会尝试更具体。
Order 和 Article 模型中的一些字段是可编辑的,而 PaymentOperation 模型中的所有字段都是只读的。
如果我从文章的管理页面编辑一篇文章,它会完美运行。另一方面,如果我尝试编辑一个订单,然后保存它,该页面的行为会很奇怪。订单未保存,页面顶部出现一条错误消息,显示“请更正以下错误”。所有可编辑和只读字段均保持不变。页面底部的两个内联状态更差。所有只读字段都重置为默认值(如果可用)或为空,并且所有 ID 都不同。内联文章的可编辑字段保持不变。在我看来,该页面正在尝试创建新条目,而不是编辑旧条目。
我尝试一次注释掉 OrderAdmin
声明中的内联,但没有效果。注释掉两者可以让我正确保存订单。
我也试过在OrderAdmin
中添加save_model
和save_formset
,但无论错误是什么,它都是在调用这些函数之前产生的。我 运行 python manage.py runserver
中的 shell 甚至没有显示任何错误消息。
models.py
和admin.py
还有很多其他型号,其中none有同样的问题。其中一些模型甚至有自己的内联。
我真的很纳闷。我试图了解上面显示的代码部分与其余代码之间的区别,但我找不到它。我知道保存过程在我几天前添加付款操作之前有效,而且我几乎可以肯定我没有更改订单和商品模型中的任何内容(不过我会检查一下,以确保万无一失)。在这一点上,我不确定我是否理解保存过程,或者代码有什么问题。
编辑:我找不到订单和文章模型及其管理员对应项的重大更改。
显然,整个问题都出在每个模型ID的editable=settings.IS_DEV
设置上。我不知道为什么,但设置 editable=False
解决了问题。
我注意到我在生产服务器上从未遇到过这个问题,只有在标记为开发的服务器上遇到过。幸运的是,能够设置一个特定的 ID 只在非常有限的情况下有用,所以我不会错过它,但我觉得我只是用一个不那么烦人的问题来交换。如果有人有更好的解决方案,我很乐意改变主意并将其视为该问题的答案。
这似乎是一个很简单的问题,但我真的想不通这是怎么回事。我在理解 Django 管理站点上的保存过程时遇到了一些问题。情况是这样的,尽量简化:
models.py
import uuid
from django.conf import settings
from django.db import models
class BaseModel(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=settings.IS_DEV)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
class Order(BaseModel):
[various properties and functions]
class Article(BaseModel):
order = models.ForeignKey(Order, null=True, on_delete=models.CASCADE, related_name='articles')
[various properties and functions]
class PaymentOperation(BaseModel):
order = models.ForeignKey(Order, null=True, on_delete=models.CASCADE)
[various properties and functions]
admin.py
from django.conf import settings
from django.contrib import admin
from models import Order, Article, PaymentOperation
class BaseModelAdmin(admin.ModelAdmin):
readonly_fields = ['created', 'modified']
if not settings.IS_DEV:
readonly_fields.append('id')
class ArticleInline(admin.TabularInline):
fields = ['id', ...]
readonly_fields = ['id', ...]
can_delete = False
extra = 0
max_num = 0
[more code]
class PaymentOperationInline(admin.TabularInline):
fields = ['id', ...]
readonly_fields = ['id', ...]
can_delete = False
extra = 0
max_num = 0
[more code]
class OrderAdmin(BaseModelAdmin):
readonly_fields = BaseModelAdmin.readonly_fields + [...]
fieldsets = [...]
inlines = [ArticleInline, PaymentOperationInline]
[more code]
class ArticleAdmin(BaseModelAdmin):
readonly_fields = BaseModelAdmin.readonly_fields + [...]
fieldsets = [...]
[more code]
这是主要结构,但我不确定它是否足以产生问题。我不想用数百行代码来解决这个问题。如有必要,我会尝试更具体。
Order 和 Article 模型中的一些字段是可编辑的,而 PaymentOperation 模型中的所有字段都是只读的。
如果我从文章的管理页面编辑一篇文章,它会完美运行。另一方面,如果我尝试编辑一个订单,然后保存它,该页面的行为会很奇怪。订单未保存,页面顶部出现一条错误消息,显示“请更正以下错误”。所有可编辑和只读字段均保持不变。页面底部的两个内联状态更差。所有只读字段都重置为默认值(如果可用)或为空,并且所有 ID 都不同。内联文章的可编辑字段保持不变。在我看来,该页面正在尝试创建新条目,而不是编辑旧条目。
我尝试一次注释掉 OrderAdmin
声明中的内联,但没有效果。注释掉两者可以让我正确保存订单。
我也试过在OrderAdmin
中添加save_model
和save_formset
,但无论错误是什么,它都是在调用这些函数之前产生的。我 运行 python manage.py runserver
中的 shell 甚至没有显示任何错误消息。
models.py
和admin.py
还有很多其他型号,其中none有同样的问题。其中一些模型甚至有自己的内联。
我真的很纳闷。我试图了解上面显示的代码部分与其余代码之间的区别,但我找不到它。我知道保存过程在我几天前添加付款操作之前有效,而且我几乎可以肯定我没有更改订单和商品模型中的任何内容(不过我会检查一下,以确保万无一失)。在这一点上,我不确定我是否理解保存过程,或者代码有什么问题。
编辑:我找不到订单和文章模型及其管理员对应项的重大更改。
显然,整个问题都出在每个模型ID的editable=settings.IS_DEV
设置上。我不知道为什么,但设置 editable=False
解决了问题。
我注意到我在生产服务器上从未遇到过这个问题,只有在标记为开发的服务器上遇到过。幸运的是,能够设置一个特定的 ID 只在非常有限的情况下有用,所以我不会错过它,但我觉得我只是用一个不那么烦人的问题来交换。如果有人有更好的解决方案,我很乐意改变主意并将其视为该问题的答案。