sehmaschine / django-grappelli

A jazzy skin for the Django Admin-Interface (official repository).
http://www.grappelliproject.com
Other
3.73k stars 659 forks source link

Filter functionality on admin pages don't work unless actions = None on ModelAdmins #214

Closed karansag closed 2 years ago

karansag commented 11 years ago

Hi all,

Unless actions = None in my ModelAdmin class definitions, grappelli raises and javascript exception and the filter functionality (with fields defined in list_filter) breaks. The dropdown button shows up but nothing drops down when you click on it.

The error is "Uncaught TypeError: Object [object Object] has no method 'actions' " on the line $("tr input.action-select").actions(); (line 66 in the grappelli template).

The relevant code snippet from the grappelli code

Also, I think this might be similar to Issue #206.

I'm using Django 1.4.1 and Grappelli 2.4.2

ecederstrand commented 8 years ago

marcoooo,

Is grappelli first in INSTALLED_APPS?

INSTALLED_APPS = (
    'grappelli',
    'django.contrib.admin',
)

Did you run collectstatic? What is the output? Which filesystem path does it collect to? How are your static files served? Which filesystem path are they served from? Have you emptied your browser cache and any server caches for your static files?

myii commented 8 years ago

@marcoooo Based upon my long answer above and the follow-up by @Tatsh, I've got a 2-step summary for you:

  1. Clear/move the static/admin/js directory
  2. Run collectstatic again

As long as you've got the correct ordering as pointed out by @ecederstrand, you'll be good to go.

marcoooo commented 8 years ago

Hi All, thank for your quiclk response !

Still got this issue.

Django packages installed:

django-admin-sortable (2.0.18) django-authtools (1.5.0) django-bootstrap-themes (3.3.6) django-braces (1.9.0) django-ckeditor (5.1.0) django-cors-headers (1.1.0) django-countries (3.4.1) django-crispy-forms (1.6.0) django-crontab (0.7.1) django-debug-toolbar (1.5) django-eav (0.9.2, /home/marc/.virtualenvs/waves1/src/django-eav) django-environ (0.4.0) django-grappelli (2.8.1) django-ipware (1.1.5) django-jquery (1.12.2) django-jquery-ui (1.11.4.1) django-log-file-viewer (0.9) django-mail-templated (2.6.2) django-mptt (0.8.4) django-multiupload (0.5.1) django-nested-admin (3.0.8) django-polymorphic (1.0.1) django-registration (2.1.2) django-smart-selects (1.2.2) django-tabbed-admin (1.0.0) djangorestframework (3.4.0) djangorestframework-jwt (1.8.0) djangorestframework-xml (1.3.0) drfdocs (0.0.11)

Running on apache with static serving setup:

<Directory [ABSOLUTE_PATH_TO_WAVES_INSTALL_DIR]/src/waves_services> Options FollowSymLinks Indexes <Files wsgi.py> Require all granted </Files> </Directory> <Location /static> SetHandler None </Location> <Location /media> SetHandler None </Location> Alias /media [ABSOLUTE_PATH_TO_WAVES_INSTALL_DIR]/media Alias /static [ABSOLUTE_PATH_TO_WAVES_INSTALL_DIR]/staticfiles

To help: actions() function seems to be declared in actions.js, but this file is not loaded in my admin pages (I inherit base_site.html in my project). Should I force this inclsion in my template ? I didn't see any trace of this import in any template in Grappelli sources.

GOT IT ! This is what happens, I don't know how, but includes on actions.js seems to be lost somewhere, I forced inclusion in my admin base_site.html template, and now it works.

For future reference it could be helpfull. (But anyway, does this file should not be included in base_site.html grappelli file ?)

myii commented 8 years ago

I run collectstatic, admin files comme again (so I deleted the folder)

@marcoooo Only delete the folder before collectstatic. When you run collectstatic again, it produces the correct files that you need to keep.

ilosamart commented 7 years ago

Hello everyone! We have here the same issue but with a different scenario:

If someone else got this scenario beware. Our solution (for now) is to mannualy copy Grappelli's static files after collectstatic.

sehmaschine commented 2 years ago

Closing this since the issue is extremely outdated. If there is still something unresolved related to this topic, please open a new ticket.

MahrezBH commented 2 days ago

I faced this issue, which I believe may be due to compatibility problems with django-material or another frontend package. I tried all the above suggestions to fix it, but without success.

The only solution I found is to re-check the actions.js file (located either in your static/admin/js directory or the django/contrib/admin/static/admin/js directory)

The actions.js file:

(function($) {
    var lastChecked;

    $.fn.actions = function(opts) {
        var options = $.extend({}, $.fn.actions.defaults, opts);
        var actionCheckboxes = $(this);
        var list_editable_changed = false;
        var checker = function(checked) {
            if (checked) {
                showQuestion();
            } else {
                reset();
            }
            $(actionCheckboxes).prop("checked", checked)
                .parent().parent().toggleClass(options.selectedClass, checked);
        },
        updateCounter = function() {
            var sel = $(actionCheckboxes).filter(":checked").length;
            // _actions_icnt is defined in the generated HTML
            // and contains the total amount of objects in the queryset
            $(options.counterContainer).html(interpolate(
            ngettext('%(sel)s of %(cnt)s selected', '%(sel)s of %(cnt)s selected', sel), {
                sel: sel,
                cnt: _actions_icnt
            }, true));
            $(options.allToggle).prop("checked", function() {
                var value;
                if (sel == actionCheckboxes.length) {
                    value = true;
                    showQuestion();
                } else {
                    value = false;
                    clearAcross();
                }
                return value;
            });
        },
        showQuestion = function() {
            $(options.acrossClears).hide();
            $(options.acrossQuestions).show();
            $(options.allContainer).hide();
        },
        showClear = function() {
            $(options.acrossClears).show();
            $(options.acrossQuestions).hide();
            $(options.actionContainer).toggleClass(options.selectedClass);
            $(options.allContainer).show();
            $(options.counterContainer).hide();
        },
        reset = function() {
            $(options.acrossClears).hide();
            $(options.acrossQuestions).hide();
            $(options.allContainer).hide();
            $(options.counterContainer).show();
        },
        clearAcross = function() {
            reset();
            $(options.acrossInput).val(0);
            $(options.actionContainer).removeClass(options.selectedClass);
        };
        // Show counter by default
        $(options.counterContainer).show();
        // Check state of checkboxes and reinit state if needed
        $(this).filter(":checked").each(function(i) {
            $(this).parent().parent().toggleClass(options.selectedClass);
            updateCounter();
            if ($(options.acrossInput).val() == 1) {
                showClear();
            }
        });
        $(options.allToggle).show().click(function() {
            checker($(this).prop("checked"));
            updateCounter();
        });
        $("a", options.acrossQuestions).click(function(event) {
            event.preventDefault();
            $(options.acrossInput).val(1);
            showClear();
        });
        $("a", options.acrossClears).click(function(event) {
            event.preventDefault();
            $(options.allToggle).prop("checked", false);
            clearAcross();
            checker(0);
            updateCounter();
        });
        lastChecked = null;
        $(actionCheckboxes).click(function(event) {
            if (!event) { event = window.event; }
            var target = event.target ? event.target : event.srcElement;
            if (lastChecked && $.data(lastChecked) != $.data(target) && event.shiftKey === true) {
                var inrange = false;
                $(lastChecked).prop("checked", target.checked)
                    .parent().parent().toggleClass(options.selectedClass, target.checked);
                $(actionCheckboxes).each(function() {
                    if ($.data(this) == $.data(lastChecked) || $.data(this) == $.data(target)) {
                        inrange = (inrange) ? false : true;
                    }
                    if (inrange) {
                        $(this).prop("checked", target.checked)
                            .parent().parent().toggleClass(options.selectedClass, target.checked);
                    }
                });
            }
            $(target).parent().parent().toggleClass(options.selectedClass, target.checked);
            lastChecked = target;
            updateCounter();
        });
        $('form#changelist-form table#result_list tr').find('td:gt(0) :input').change(function() {
            list_editable_changed = true;
        });
        $('form#changelist-form button[name="index"]').click(function(event) {
            if (list_editable_changed) {
                return confirm(gettext("You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost."));
            }
        });
        $('form#changelist-form input[name="_save"]').click(function(event) {
            var action_changed = false;
            $('select option:selected', options.actionContainer).each(function() {
                if ($(this).val()) {
                    action_changed = true;
                }
            });
            if (action_changed) {
                if (list_editable_changed) {
                    return confirm(gettext("You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action."));
                } else {
                    return confirm(gettext("You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button."));
                }
            }
        });
    };
    /* Setup plugin defaults */
    $.fn.actions.defaults = {
        actionContainer: "div.actions",
        counterContainer: "span.action-counter",
        allContainer: "div.actions span.all",
        acrossInput: "div.actions input.select-across",
        acrossQuestions: "div.actions span.question",
        acrossClears: "div.actions span.clear",
        allToggle: "#action-toggle",
        selectedClass: "selected"
    };
})(django.jQuery);

This actions.js file contains the default actions handling script used by Django's admin interface to manage multiple selection checkboxes, ensuring proper handling of selected actions and form submissions. If you're still facing the issue, consider investigating other JS files in your setup that could be conflicting, or try updating your frontend packages to the latest compatible versions with Django.