0

I have a django application which is using django.contrib.admin for administrative tasks.

For one model I now need to add a field which indicates which part of the code each row was created from. I am using readonly_fields to prevent this value from being changed through the administration interface.

A default value in this field will tell me that the row was either

  • created before the field was introduced
  • created by code which has not been updated to set the field
  • created through the administration interface

But I need better granularity than that. In particular I want to be able to distinguish between a row created by code which doesn't know about the field, and a row created through the administration interface.

Is there some way my ModelAdmin class can specify an initial value for a field mentioned in readonly_fields?

kasperd
  • 1,952
  • 1
  • 20
  • 31
  • is there a constructor? That's where you can set it most other languages. – Mark Sep 26 '15 at 12:11
  • @Mark I could add a constructor to the class, but how would the constructor know whether it was called from `django.contrib.admin` or not? – kasperd Sep 26 '15 at 12:15

2 Answers2

1

One way to do this is,

def get_form(self, request, caja=None, **kwargs):
    self.form = YourModelForm

    form = super(YourModelAdmin, self).get_form(request, caja, **kwargs)
    form.base_fields['field'].initial = your_initial_data
    return form
Nick Cuevas
  • 1,474
  • 15
  • 10
0

I found this solution, which appears to work:

class Admin(ModelAdmin):
    readonly_fields = ('created_by',)
    def save_form(self, request, form, change):
        r = super(Admin, self).save_form(request, form, change)
        if not change:
            assert r.created_by == CREATED_BY_UNKNOWN
            r.created_by = CREATED_BY_ADMIN
        return r

CREATED_BY_UNKNOWN and CREATED_BY_ADMIN are values defined elsewhere in my code.

kasperd
  • 1,952
  • 1
  • 20
  • 31
  • 1
    It might be slightly better to override `save_model`, as this seems to be the [documented approach](https://docs.djangoproject.com/en/1.10/ref/contrib/admin/#django.contrib.admin.ModelAdmin.save_model) to achieve the desired outcome. – Joshua Pokotilow Mar 10 '17 at 18:55
  • @JoshuaPokotilow It's been 1½ years, and I no longer remember exactly which approaches I tried before coming up with my solution. So I cannot tell you whether using `save_model` was tested and discarded for some reason. I can tell you that the solution I came up with worked, and to the best of my knowledge it is still being used and never caused a problem. – kasperd Mar 10 '17 at 22:05
  • I don't doubt your approach works. Just pointing out an alternative that might be more future-proof. I don't see `save_form` documented anywhere, so there's a possibility (however remote) that Django will stop calling it someday. Unless something has been peculiarly customized, there's also no reason to think `save_model` wouldn't work just as well as `save_form` for Django 1.6 or later, at least given the stated problem / proposed solution. – Joshua Pokotilow Mar 10 '17 at 23:02
  • @JoshuaPokotilow Sure. I'll keep your suggestion in mind in case I ever need to do anything similar again. The code base in question was tested with 1.8 and there were many other things which did not work. So it surely would be a significant undertaking to port it to 1.8. – kasperd Mar 11 '17 at 00:24