0

I'm flummoxed by the following:

models.py

class MyModel(models.Model):
    ...
    @property
    def xyz(self):
        return ...

admin.py:

class MyModelAdmin(admin.ModelAdmin):
    readonly_fields = ("xyz",)
    ...
    def get_readonly_fields(self, request, obj=None):
        """ As per http://stackoverflow.com/a/13818017/1149759 """
        if <some condition>:
            return [f.name for f in self.model._meta.fields]
        return self.readonly_fields

If <some condition> is satisfied, the admin page for this model fails with:

Unknown field(s) (xyz) specified for MyModel. 
Check fields/fieldsets/exclude attributes of class MyModel.

I tried refactoring the model and admin code to make xyz() not a property, but this same error happened in the same way.

Even tried stepping through the internal Django code. It's failing on this line:

lib/python2.7/site-packages/django/contrib/admin/options.py(640)get_form()
-> return modelform_factory(self.model, **defaults)

{'fields': [..., 'xyz', ...], 
  'formfield_callback': <functools.partial object at 0x104a024c8>, 
  'form': <class 'django.forms.widgets.ModelForm'>, 
  'exclude': [<a long list of fields that does not include xyz>]}

Thanks for any insight you can provide.

Update:

  • Removing xyz from readonly_fields doesn't fix things
  • Tried eliminating readonly_fields altogether as per comment below. The following also did not work:

def get_readonly_fields(self, request, obj=None): if <whatever>: return [f.name for f in self.model._meta.fields] return ['xyz', ...]

After additional testing, it begins to seem to me that there is no way that get_readonly_fields will work on this model!

class MyModelAdmin(admin.ModelAdmin):
    # readonly_fields = ("xyz",) # Removed this field to test
    ...
    def get_readonly_fields(self, request, obj=None):
        return [] # Removed all the logic 

The preceding still throws the Unknown fields specified for xyz -- as well as for the following two fields on the model!

added = models.DateTimeField(auto_now_add=True, null=True, blank=True,)
last_updated = models.DateTimeField(auto_now=True, null=True, blank=True,)
TAH
  • 1,658
  • 1
  • 19
  • 37

2 Answers2

1

It seems the only way to get this to work is to explicitly add xyz to the list of read-only fields.

class MyModelAdmin(admin.ModelAdmin):
    readonly_fields = ("xyz", ...)
    ...
    def get_readonly_fields(self, request, obj=None):
        if <condition>:
            ro = [f.name for f in self.model._meta.fields]
            ro.append('xyz') # <=============
            return ro
        return self.readonly_fields
TAH
  • 1,658
  • 1
  • 19
  • 37
0

Properties are different from fields. You've defined xyz as a property, which is not supported as editable by the Django Admin. Only fields on the model can be members of the readonly_fields property of your admin. You should find that xyz is not a member of self.model._meta.fields and thus would never be returned by get_readonly_fields.

You should also include either readonly_fields or get_readonly_fields.

Jordan Haines
  • 206
  • 1
  • 4
  • Thanks for your thoughts, although they did not lead to a resolution. Please see the updates above. Thanks! – TAH Apr 13 '16 at 12:54
  • Just want to clarify - when you return ["added"] from `get_only_fields` do you still get an error? I just want to make sure you're not mixing up properties and fields. You should be able to included "added" or "last_updated" in the list returned by `get_readonly_fields`. If you still get the error with those fields, I can dig into this a bit further for you – Jordan Haines Apr 14 '16 at 02:41