Django:在管理界面中伪造一个字段?

发布于 2024-10-16 02:06:08 字数 132 浏览 1 评论 0原文

我有一个模型,Foo。它具有多个数据库属性以及多个基于因素组合计算的属性。我想将这些计算属性呈现给用户,就好像它们是数据库属性一样。 (支持因素将发生变化以反映用户输入。)有没有办法使用 Django 管理界面来做到这一点?

I have a model, Foo. It has several database properties, and several properties that are calculated based on a combination of factors. I would like to present these calculated properties to the user as if they were database properties. (The backing factors would be changed to reflect user input.) Is there a way to do this with the Django admin interface?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

酒废 2024-10-23 02:06:08

我建议您为 Foo (FooAdminForm) 建立一个模型表单子类,以添加您自己的不受数据库支持的字段。您的自定义验证可以驻留在 ModelForm 的 clean_* 方法中。

FooAdminsave_model 方法中,您可以获得请求、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):
        super(FooAdminForm, self).__init__(*args, **kwargs)
        # only change attributes if an instance is passed            
        instance = kwargs.get('instance')
        if instance:
            self.fields['calculated'].initial = (instance.bar == 42)

I would suggest you subclass a modelform for Foo (FooAdminForm) to add your own fields not backed by the database. Your custom validation can reside in the clean_* methods of ModelForm.

Inside the save_model method of FooAdmin you get the request, an instance of Foo and the form data, so you could do all processing of the data before/after saving the instance.

Here is an example for a model with a custom form registered with 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)

Providing initial values for custom fields based on instance data

(I'm not sure if this is the best solution, but it should work.)

When a modelform for a existing model instance in the database is constructed, it gets passed this instance. So in FooAdminForm's __init__ one can change the fields attributes based on instance data.

    def __init__(self, *args, **kwargs):
        super(FooAdminForm, self).__init__(*args, **kwargs)
        # only change attributes if an instance is passed            
        instance = kwargs.get('instance')
        if instance:
            self.fields['calculated'].initial = (instance.bar == 42)
递刀给你 2024-10-23 02:06:08

获取任意数据以显示在更改列表中或使字段以以下形式显示是很容易的: list_display 任意采用实际模型属性或在模型或 modeladmin 上定义的方法,并且您可以子类化 forms.ModelForm 以将您想要的任何字段类型添加到更改表单中。

更困难/不可能的是将两者结合起来,即在更改列表上拥有任意数据,您可以通过指定 list_editable 就地编辑它。 Django 似乎只接受与数据库字段相对应的真实模型属性。 (即使在模型定义中的方法上使用 @property 也是不够的)。

有没有人找到一种方法可以直接从更改列表页面编辑模型中实际不存在的字段?

It's easy enough to get arbitrary data to show up in change list or make a field show up in the form: list_display arbitrarily takes either actual model properties, or methods defined on the model or the modeladmin, and you can subclass forms.ModelForm to add any field type you'd like to the change form.

What's far more difficult/impossible is combining the two, i.e. having an arbitrary piece of data on the change list that you can edit in-place by specifying list_editable. Django seems to only accept a true model property that corresponds to a database field. (even using @property on the method in the model definition is not enough).

Has anyone found a way to edit a field not actually present on the model right from the change list page?

幻梦 2024-10-23 02:06:08

您可以在模型中使用 @property 装饰器 (Python >= 2.4):

class Product(models.Model):

    @property
    def ranking(self):
        return 1

然后可以在 list_display 中使用 ranking

class ProductAdmin(admin.ModelAdmin):
    list_display = ('ranking', 'asin', 'title')

You can use the @property decorator in your model (Python >= 2.4):

class Product(models.Model):

    @property
    def ranking(self):
        return 1

ranking can then be used in list_display:

class ProductAdmin(admin.ModelAdmin):
    list_display = ('ranking', 'asin', 'title')
暮凉 2024-10-23 02:06:08

在编辑表单中,将属性名称放入 readonly_fields(仅限 1.2 及以上版本)。

在更改列表中,将其放入 list_display

In the edit form, put the property name into readonly_fields (1.2 upwards only).

In the changelist, put it into list_display.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文