如何将计算字段添加到Django mod

2024-09-29 19:32:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个简单的Employee模型,其中包括firstnamelastnamemiddlename字段。

在管理方面,可能在其他方面,我想显示为:

lastname, firstname middlename

对我来说,这样做的逻辑位置是在模型中创建一个计算字段:

from django.db import models
from django.contrib import admin

class Employee(models.Model):
    lastname = models.CharField("Last", max_length=64)
    firstname = models.CharField("First", max_length=64)
    middlename = models.CharField("Middle", max_length=64)
    clocknumber = models.CharField(max_length=16)
    name = ''.join(
        [lastname.value_to_string(),
        ',',
         firstname.value_to_string(),
        ' ',
         middlename.value_to_string()])

    class Meta:
        ordering = ['lastname','firstname', 'middlename']

class EmployeeAdmin(admin.ModelAdmin):
    list_display = ('clocknumber','name')
    fieldsets = [("Name", {"fields":(("lastname", "firstname", "middlename"), "clocknumber")}),
        ]

admin.site.register(Employee, EmployeeAdmin)

最终,我认为我需要的是将名称字段的值作为字符串获取。我得到的错误是value_to_string() takes exactly 2 arguments (1 given)。字符串的值需要self, obj。我不知道obj是什么意思。

一定有一个简单的方法来做这件事,我相信我不是第一个想做这件事的人。

编辑:这是我根据丹尼尔的回答修改的代码。我得到的错误是:

django.core.exceptions.ImproperlyConfigured: 
    EmployeeAdmin.list_display[1], 'name' is not a callable or an 
    attribute of 'EmployeeAdmin' of found in the model 'Employee'.


from django.db import models
from django.contrib import admin

class Employee(models.Model):
    lastname = models.CharField("Last", max_length=64)
    firstname = models.CharField("First", max_length=64)
    middlename = models.CharField("Middle", max_length=64)
    clocknumber = models.CharField(max_length=16)

    @property
    def name(self):
        return ''.join(
            [self.lastname,' ,', self.firstname, ' ', self.middlename])

    class Meta:
        ordering = ['lastname','firstname', 'middlename']

class EmployeeAdmin(admin.ModelAdmin):
    list_display = ('clocknumber','name')
    fieldsets = [("Name", {"fields":(("lastname", "firstname", "middlename"), "clocknumber")}),
]

admin.site.register(Employee, EmployeeAdmin)

Tags: djangonameselfadminmodelsemployeefirstnamelength
3条回答

Daniel Roseman的解决方案使计算字段成为一个Model的属性,然而它是does not make it accessible via QuerySet methods(例如all().values())。这是因为QuerySet方法call the database directly,绕过django Model

由于queryset直接访问数据库,解决方案是通过附加计算字段来重写Manager.get_queryset()方法。使用.annotate()创建计算字段。最后,将Model中的objects管理器设置为新的Manager

下面是一些代码来演示这一点:

models.py

from django.db.models.functions import Value, Concat
from django.db import Model

class InvoiceManager(models.Manager):
    """QuerySet manager for Invoice class to add non-database fields.

    A @property in the model cannot be used because QuerySets (eg. return
    value from .all()) are directly tied to the database Fields -
    this does not include @property attributes."""

    def get_queryset(self):
        """Overrides the models.Manager method"""
        qs = super(InvoiceManager, self).get_queryset().annotate(link=Concat(Value("<a href='#'>"), 'id', Value('</a>')))
        return qs

class Invoice(models.Model):
    # fields

    # Overridden objects manager
    objects = InvoiceManager()

现在,您可以调用.values().all(),并访问在Manager中声明的新计算的link属性。

也可以在.annotate()中使用other functions,例如F()

我相信属性在object._meta.get_fields()中仍然不可用。我相信你可以在这里添加它,但我还没有探索如何-任何编辑/评论将是有益的。

这不是你作为一个领域所做的事情。即使该语法起作用,它也只会在定义类时给出值,而不是在访问它时。您应该将其作为一个方法来执行,并且可以使用@property装饰器使其看起来像一个普通属性。

@property
def name(self):
    return ''.join(
        [self.lastname,' ,', self.firstname, ' ', self.middlename])

self.lastname等只是它们的值,因此不需要调用任何其他方法来转换它们。

好的。。。丹尼尔·罗斯曼的回答似乎应该奏效。像往常一样,在你发布问题之后,你会发现你想要的是什么。

从开箱即用的django 1.5 docs I found this example开始。感谢大家的帮助。

以下是有效的代码:

from django.db import models
from django.contrib import admin

class Employee(models.Model):
    lastname = models.CharField("Last", max_length=64)
    firstname = models.CharField("First", max_length=64)
    middlename = models.CharField("Middle", max_length=64)
    clocknumber = models.CharField(max_length=16)

    def _get_full_name(self):
        "Returns the person's full name."
        return '%s, %s %s' % (self.lastname, self.firstname, self.middlename)
    full_name = property(_get_full_name)


    class Meta:
        ordering = ['lastname','firstname', 'middlename']

class EmployeeAdmin(admin.ModelAdmin):
    list_display = ('clocknumber','full_name')
    fieldsets = [("Name", {"fields":(("lastname", "firstname", "middlename"), "clocknumber")}),
]

admin.site.register(Employee, EmployeeAdmin)

相关问题 更多 >

    热门问题