By following the steps below, you can recreate the functionality of the object related to administering Django without having to create any custom widgets, views, and URLs. These steps assume that you are trying to open this popup in your own admin site, which the Django administrator subclasses.
Suppose the following two models: Book and Author , with FK from book to author. Let's also assume that we need the ability to use a Linked pop-up object to add an author when creating / editing a book:
[app_name] /models.py:
from django.db import models class Author(models.Model): name = models.CharField(max_length=200) class Book(models.Model): author = models.ForeignKey(Author) title = models.CharField(max_length=200)
Allows you to create our custom website:
[app_name] /sites.py:
from django.contrib.admin.sites import AdminSite my_admin_site = AdminSite(name='my_custom_admin')
Our user admin site will register two ModelAdmins parameters so that users can add / edit / delete both books and authorβs models:
[app_name] /admin.py:
from django.contrib.admin.options import ModelAdmin from [app_name].forms import BookForm
Now we will configure BookForm , which is used in BookModelAdmin above. This is where the magic happens. For more information on the LinkedFieldWidgetWrapper api, click here :
[application_name] /forms.py:
from django.contrib.admin.widgets import RelatedFieldWidgetWrapper from django import forms from [app_name].models import Book from [app_name].sites import my_admin_site class BookForm(forms.ModelForm): author = Book._meta.get_field('author').formfield( widget=RelatedFieldWidgetWrapper( Book._meta.get_field('author').formfield().widget, Book._meta.get_field('author').rel, my_admin_site, can_add_related=True ) ) class Meta: model = Book
Notes:
- You will need to make sure that these two javascript files are included in your templates:
admin/js/core.js and admin/js/admin/RelatedObjectLookups.js .
Gotchas:
is_popup must be set and correctly passed in your templates. In particular, in any custom change_form.html templates that you override, you should remember to add this line to your form tags: {% if is_popup %}<input type="hidden" name="_popup" value="1" />{% endif %} , so the logic in BaseModelAdmin.response_add() returns the correct answer.
Under the hood: Essentially, we reuse the form processing logic, widget wrapper and javascript, which is already included in the Django admin.
- Using
RelatedFieldWidgetWrapper to wrap the widget associated with the corresponding field of an object in our form (and, in particular, pass can_add_related=True in the constructor), tells the widget to add the necessary "+" link with the corresponding onclick javascript event attached to it. - Django admin javascript handles all the logic needed to launch a popup.
- The logic
{% if is_popup %}...{% endif %} in our change_form.html template (s) and the logic in BaseModelAdmin.response_add() handles the saving of the new linked object and returns a corresponding javascript response that tells the popup that it must be closed.
Related repo: This public repo should provide sample code for the Django project discussed above: https://github.com/cooncesean/Books