Администратор Django 1.11: создайте отношение OneToOne и его объект в администраторе - PullRequest
0 голосов
/ 11 июня 2018

У меня есть простое приложение (о 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}'

Mixin QRCodeable - это абстрактный базовый класс, который дает функции отношение OneToOne к QR-коду.Mixin UniversallyUniqueIdentifiable дает ему UUID.

В любом случае, теперь я хочу иметь возможность создавать QR-коды с функциями внутри администратора Django.Поэтому я написал свой собственный класс администратора (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,
    ]

Этот код приводит к следующему интерфейсу администратора:

Admin interface of the QR code in the Django admin.

Если я сейчас нажму add another QR code function, выберу функцию и нажму «Сохранить», новый экземпляр функции QR-кода НЕ будет создан!Это почему?Как я могу написать эту модель администратора, чтобы я мог создавать функции для QR-кода в QR-кодах администратора?

1 Ответ

0 голосов
/ 23 марта 2019

Вероятно, это дубликат Django Admin, не сохраняющий предварительно заполненные встроенные поля, которые остаются в исходном состоянии .Ваш встроенный будет использовать только значения по умолчанию, но администратор 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
...