DateTimeField doesn't show in admin system
Asked Answered
S

10

119

How come my "date" field doesn't come up in the admin system?

In my admin.py file i have

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

and the Rating model has a field called "date" which looks like this

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

However within the admin system, the field doesn't show, even though editable is set to True.

Does anyone have any idea?

Sharyl answered 17/6, 2011 at 13:6 Comment(0)
P
74

I believe to reason lies with the auto_now_add field.

From this answer:

Any field with the auto_now attribute set will also inherit editable=False and therefore will not show up in the admin panel.

Also mentioned in the docs:

As currently implemented, setting auto_now or auto_now_add to True will cause the field to have editable=False and blank=True set.

This does make sense, since there is no reason to have the field editable if it's going to be overwritten with the current datetime when the object is saved.

Polynesia answered 17/6, 2011 at 13:13 Comment(4)
Though surely you should be able to edit auto_now_add via the admin after the entry has first been created?Gaspard
You should also be able to simply display it in the admin interface, even if it was uneditable.Tricuspid
Please refer to the answer by @hunger below for how to display it as a readonly field in the admin interface.Wineglass
It does make sense to have a field editable if the field is only inited on an object creation (auto_now_add=True).Homeopathy
H
263

If you really want to see date in the admin panel, you can add readonly_fields in admin.py:

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

admin.site.register(Rating,RatingAdmin)

Any field you specify will be added last after the editable fields. To control the order you can use the fields options.

Additional information is available from the Django docs.

Harrie answered 14/5, 2014 at 16:18 Comment(6)
THIS is the real answer!!Seabolt
if you stipulate a fields you also have to put your field in that, so you would need it both in readonly_fields and fields otherwise the field wouldn't show up.Dear
I just wanted to note that this also applied if you are using fieldsets, just ran into this issue today.Indigo
This will make the field appear only when we click and open a particular entry. If you want the field to be visible in the listview itself then https://mcmap.net/q/181769/-datetimefield-doesn-39-t-show-in-admin-systemDisgraceful
Note that I'm not sure why but this does not seem to work for DateTimeFields with auto_now_add=True under Django 1.9. A (sort of) workaround is to add them to the list_display tuple instead. Edit: It will work if you also add your field to fields as @BjornTipling mentioned.Compulsion
you could also: admin.site.register(your_model, readonly_fields = ('your_field',))Galvanize
P
74

I believe to reason lies with the auto_now_add field.

From this answer:

Any field with the auto_now attribute set will also inherit editable=False and therefore will not show up in the admin panel.

Also mentioned in the docs:

As currently implemented, setting auto_now or auto_now_add to True will cause the field to have editable=False and blank=True set.

This does make sense, since there is no reason to have the field editable if it's going to be overwritten with the current datetime when the object is saved.

Polynesia answered 17/6, 2011 at 13:13 Comment(4)
Though surely you should be able to edit auto_now_add via the admin after the entry has first been created?Gaspard
You should also be able to simply display it in the admin interface, even if it was uneditable.Tricuspid
Please refer to the answer by @hunger below for how to display it as a readonly field in the admin interface.Wineglass
It does make sense to have a field editable if the field is only inited on an object creation (auto_now_add=True).Homeopathy
T
25

Major Hack:

If you really need to do this (as I do) you can always hack around it by immediatley setting the field to be "editable" defining the field as follows:

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

This will make the field editable, so you can actually alter it. It seems to work fine, at least with the mysql backing engine. I cannot say for certian if other backing stores would make this data immutable in the database and thus cause a problem when editing is attempted, so use with caution.

Tricuspid answered 30/5, 2013 at 17:13 Comment(6)
Nah, don't do this, use the readonly_fields solution described by Hunger.Seabolt
@GreenAsJade: A rationale would be nice.Deception
@Deception Rationale to use Hunger's solution instead of this: because this is a major hack and comes with "use with caution" , wheras Hunger's solution uses django the way it is designed to be used. Why would you risk a major hack when you can do what you need in a legitimate and supported fashion?Seabolt
This hack solution is not that bad. The only use case for it however I see is testing - when tester need to alter date.Totalizer
Or when we migrate the entities from a test server to prod.Juno
just a warning: this hack messed up the migrations for meGad
S
20

Depending on your specific needs, and any nuances in difference in behavior, you could do the following:

from django.utils.timezone import now

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

The default field can be used this way: 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.

This does not set editable to False

Suggestibility answered 28/12, 2014 at 18:56 Comment(3)
I would use from django.utils.timezone import now instead of datetime.now, but this looks promising.Consecration
Stackoverflow is awesome because, some answers make you realize you didn't ask the right question ! Thank you.Amarette
thanks @Suggestibility , I have been doing projects in django from so long but wasn't aware of this , thanks again !Gautious
D
6

If you want any field to be visible in the list of all your entries (when you click on a model in the admin people) and not when you open that particular entry then -

class RatingAdmin(admin.ModelAdmin):
    list_display = ('name', 'date') 

admin.site.register(Rating, RatingAdmin)

'name' being your main field or any other field you want to display in the admin panel.

This way you can specify all the columns you want to see.

Disgraceful answered 23/1, 2016 at 18:6 Comment(0)
V
5

It might have to do with the auto_now_add being true. Perhaps instead of that parameter to capture the date on add, you could override the model save method to insert the datetime when the id is null.

class Rating(models.Model):

    ....
    def save(self, *args, **kwargs)
        if not self.id: 
            self.date = datetime.datetime.now()
Vergeboard answered 17/6, 2011 at 13:14 Comment(3)
If you did, then there is no reason to define field as auto_nowContretemps
Not sure why the downvote; the first link Shawn Chin provides indicates a similar approach.Vergeboard
That's a sensible alternative, assuming auto_now is not used and editable=False. +1Polynesia
I
1

Can be displayed in Django admin simply by below code in admin.py

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

Above code will display all fields in django admin that are mentioned in list_display, no matter the model field is set to True for auto_now attribute

Irinairis answered 13/4, 2021 at 4:52 Comment(1)
I find this solution with the decorator as the most compact. Alternatively, you define the class and register the model and the class separately.Sherris
L
1

I wanted to create an editable time field that defaults to the current time.

I actually found that the best option was to avoid the auto_now or auto_add_now altogether and simply use the datetime library.

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

The big thing is that you should make it's the variable now instead of a function/getter, otherwise you're going to get a new default value each time you call makemigrations, which will result in generating a bunch of redundant migrations.

Lavina answered 13/4, 2021 at 17:20 Comment(1)
This is a much more accurate resolution to the issue at hand. It properly provides a way to make the field visible and properly editable at the admin site, while maintaining the correct behavior on the app.Footboy
C
0

You can not do that, check the documentation

auto_now and auto_now_add are all non-editable fields and you can not override them...

Contretemps answered 17/6, 2011 at 13:20 Comment(0)
S
0

This is a combination of the answers by Hunger and using a decorator as suggested by Rahul Kumar:

In your admin.py, you just need:

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

The fields specified in readonly_fields will appear in the add and change page i.e. inside the individual record. And - of course - are not editable.

The fields in list_display will constitute the representation in the main list page of the admin (i.e. the list of all records). In this case, it makes sense not to specify list_display = ('date',) only, because you will see only the dates. Instead, include also the main title / name of the record.

Example:

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

if in the models.py this model is defined as:

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
Sherris answered 26/10, 2022 at 13:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.