在 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_modelsave_formset,但无论错误是什么,它都是在调用这些函数之前产生的。我 运行 python manage.py runserver 中的 shell 甚至没有显示任何错误消息。

models.pyadmin.py还有很多其他型号,其中none有同样的问题。其中一些模型甚至有自己的内联。

我真的很纳闷。我试图了解上面显示的代码部分与其余代码之间的区别,但我找不到它。我知道保存过程在我几天前添加付款操作之前有效,而且我几乎可以肯定我没有更改订单和商品模型中的任何内容(不过我会检查一下,以确保万无一失)。在这一点上,我不确定我是否理解保存过程,或者代码有什么问题。

编辑:我找不到订单和文章模型及其管理员对应项的重大更改。

显然,整个问题都出在每个模型ID的editable=settings.IS_DEV设置上。我不知道为什么,但设置 editable=False 解决了问题。

我注意到我在生产服务器上从未遇到过这个问题,只有在标记为开发的服务器上遇到过。幸运的是,能够设置一个特定的 ID 只在非常有限的情况下有用,所以我不会错过它,但我觉得我只是用一个不那么烦人的问题来交换。如果有人有更好的解决方案,我很乐意改变主意并将其视为该问题的答案。