I want to create a link which opens the django admin add page of a model with some fields pre filled.
I checked that it is possible to add parameters to the GET dict
It appears the problem is your passing a string when it expects a date. You need to convert your string into a date first.
You can use the built in python library datetime:
import datetime
value = datetime.datetime.strptime(value, "%Y-%m-%d %H:%M:%S")
def decompress(self, value):
...
Edit: alecxe correctly pointed out that I was not properly answering your question. With a bit of a searching I found something that might be more relevant.
According to this answer, Django allows you to replace the GET dictionary before it is processed. Borrowing from this example, it seems feasible that we could intercept your get parameters and replace the string dates with datetime objects in the GET dictionary
def add_view(self, request, form_url='', extra_context=None):
// any extra processing can go here...
g = request.GET.copy()
g.update({
'date':datetime.datetime.strptime(request.GET.get('date'), "%Y-%m-%d %H:%M:%S"),
})
request.GET = g
return super(MyModelAdmin, self).add_view(request, form_url, extra_context)
No, it isn't a bug; there's maybe an argument that the default behaviour could be improved, but the existing implementation is a reasonable first pass (as evidenced by the fact that it works on integers, strings, foreign keys, etc). There's enough metadata about the model, and enough deserialization code that it would be possible to do slightly better handling here, but I don't think it's a straight up bug.
The good news is that there is an official way to handle this; on your ModelAdmin
class, define:
def get_changeform_initial_data(self, request):
This method takes the request, and converts that request into the value that will be passed in as the initial
argument to the form on a change list (i.e., an add or edit page in Admin). As you might expect, the default implementation of this method is "take the GET arguments and convert into a dictionary"; if you do some additional handling for the fields that you know to be datetimes, then
Alternatively, you don't have to use the request object at all. If you know that "Person" objects will always have an initial name of "Unknown", and an initial start date of 1 Jan 2014, then you can just write:
class PersonAdmin(ModelAdmin):
...
def get_changeform_initial_data(self, request):
return {
'name': 'Unknown',
'start_date': date(2014, 1, 1)
}
i.e., don't pay any attention to the request data, just populate the initial data manually. Since it's initial data to the form, any existing data on the object will override the value provided in initial
, and that initial data will be used without the user needing to provide any GET
arguments in their request.