Django 1.11 admin:在管理员中创建OneToOne关系及其对象

J. *_*ers 5 django django-models django-admin python-3.x django-1.11

我有一个简单的应用程序(关于QR码),我有两个模型.第一个用于定义QR码,第二个用于赋予其功能.(对于那些想知道的人:我把它分成两个模型,因为我们的QR码很复杂,有时缺乏功能而且是只读的.我想尽可能地保持我们的数据库规范化.)这是模型(models.py):

from django.core.exceptions import ObjectDoesNotExist
from django.db import models
from django.utils.translation import ugettext_lazy as _

from core.behaviors import QRCodeable, UniversallyUniqueIdentifiable
from core.utils import QR_CODE_FUNCTIONS
from model_utils.fields import StatusField
from model_utils.models import SoftDeletableModel, TimeStampedModel

QR_CODE_PREFIX = "QR Code"
QR_CODE_FUNCTION_PREFIX = "Function"
QR_CODE_FUNCTION_MIDFIX = "for"


class QRCode(
    UniversallyUniqueIdentifiable,
    SoftDeletableModel,
    TimeStampedModel,
    models.Model
):
    @property
    def function(self):
        try:
            return self.qrcodefunction.qr_code_function
        except ObjectDoesNotExist:
            return ""

    class Meta:
        verbose_name = _('QR code')
        verbose_name_plural = _('QR codes')

    def __str__(self):
        return f'{QR_CODE_PREFIX} {self.uuid}'


class QRCodeFunction(
    UniversallyUniqueIdentifiable,
    SoftDeletableModel,
    TimeStampedModel,
    QRCodeable,
    models.Model
):
    QR_CODE_FUNCTIONS = QR_CODE_FUNCTIONS
    qr_code_function = StatusField(choices_name="QR_CODE_FUNCTIONS")

    class Meta:
        verbose_name = _('QR code function')
        verbose_name_plural = _('QR code functions')

    def __str__(self):
        return f'{QR_CODE_FUNCTION_PREFIX} {self.qr_code_function} {QR_CODE_FUNCTION_MIDFIX} {self.qr_code}'
Run Code Online (Sandbox Code Playgroud)

mixin QRCodeable是一个抽象基类,它赋予函数与QR码的OneToOne关系.mixin UniversallyUniqueIdentifiable给它一个uuid.

无论如何,我现在希望能够在Django管理员中创建具有功能的QR码.所以我写了自己的管理类(admin.py):

from django.contrib import admin

from .models import QRCode, QRCodeFunction


class QRCodeFunctionInline(admin.TabularInline):
    model = QRCodeFunction
    extra = 0


@admin.register(QRCode)
class QRCodeAdmin(admin.ModelAdmin):
    save_on_top = True
    search_fields = ['qrcodefunction__qr_code_function']
    list_display = (
        '__str__',
        'function',
    )
    inlines = [
        QRCodeFunctionInline,
    ]
Run Code Online (Sandbox Code Playgroud)

此代码生成以下管理界面:

Django管理员中QR码的管理界面.

如果我现在点击add another QR code function,选择一个功能并点击保存,则不会创建新的QR码功能实例!这是为什么?有人可以帮助我如何编写这个模型管理员,以便我可以在QR码管理员中创建QR码的功能?

sch*_*ngt 0

这可能是Django Admin 不保存预填充的内联字段的重复,这些字段保留在初始状态。您的内联将仅使用默认值,但如果一个或多个字段已更改,Django 的管理员默认情况下不会实际创建实例。这是一次痛苦的经历,但 Django 在这里谨慎行事是错误的。不创建比创建后必须删除更好。

根据您的上下文调整该问题的答案是:

from django.contrib import admin
from django.forms.models import ModelForm

class AlwaysChangedModelForm(ModelForm):
    def has_changed(self):
        """ Should returns True if data differs from initial. 
        By always returning true even unchanged inlines will get validated and saved."""
        return True


class QRCodeFunctionInline(admin.TabularInline):
    model = QRCodeFunction
    form = AlwaysChangedModelForm
    extra = 0
Run Code Online (Sandbox Code Playgroud)