1

Django 3.0.8

admin.py

class PostAdmin(admin.ModelAdmin):
    list_display = ("id", "title", 'category',)

    def get_fields(self, request, obj=None):
        fields = [a_field.name for a_field in self.model._meta.fields]
        return fields

    def get_readonly_fields(self, request, obj):
        readonly_fields = self.readonly_fields
        if obj:
            if obj.already_published and (not request.user.has_perm('posts.change_already_puclished')):
                readonly_fields = READONLY_FIELDS_AFTER_PUBLISHING

        return readonly_fields

traceback

Exception Type: FieldError
Exception Value:    
'created' cannot be specified for Post model form as it is a non-editable field. Check fields/fieldsets/exclude attributes of class PostAdmin.

Local vars

Variable    Value
change  
False
defaults    
{'exclude': None,
 'fields': ['id',
            'comment',
            'title',
            'slug',
            'description',
            'body',
            'draft',
            'already_published',
            'featured_image',
            'category',
            'excerpt',
            'h1',
            'author',
            'created',
            'updated',
            'sidebar',
            'keywords',
            'lsi',
            'google_indexed',
            'google_first_indexed',
            'yandex_indexed',
            'yandex_first_indexed'],
 'form': <class 'django.forms.widgets.ModelForm'>,
 'formfield_callback': functools.partial(<bound method BaseModelAdmin.formfield_for_dbfield of <posts.admin.PostAdmin object at 0x7f1d596e3820>>, request=<WSGIRequest: GET '/admin/posts/post/add/'>)}
exclude 
None
excluded    
None
fields  
['id',
 'comment',
 'title',
 'slug',
 'description',
 'body',
 'draft',
 'already_published',
 'featured_image',
 'category',
 'excerpt',
 'h1',
 'author',
 'created',
 'updated',
 'sidebar',
 'keywords',
 'lsi',
 'google_indexed',
 'google_first_indexed',
 'yandex_indexed',
 'yandex_first_indexed']
form    
<class 'django.forms.widgets.ModelForm'>
kwargs  
{}
new_attrs   
{'declared_fields': {}}
obj 
None
readonly_fields 
()
request 
<WSGIRequest: GET '/admin/posts/post/add/'>
self    
<posts.admin.PostAdmin object at 0x7f1d596e3820>

The same as image:

enter image description here

I try this code both with a superuser and a user who don't have change_already_puclished permission.

  1. Superuser: when trying to add or change a post, the error appear.
  2. Ordinary user: adding posts is Ok, no errors. But adding a new pose causes this error.

Edit

class Post(DraftMixin,
       TitleMixin,
       TagMixin,
       SlugMixin,
       DescriptionMixin,
       CommentMixin,
       FeaturedImageMixin,
       BodyMixin,
       models.Model):
category = models.ForeignKey(Category,
                             on_delete=models.PROTECT,
                             verbose_name="Категория")

excerpt = models.TextField(default=True,
                           blank=True,
                           verbose_name="Выдержка") # A text associated to a Post. Most of the time, it is used as the Post summary.
h1 = models.CharField(max_length=500,
                      blank=True,
                      default="",
                      verbose_name="H1")
author = models.ForeignKey(Author,
                           blank=True,
                           null=True,
                           on_delete=models.PROTECT,
                           related_name='blog_posts',
                           verbose_name="Автор")

created = models.DateField(auto_now_add=True,
                           verbose_name="Дата создания")
updated = models.DateField(auto_now=True,
                           verbose_name="Дата обновления")

sidebar = models.ForeignKey(Sidebar,
                            null=True,
                            blank=True,
                            on_delete=models.PROTECT,
                            verbose_name="Сайдбар")

keywords = models.TextField(blank=True, default="", verbose_name="Ключевые слова")
lsi = models.TextField(blank=True, default="", verbose_name="LSI")

google_indexed = models.BooleanField(verbose_name="Индексировано Google",
                                     default=False)
google_first_indexed = models.DateField(blank=True,
                                        null=True,
                                        verbose_name="Дата первой индексации Google")

yandex_indexed = models.BooleanField(verbose_name="Индексировано Яндекс",
                                     default=False)
yandex_first_indexed = models.DateField(blank=True,
                                        null=True,
                                        verbose_name="Дата первой индексации Яндексом")

class Meta:
    ordering = ('-created',)
    verbose_name = "Статья"
    verbose_name_plural = "Статьи"
    permissions = [
        ("change_already_puclished", 'Может менять статус "Уже опубликовано"'),
    ]
halfer
  • 19,824
  • 17
  • 99
  • 186
Michael
  • 4,273
  • 3
  • 40
  • 69

2 Answers2

1

The problem is caused by this definition:

created = models.DateField(auto_now_add=True,
                           verbose_name="Дата создания")

auto_now_add makes it so that Django can't edit it. So you can't specify it as an editable form field.

You need to specify it as a readonly field. See: Django admin: How to display a field that is marked as editable=False' in the model?

Aayush Agrawal
  • 1,354
  • 1
  • 12
  • 24
1

If you set auto_now_add to True, then the field will become un-editable by default (editable=False) and Django will handle that field automatically. Also auto_now=True will cause an override to any changes since it will update the field when you call save() on an instance.

You can add those fields to be shown in a form by adding them to readonly_fields but you can't add/edit them. Now you either have to remove auto_now_add and auto_now and provide your value for them or you should let Django do it for you.

Django docs: DateField.auto_now_add

Navid Zarepak
  • 4,148
  • 1
  • 12
  • 26