Gauravwagh / django-grappelli

Automatically exported from code.google.com/p/django-grappelli
Other
0 stars 0 forks source link

reorder inlines #265

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
see http://code.djangoproject.com/ticket/14238

with grappelli, just remove the comments from the inline-templates and add the 
sortable-script ... that´s the easy part.
more challenging ... write a patch for django in order to retrieve the 
ordered-forms in case of an error.

Original issue reported on code.google.com by sehmaschine on 9 Sep 2010 at 11:14

GoogleCodeExporter commented 9 years ago

Original comment by sehmaschine on 15 Sep 2010 at 3:26

GoogleCodeExporter commented 9 years ago
This issue was closed by revision r1152.

Original comment by klemens.mantzos on 20 Sep 2010 at 3:33

GoogleCodeExporter commented 9 years ago
reopen:
a) testing is needed.
b) rename sort-field.
c) documentation is missing.

Original comment by sehmaschine on 20 Sep 2010 at 3:45

GoogleCodeExporter commented 9 years ago
styles are needed as well.

Original comment by sehmaschine on 20 Sep 2010 at 3:46

GoogleCodeExporter commented 9 years ago
 * sortable feature for existing inlines only (django.contib.admin throws
exception if you sort a new inline within the existing ones)
 * added basic placeholder (styling still needed)

what should be the correct/new name for the "sort_field_name" property?

Original comment by klemens.mantzos on 20 Sep 2010 at 4:52

GoogleCodeExporter commented 9 years ago
first, I think we shouldn´t commmit half-baked stuff (styling is not a 
blocker, but not being able to add new items is definitely one) - so, that code 
shouldn´t land in trunk.

still have to think about the naming ...

Original comment by sehmaschine on 20 Sep 2010 at 5:00

GoogleCodeExporter commented 9 years ago
I have a drag-n-drop sorting implementation that allows for sorting new inlines 
(once they have at least one field filled in), running in a customized 
Grappelli.  Would you like to have a look?  (It's much simpler, and it doesn't 
currently permit the use of any field as the sort order field, but maybe it 
could serve as a reference to figure out how to make Grappelli's implementation 
work.)

Original comment by ringe...@gmail.com on 20 Sep 2010 at 5:30

GoogleCodeExporter commented 9 years ago
@ringmeup: how can you (re)order without an order-field? there has to be a 
db-field storing the order, right? anyway ... yes, I´d like to have a look.

Original comment by sehmaschine on 20 Sep 2010 at 5:36

GoogleCodeExporter commented 9 years ago
@ringmeup – additional question: with your implementation, the ordering is 
preserved in case of errors, right?

Original comment by sehmaschine on 20 Sep 2010 at 5:40

GoogleCodeExporter commented 9 years ago
It does use a DB field for the order, just assumes that it has a particular 
name.  Basically, I had implemented this for private use, and figured I could 
use the same field name for all sortable inlines in my own projects.  For the 
same reason, 
I haven't tested it yet with date, RelatedLookup, or TinyMCE fields, although 
I'm sure it could be adapted to those.  And the code is ugly in places, but it 
works.

Currently it preserves the new order numbers after an error, but not actual 
ordering.  It shouldn't be too hard to add something to re-sort on page load, 
though.

Here's the code.  It depends on the following jQuery UI modules:

jquery.ui.core
jquery.ui.widget
jquery.ui.mouse
jquery.ui.sortable

#Start code
##############

django.jQuery(function($) {
    $("div.inline-group").sortable({ 
        //axis: 'y',
        placeholder: 'ui-state-highlight', 
        forcePlaceholderSize: 'true', 
        items: 'div.inline-related', 
        update: function() {
            $('div.inline-related', this).each(function(i) {
                // Only update the position for inlines that actually have data; otherwise we'll throw errors for any inlines that the user left empty
                if (
                            !isNaN(parseInt($('input[id$=position]', this).eq(0).val()))
                            && (
                                $('input[type!="hidden"][value!=""]:not([id$=position]):not([id$=DELETE])', this).length
                                || $('textarea[value!=""]', this).length
                                || $('select[value!=""]', this).length
                            )
                        ) 
                { // the inline does have data, so set position to the new number
                    $('input[id$=position]', this).eq(0).val(i+1);
                }
        });
      }
    });
    $("div.inline-group").disableSelection();

});

// use different cursor for draggables
django.jQuery(document).ready(function($){
    $('input[id$=position]').parent('div').parent('div').parent('div.inline-related').css('cursor','move');
});

Original comment by ringe...@gmail.com on 20 Sep 2010 at 5:57

GoogleCodeExporter commented 9 years ago
thanks a lot - we´ll take a closer look at your script. that being said, 
preserving the order in case of errors is _very_ important to us (and we don´t 
want to re-sort on page-load).

Original comment by sehmaschine on 20 Sep 2010 at 6:24

GoogleCodeExporter commented 9 years ago
How are you currently handling order preservation?  (I can't make it out from 
the changeset.)  Would it make sense to sort the forms of the formset on either 
the view or template level before outputting them?  The ordering data is 
transmitted with the form submission, so it's there to use.  

Original comment by ringe...@gmail.com on 20 Sep 2010 at 6:39

GoogleCodeExporter commented 9 years ago
preserving the order is done by (re)setting the form-prefixes within the 
formset.

problem is, that django should return ordered forms anyway (at least when I set 
can_order). unfortunately, that´s not the case.

Original comment by sehmaschine on 21 Sep 2010 at 10:05

GoogleCodeExporter commented 9 years ago
@ringemup: and you can actually add an inline and order it on top off the 
existing ones - save - and not getting an python error (because the id field of 
the new inline is empty)?

what django version are you using?

(your code looks like it works if you have 1 inline in your changeform only, 
right?)

Original comment by klemens.mantzos on 21 Sep 2010 at 11:39

GoogleCodeExporter commented 9 years ago
Ah, that's the Django bug that's holding this up?  

I haven't done a whole lot of work with formsets, but is that something we can 
fix by subclassing the admin inline classes or ModelFormset?

Original comment by ringe...@gmail.com on 21 Sep 2010 at 11:40

GoogleCodeExporter commented 9 years ago
 > Ah, that's the Django bug that's holding this up?

kind of. so you didn't fixed that "sort new inlines on top of existing 
ones"-issue either? thx anyway

Original comment by klemens.mantzos on 21 Sep 2010 at 11:45

GoogleCodeExporter commented 9 years ago
> so you didn't fixed that "sort new inlines on top of existing ones"-issue 
either?

I'm not understanding what that issue is.  The code I posted allows you to 
drag-and-drop sort any inlines, including ones that were blank when the form 
was loaded, or that were created on the fly using the "Add another <whatever>" 
link.

Oops, missed your other comment...

>You can actually add an inline and order it on top off the existing ones - 
save - and not getting an python error (because the id field of the new inline 
is empty)?

Yes, absolutely, and I do it all the time.  It just won't set the order field 
on an inline unless there's already another field in the inline that has a 
value.  (If you set the order field on all inlines in the formset, then any 
intentionally empty inlines at the bottom of the formset would be given a 
non-empty field and would cause validation to throw errors on any other 
required fields in the model).  Ideally, it would be able to use the same logic 
to tell which inlines are empty as the formset itself does after submission, 
but I never bothered looking that up -- however, it looks like you have a way 
to do that with a single function call in your code.

> what django version are you using?

1.2

> (your code looks like it works if you have 1 inline in your changeform only, 
right?)

It works with as many inlines as you like.  I have it on one admin screen that 
takes three different inlines -- two tabular and one stacked.

Original comment by ringe...@gmail.com on 21 Sep 2010 at 11:57

GoogleCodeExporter commented 9 years ago
@ringemup: so the only drawback on your version is that the inlines loose the 
order (after submit) if you have an error in your change_form?

i.e.:
1) sort inlines as i like.
2) leave a required field empty (not necessarily in the inlines)
3) submit
=> get an error message, and inlines have the old order

Original comment by klemens.mantzos on 21 Sep 2010 at 1:06

GoogleCodeExporter commented 9 years ago
Correct.  And after error they actually still have the correct value in the 
order field, just the wrong display order -- which is something that could be 
fixed by either sorting before output, or sorting via javascript.

I'd also want to fix the following issues in my code before releasing it to a 
wider audience:

1) expects the field that stores the order to be called "position"
2) code to determine which inlines are empty is a fairly ugly hack, and may not 
work with all field types, fields with initial values, etc. at present

BTW, credit where credit is due, my code is adapted from:
http://djangosnippets.org/snippets/1053/ and its comments

Original comment by ringe...@gmail.com on 21 Sep 2010 at 1:15

GoogleCodeExporter commented 9 years ago
made an update in trunk r1156:

improved sortable inlines feature:
 * works with new inlines
 * keeps order if error occurs
 * improved check is_form_filled()

Original comment by klemens.mantzos on 22 Sep 2010 at 1:19

GoogleCodeExporter commented 9 years ago
set axis to 'y'.

Original comment by sehmaschine on 22 Sep 2010 at 3:16

GoogleCodeExporter commented 9 years ago
Is this now implemented in trunk? Is it possible to document how to get it 
working? I currently have a model with a field called "order". How do I 
activate the drag and drop? Setting "sortable=True" in the admin doesn't seem 
to work. Nor does creating a model form that calls in "ordering.js". 

Sorry if this is premature, but I'd love to get this working with my 
installation.

Thanks.

Original comment by dmee...@gmail.com on 26 Sep 2010 at 5:17

GoogleCodeExporter commented 9 years ago
implemented in trunk.

take a look at this:
http://code.google.com/p/django-grappelli/wiki/Upgrade_2_2

and here is how you add the sortable feature to you inlines:
http://code.google.com/p/django-grappelli/wiki/inlinemodeladminoptions_2_2#sorta
ble_inlines

Original comment by klemens.mantzos on 2 Oct 2010 at 11:23

GoogleCodeExporter commented 9 years ago
Might be working for Stacked and tabularinlines, but what about 
GenericTabularInline?

Original comment by sertech...@gmail.com on 14 Oct 2010 at 10:13

GoogleCodeExporter commented 9 years ago
@sertechaun: drag/drop with GenericTabularInline works for me ... what exactly 
doesn´t work for you?

Original comment by sehmaschine on 14 Oct 2010 at 10:30