У меня есть модель, Foo
. Он имеет несколько свойств базы данных и несколько свойств, которые рассчитываются на основе комбинации факторов. Я хотел бы представить эти рассчитанные свойства пользователю, как если бы они были свойствами базы данных. (Факторы поддержки будут изменены, чтобы отражать пользовательский ввод.) Есть ли способ сделать это с помощью интерфейса администратора Django?
Django: Подделка поля в интерфейсе администратора?
Ответ 1
Я бы предложил вам подкласс modelform для Foo
(FooAdminForm), чтобы добавить ваши собственные поля, не поддерживаемые базой данных. Ваша пользовательская проверка может находиться в методах clean_*
ModelForm.
Внутри метода save_model
FooAdmin
вы получите запрос, экземпляр Foo
и данные формы, чтобы вы могли выполнять всю обработку данных до/после сохранения экземпляра.
Вот пример модели с пользовательской формой, зарегистрированной в django admin:
from django import forms
from django.db import models
from django.contrib import admin
class Foo(models.Model):
name = models.CharField(max_length=30)
class FooAdminForm(forms.ModelForm):
# custom field not backed by database
calculated = forms.IntegerField()
class Meta:
model = Foo
class FooAdmin(admin.ModelAdmin):
# use the custom form instead of a generic modelform
form = FooAdminForm
# your own processing
def save_model(self, request, obj, form, change):
# for example:
obj.name = 'Foo #%d' % form.cleaned_data['calculated']
obj.save()
admin.site.register(Foo, FooAdmin)
Предоставление начальных значений для настраиваемых полей на основе данных экземпляра
(Я не уверен, что это лучшее решение, но оно должно работать.)
Когда модель модели для существующего экземпляра модели в базе данных сконструирована, он получает этот экземпляр. Таким образом, в FooAdminForm __init__
можно изменить атрибуты полей на основе данных экземпляра.
def __init__(self, *args, **kwargs):
# only change attributes if an instance is passed
instance = kwargs.get('instance')
if instance:
self.base_fields['calculated'].initial = (instance.bar == 42)
forms.ModelForm.__init__(self, *args, **kwargs)
Ответ 2
Достаточно легко получить произвольные данные для отображения в списке изменений или создать поле в форме: list_display
произвольно принимает либо фактические свойства модели, либо методы, определенные на модели или modeladmin, и вы можете подклассы forms.ModelForm
, чтобы добавить любой тип поля, который вы хотите изменить.
Что намного сложнее/невозможнее объединить два, то есть иметь произвольную часть данных в списке изменений, которую вы можете редактировать на месте, указав list_editable
. Кажется, что Django принимает только истинное свойство модели, соответствующее поле базы данных. (даже при использовании @property
для метода в определении модели недостаточно).
Кто-нибудь нашел способ редактировать поле, которое фактически не присутствует на модели, прямо со страницы списка изменений?
Ответ 3
В форме редактирования поместите имя свойства в readonly_fields (только 1.2 вверх).
В списке изменений переместите его в list_display.
Ответ 4
Вы можете использовать декоратор @property в своей модели (Python >= 2.4):
class Product(models.Model):
@property
def ranking(self):
return 1
"ранжирование" может затем использоваться в list_display
:
class ProductAdmin(admin.ModelAdmin):
list_display = ('ranking', 'asin', 'title')