4

I have a fairly simple Django application (v1.3 on Red Hat) for which I'm using the admin application to create and modify database records. One of the fields in my underlying model is a date field. Each time the corresponding field is displayed in the admin's new or edit form I'd like the initial value of this field to be today's date (and time). The user may choose to modify it thereafter, if she desires.

I know that I can set the default field value within my model definition (i.e. in models.py). Which works fine when a database record is first created. But for subsequent invocations of the change form the callable that I've assigned to the default parameter (datetime.datetime.now) obviously doesn't get invoked.

I've looked at - and tried - pretty well all of the many proposed solutions described elsewhere in stackoverflow, without success. Most of these appear to revolve around inserting initialisation code into the ModelForm subclass, e.g. either something like this...

class ConstantDefAdminForm(ModelForm) :
    a_date_field = DateField(initial="datetime.datetime.now")  # or now()
    class Meta :
        model = ConstantDef
        widgets = {
            ...
        }

or something like this...

class ConstantDefAdminForm(ModelForm) :
    class Meta :
        model = ConstantDef
        widgets = {
            ...
    }
    def __init__(self, ...) :
        # some initialisation of a_date_field
        super(ConstantDefAdminForm, self).__init__(...)

But neither of these approaches work. The initial field value is always set to the value that is stored in the database. My reading of the Django documentation is that the various ways of imposing initial field values in forms only work for unbound forms, not bound forms. Right?

But this capability (to selectively override currently stored values) would seem to be such a popular requirement that I'm convinced that there must be a way to do it.

Has anyone out there succeeded in doing this?

Thanks in advance,

Phil

5 Answers 5

4

In Django 1.4 the default=<callable> in model's declaration works well:

class MyModel(models.Model):
    dt = models.TimeField(null=True, blank=True, default=datetime.datetime.now)

every time you add a record the default value of the field is updated.

But the use the field's default parameter cause me some problem with the Admin log history of DateField objects, that are every time recorded as changed also when they are not modified. So I've adopted a solution based on https://stackoverflow.com/a/11145346/1838607:

import datetime

class MyModelAdminForm(forms.ModelForm):
    class Meta:
        model = MyModel

    def __init__(self, *args, **kwargs):
        super(MyModelAdminForm, self).__init__(*args, **kwargs)

        self.fields['dt'].initial = datetime.datetime.now

class MyModelAdmin(admin.ModelAdmin):
    form = MyModelAdminForm
    fields = ('dt',)
Sign up to request clarification or add additional context in comments.

Comments

3

Here's an approach that might work. In your model admin class, change the value of obj.a_date_field before the form is bound. The 'default' value for the date field should be the new value.

class MyModelAdmin(ModelAdmin):
    ...
    def get_object(self, request, object_id):
        obj = super(MyModelAdmin, self).get_object(request, object_id)
        if obj is not None:
            obj.a_date_field = datetime.now()
        return obj

Note that get_object is not documented, so this is a bit hacky.

1 Comment

Cool! That seems to do the trick. Not sure what, if any, side effects there might be. But I guess I'll find out in due course :-) Thanks alot.
1

I had a similar problem, and I found the solution from here

I think what you will want to do is this:

class yourAdminModel(admin.ModelAdmin):

    fields = ['your_date_field']

    def add_view(self, request, form_url="", extra_context=None):
        data = request.GET.copy()
        data['your_date_field'] = datetime.date.today() # or whatever u need
        request.GET = data
        return super(yourAdminModel, self).add_view(request, form_url="", extra_context=extra_context)

Comments

0

You should be able to use auto_now with your DateTime Field which according to the docs will automatically set the value to now() each time the form is saved

1 Comment

Hi Brandon. Thanks for the tip. I hadn't spotted these date field options before. Unfortunately they don't quite do the trick because, as the docs mention, the field is rendered non-editable when either of the auto_now/auto_now_add options are applied. Which means the field won't show up in any admin form (though it seems this can be partially got round by setting the field read-only - not that this would be very useful to end users!).
0

Since Django 1.7 there is a function get_changeform_initial_data in ModelAdmin that sets initial form values:

def get_changeform_initial_data(self, request):
    return {'dt': datetime.now()}

1 Comment

This is nice, but it only works when adding new objects, not when changing existing ones.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.