DateTimeField在管理系统中不显示。

117

为什么我的“日期”字段在管理系统中没有显示?

在我的admin.py文件中,我有以下代码:

from django.contrib import admin
from glasses.players.models import *
admin.site.register(Rating)

并且评分模型有一个名为“date”的字段,它看起来像这样

date = models.DateTimeField(editable=True, auto_now_add=True)

然而在管理系统中,即使将editable设置为True,该字段也不会显示。

有人有什么想法吗?

10个回答

255
如果您想在管理面板中查看日期,可以在 admin.py 中添加 readonly_fields:
class RatingAdmin(admin.ModelAdmin):
    readonly_fields = ('date',)

admin.site.register(Rating,RatingAdmin)

您指定的任何字段都将添加到可编辑字段之后。要控制顺序,可以使用 fields 选项。

有关更多信息,请参见Django文档


37
这才是真正的答案!! - GreenAsJade
5
如果您规定了“字段”,则必须将您的字段放在其中,因此您需要同时在“readonly_fields”和“fields”中使用它,否则该字段将不会显示。 - Bjorn
我只想指出,如果您正在使用“字段集”,那么这也适用,今天我遇到了这个问题。 - Kevin Brown-Silva
1
这将使字段仅在单击并打开特定条目时出现。如果您希望该字段在列表视图本身中可见,则请参阅https://dev59.com/Bmw15IYBdhLWcg3wzO9_#34966908。 - Jyotman Singh
1
请注意,我不确定为什么,在Django 1.9下使用auto_now_add=True的DateTimeFields似乎无法正常工作。一种(有点)解决方法是将它们添加到list_display元组中。编辑:如果您像@BjornTipling提到的那样还将字段添加到fields中,则它将起作用。 - Taylor D. Edmiston

72

我认为原因在于auto_now_add字段。

来自这个答案

任何使用auto_now属性的字段也将继承editable=False,因此不会显示在管理面板中。

还在文档中提到:

目前的实现方式是,将auto_now或auto_now_add设置为True将使字段具有editable=False和blank=True设置。

这是有道理的,因为如果将对象保存时覆盖当前日期时间,则没有理由使该字段可编辑。


34
在记录被创建后,您应该可以通过管理员修改auto_now_add,对吗?请注意,需要保持原意并尽量使语言通俗易懂。 - Christopher Orr
78
即使它是不可编辑的,你也应该能够在管理界面中简单地显示它。 - Brad
1
请参考下面 @hunger 的答案,了解如何在管理界面中将其显示为只读字段。 - gdvalderrama
1
如果字段仅在对象创建时初始化(auto_now_add=True),则将字段设置为可编辑是有意义的。 - sergzach

25

主要黑客:

如果你真的需要这样做(像我一样),你可以通过立即将字段设置为“可编辑”来绕过它,定义如下字段:

class Point(models.Model):
  mystamp=models.DateTimeField("When Created",auto_now_add=True)
  mystamp.editable=True

这将使该字段可编辑,以便您可以实际更改它。至少在使用mysql后端引擎时似乎运行良好。我无法确定其他后备存储是否会使此数据在数据库中不可变,从而在尝试编辑时导致问题,因此请慎用


不要这样做,使用Hunger描述的readonly_fields解决方案。 - GreenAsJade
2
@GreenAsJade:有一个合理的解释会很好。 - mhsmith
@mhsmith 为什么要使用Hunger的解决方案而不是这个:因为这是一个重大的黑客行为,并带有“谨慎使用”的警告,而Hunger的解决方案则是按照Django设计的方式来使用。当您可以以合法和受支持的方式完成所需操作时,为什么要冒险进行重大的黑客行为呢? - GreenAsJade
7
这个破解方案并不那么糟糕。然而我唯一看到的使用情况是测试,当测试人员需要更改日期时。 - jacoor
或者当我们将实体从测试服务器迁移到生产环境时。 - Babu
2
只是一个警告:这个黑客攻击搞乱了我的迁移。 - damio

20

根据您的具体需求和行为差异的任何细微差别,您可以采取以下措施:

from django.utils.timezone import now

class MyModel(models.Model):
    date = models.DateTimeField(default=now)

默认字段可以这样使用:https://docs.djangoproject.com/en/dev/ref/models/fields/#default

The default value for the field. This can be a value or a callable object. If callable it will be called every time a new object is created.

这不会将可编辑性设置为False


1
我会使用 from django.utils.timezone import now 而不是 datetime.now,但这看起来很有前途。 - amjoconn
谢谢,我改了。 - orblivion
Stackoverflow很棒,因为有些答案让你意识到自己没有问对问题!谢谢。 - Samuel Dauzon
谢谢@orblivion,我一直在使用Django做项目,但是之前不知道这个,再次感谢! - faijan memon

6
如果您想让任何字段在所有条目列表中可见(当您在管理人员中单击模型时),而不是在打开特定条目时,则-
class RatingAdmin(admin.ModelAdmin):
    list_display = ('name', 'date') 

admin.site.register(Rating, RatingAdmin)

'name'是你的主要字段或任何你想在管理面板中显示的其他字段。

通过这种方式,你可以指定所有想要查看的列。


5

这可能与auto_now_add参数为true有关。也许你可以重写模型保存方法,当id为空时插入日期时间,而不是使用该参数在添加时捕获日期。

class Rating(models.Model):

    ....
    def save(self, *args, **kwargs)
        if not self.id: 
            self.date = datetime.datetime.now()

如果您这样做了,那么就没有理由将字段定义为__auto_now__。 - FallenAngel
不确定为什么会被踩;Shawn Chin 提供的第一个链接指出了类似的方法。 - Joe J
这是一个明智的选择,假设没有使用auto_noweditable=False。+1 - Shawn Chin

1

可以通过以下admin.py中的代码简单地在Django admin中显示

@admin.register(model_name)
class model_nameAdmin(admin.ModelAdmin):
    list_display = ['date']

上述代码将在Django管理界面中显示所有在list_display中提到的字段,无论模型字段是否设置为Trueauto_now属性。

我觉得使用装饰器的解决方案最为简洁。或者,您可以定义类并单独注册模型和类。 - Domenico Spidy Tamburro

1

我想创建一个可编辑的时间字段,其默认值为当前时间。

实际上,我发现最好的选择是避免使用auto_nowauto_add_now,而是直接使用datetime库。

MyTimeField = models.TimeField(default=datetime.now)

重要的是,你应该将变量now设置为函数/获取器,而不是一个函数/获取器,否则每次调用makemigrations时都会得到一个新的默认值,这将导致生成大量冗余的迁移。

1
这是一个更准确的解决方案,能够在管理网站上正确显示和编辑字段,并在应用程序上保持正确的行为。 - undefined

0

你不能这样做,请查看文档

auto_nowauto_now_add都是不可编辑的字段,你无法覆盖它们...


0
这是根据 Hunger 的答案和根据 Rahul Kumar 建议使用装饰器的组合:

在您的 admin.py 文件中,您只需要:

@admin.register(Rating)
class RatingAdmin(admin.ModelAdmin):
    readonly_fields = ('date',)

readonly_fields 中指定的字段将出现在添加和更改页面中,即单个记录内部。当然,这些字段是不可编辑的。

list_display 中的字段将构成管理界面主列表页的表示形式(即所有记录的列表)。在这种情况下,不仅仅指定 list_display = ('date',) 是有意义的,因为你只会看到日期。相反,还应包括记录的主标题/名称。

例如:

readonly_fields = ('title', 'date',)

如果在 models.py 中定义了这个模型:
class Rating(models.Model):
    title = models.CharField('Movie Title', max_length=150)
    ...
    date = models.DateTimeField(editable=True, auto_now_add=True)

    def __str__(self):
        return self.title

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接