3

In Django's admin, I've seen how I can set the fields of an 'add object' form using GET variables (e.g. /admin/app/model/add?title=lol sets the 'Title' field to 'lol').

However, I want to be able to do something along the lines of /admin/app/model/add?key=18 and load default data for my fields from an instance of another model. Ideally, I'd also like to be able to do some processing on the values that I populate the form with. How do I do this?

avramov
  • 2,119
  • 2
  • 18
  • 41

2 Answers2

6

I managed to figure it out. Thankfully, Django allows you to replace a request's GET dict (which it uses to pre-populate the admin form). The following worked for me:

class ArticleAdmin(admin.ModelAdmin):
    # ...

    def add_view(self, request, form_url='', extra_context=None):
        source_id = request.GET.get('source', None)
        if source_id is not None:
            source = FeedPost.objects.get(id=source_id)
            # any extra processing can go here...
            g = request.GET.copy()
            g.update({
                'title': source.title,
                'contents': source.description + u"... \n\n[" + source.url + "]",
            })
            request.GET = g

        return super(ArticleAdmin, self).add_view(request, form_url, extra_context)

This way, I obtain the source object from a URL parameter, do what I want with them, and pre-populate the form.

Nitin Nain
  • 5,113
  • 1
  • 37
  • 51
avramov
  • 2,119
  • 2
  • 18
  • 41
2

You can override method add_view of ModelAdmin instance. Add getting an object there, set object's pk to None and provide that object as an instance to the form. Object with pk == None will be always inserted as a new object in the database on form's save()

ilvar
  • 5,718
  • 1
  • 20
  • 17
  • I'm not sure what you mean. I played around with add_view; however, the super method returns a rendered form, and I don't know how to populate it beforehand. – avramov Apr 19 '12 at 13:59
  • 1
    Don't use super method yet. Just change [form creation](https://code.djangoproject.com/browser/django/trunk/django/contrib/admin/options.py#L936) so it could get and use an object as `initial`. You can also override `get_form` and create a form class with correct `instance` built-in, it will be more DRY but also more complicated code. – ilvar Apr 19 '12 at 15:24