Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Admin popup functionality

This topic is fairly common (most explicitly detailed here: http://www.hoboes.com/Mimsy/hacks/replicating-djangos-admin/), but I'm still having trouble with it. I'm trying to use the "plus" button functionality used in the admin site where one can add an additional foreign key to a linked entry. In the admin site, a popup displays allowing the user to submit a new field and then that new value is populated on the original form.

I think my issue centers around the inclusion of this line:

within the base.html template and the popadd.html template. Clicking the plus button does not bring up a new window. The popadd template simply loads in the same tab. And submitting a new entry does not take the user back to the original form.

The admin site is functional. I am including ADMIN_MEDIA_PREFIX = '/media/admin/' in the settings.py file. Does it have something to do with where the RelatedObjectLookups.js lives? It's currently in an admin directory outside of my project folder. Do I have to create a symlink?

Sorry for the noob questions. Would appreciate any suggestions (as detailed as possible).

like image 211
Ed. Avatar asked Feb 27 '10 14:02

Ed.


People also ask

How do I use popups in Django?

Html content rendered by this view will be loaded into bootstrap dialog. Create your popup view same as normal django view. If user click on the element with the attribute data-popup-view-value , the value of this attribute will be set in form field and dialog will close.

What we can do in admin portal in Django?

Overview. The Django admin application can use your models to automatically build a site area that you can use to create, view, update, and delete records. This can save you a lot of time during development, making it very easy to test your models and get a feel for whether you have the right data.

Can I use Django admin as frontend?

Django Admin is one of the most important tools of Django. It's a full-fledged application with all the utilities a developer need. Django Admin's task is to provide an interface to the admin of the web project. Django's Docs clearly state that Django Admin is not made for frontend work.


1 Answers

Following the steps outlined below will allow you to recreate Django admin's related object pop-up functionality without having to create any custom widgets, views, and urls. These steps assume you are trying to get this pop-up working in your own custom admin site which subclasses Django's admin.

Lets assume the following two models Book and Author, with an FK from Book to Author. Lets also assume that we'll want the ability to use the Related Object Pop-Up 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)

Lets create our custom admin site:

[app_name]/sites.py:

from django.contrib.admin.sites import AdminSite

my_admin_site = AdminSite(name='my_custom_admin')

Our custom admin site will register two ModelAdmins to allow users to add/edit/delete both the Book and Author models:

[app_name]/admin.py:

from django.contrib.admin.options import ModelAdmin

from [app_name].forms import BookForm # We'll create this form below
from [app_name].models import Author, Book
from [app_name].sites import my_admin_site

class BookModelAdmin(ModelAdmin):
    form = BookForm()

# Register both models to our custom admin site
my_admin_site.register(Author, ModelAdmin)
my_admin_site.register(Book, BookModelAdmin)

Now, we'll setup the BookForm which is used in the BookModelAdmin above. This is where the magic happens. For more info on the RelatedFieldWidgetWrapper api, click here:

[app_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:

  1. You will need to ensure that these two javascript files included in your templates: admin/js/core.js and admin/js/admin/RelatedObjectLookups.js.

Gotchas:

  1. is_popup needs to be set and passed correctly in your templates. Specifically, in any custom change_form.html templates you override, you must remember to add this line somewhere within your form tags: {% if is_popup %}<input type="hidden" name="_popup" value="1" />{% endif %}, so that the logic in BaseModelAdmin.response_add() returns the correct response.

Under The Hood: Essentially, we're re-using the form processing logic, widget wrapper and javascript that is already included with Django admin.

  1. Using RelatedFieldWidgetWrapper to wrap the widget associated to the related object field in our form (and specifically passing can_add_related=True in the constructor) tells the widget to append the necessary '+' link with the appropriate javascript onclick event attached to it.
  2. Django admin's javascript handles all of the logic necessary to launch the pop-up.
  3. The {% if is_popup %}...{% endif %} logic in our change_form.html template(s) and the logic in BaseModelAdmin.response_add() handles the saving of the new related object and returns the appropriate javascript response that informs the pop-up that it needs to be closed.

Related Repo: This public repo should provide sample code for the Django project discussed above: https://github.com/cooncesean/Books

like image 182
cooncesean Avatar answered Sep 28 '22 11:09

cooncesean