0

I lookup for the solution but I believe I'm doing something wrong or in Django 4 is different. The created_at and updated_at fields doesn't appear on admin. I don't know what I'm skipping.

The Parent class

class TimeStampMixin(models.Model):
  class Meta:
      abstract = True
  created_at = models.DateTimeField(auto_now_add=True)
  updated_at = models.DateTimeField(auto_now=True)

  def __str__(self) -> str:
      return f'{self.created_at} - {self.updated_at}'

The class that inherited from TimeStampMixin

class Post(TimeStampMixin):
    STATUS_CHOICES = (
        ('draft', 'Draft'),
        ('published', 'Published'),
    )
    title = models.CharField(max_length=200)
    body = models.TextField()
    category = models.ForeignKey('Category', on_delete=models.SET_NULL, null=True)
    # tags = models.ManyToManyField('Tag')
    tags = TaggableManager()
    objects = models.Manager() # The default manager.
    slug = models.SlugField(max_length=250,
                            unique_for_date='publish')
    author = models.ForeignKey(User,
                              on_delete=models.CASCADE,
                              related_name='blog_posts')
    publish = models.DateTimeField(default=timezone.now)
    status = models.CharField(max_length=10,
                              choices=STATUS_CHOICES,
                              default='draft')
    
    published = PublishedManager() # Our custom manager.


    class Meta:
        ordering = ('-publish',)
        
    def __str__(self):
        return self.title
    
    def get_absolute_url(self):
        return reverse('blog:post_detail',
                        args=[self.publish.year,
                                self.publish.month,
                                self.publish.day, self.slug])

the admin specification in admin.py file

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    list_display = ('title', 'slug', 'author', 'publish', 'status', 'created_at', 'updated_at')
    list_filter = ('status', 'created_at', 'publish', 'author')
    search_fields = ('title', 'body')
    prepopulated_fields = {'slug': ('title',)}
    raw_id_fields = ('author',)
    date_hierarchy = 'publish'
    ordering = ('status', 'publish')

the result

enter image description here

  • because you have it under a mate class you should put them above the mate class and apply migrations. – Godda Dec 28 '21 at 19:18
  • I believe that you mean `meta class` and doesn't the position of the `meta class` I tried before, after and nothing. –  Dec 29 '21 at 17:34
  • Yes i meant Meta class it was a typo! It seems you already have answers to the issue at hand! – Godda Dec 29 '21 at 18:14

2 Answers2

0

This is what you are supposed to do and then you apply migrations,Before you add the perent model to admin.py.

class TimeStampMixin(models.Model):
      created_at = models.DateTimeField(auto_now_add=True)
      updated_at = models.DateTimeField(auto_now=True)
      
      class Meta:
            abstract = True
      def __str__(self):
          return f'{self.created_at} - {self.updated_at}'

Better yet can just add the date time field to your child model since you are not adding the parent to the admin, i guess it should work. So you can do something like this. This is just an alternative example..

class Post(TimeStampMixin):
    STATUS_CHOICES = (
        ('draft', 'Draft'),
        ('published', 'Published'),
    )
    title = models.CharField(max_length=200)
    body = models.TextField()
    category = models.ForeignKey('Category', on_delete=models.SET_NULL, null=True)
    # tags = models.ManyToManyField('Tag')
    tags = TaggableManager()
    objects = models.Manager() # The default manager.
    slug = models.SlugField(max_length=250,
                            unique_for_date='publish')
    author = models.ForeignKey(User,
                              on_delete=models.CASCADE,
                              related_name='blog_posts')
    publish = models.DateTimeField(default=timezone.now)
    status = models.CharField(max_length=10,
                              choices=STATUS_CHOICES,
                              default='draft')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    published = PublishedManager() # Our custom manager.
Godda
  • 951
  • 1
  • 10
  • 26
  • What do you mean, before I added the parent model? I added `TimeStampMixin` at the same time that I did with Post and applied `makemigration` and `migration` after add it on model. –  Dec 29 '21 at 17:36
  • I use the TimeStampMixin in order to avoid repeating on all my models `created_at` and `updated_at` fields. Abstract base classes are useful when you want to put some common information into a number of other models. You write your base class and put abstract=True in the Meta class. This model will then not be used to create any database table. Instead, when it is used as a base class for other models, its fields will be added to those of the child class. https://docs.djangoproject.com/en/4.0/topics/db/models/#abstract-base-classes –  Dec 29 '21 at 17:37
  • What i mean is that you don't set DateTImeField under a mate class it wont work as in your case and off cause i know you can set fields in an abstract class. – Godda Dec 29 '21 at 18:04
  • You should have a look at your model TimeStampMixin codes you had set the datetimefield under the metaclass which wont work! – Godda Dec 29 '21 at 18:09
  • Even from the this docs shared on here ,you can clearly see that the name and age field was not added to the abstract Meta class docs.djangoproject.com/en/4.0/topics/db/models/… – Godda Dec 29 '21 at 18:29
0

The problem is that your created_at and updated_at should be readonly_fields. Try the following

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    list_display = ('created_at', 'updated_at')
    # your code
    readonly_fields = ('created_at', 'updated_at')

It will work