Repository: stephenmcd/mezzanine

Issue:
Can't make a page an existing page's child
In my page tree, I have to root-level pages:
![two pages](https://f.cloud.github.com/assets/421710/4483/0df21e36-4311-11e2-8872-f0cba4fe2f56.png)
I want to make 'asdf' an child of 'foo bar':
![desired](https://f.cloud.github.com/assets/421710/4479/dd5c4846-4310-11e2-8fa8-1b25eaec27d3.png)
But when dragging I can only reorder the pages, not make one a child of the other.



Discussion:
Thanks Gavin. This has been a known issue for a while - the drop doesn't work because there's no list in the underlying HTML to drop it onto. A work-around is to add a temporary child page to the parent, then you'll be to drag a page to the parent, and remove the temporary child.

We actually had a fix committed for this a while back, but it made the tree look quite clunky so it was pulled out (I can't find the commit at the moment).

We'll leave this issue open to track it.

Ok. Can you let me know if you find the commit? I think I'll take a crack at this, and see if we can get it to look nice too.

Found it! 

https://github.com/stephenmcd/mezzanine/pull/188


Resolving patch:
diff --git a/mezzanine/pages/views.py b/mezzanine/pages/views.py
--- a/mezzanine/pages/views.py
+++ b/mezzanine/pages/views.py
@@ -2,6 +2,7 @@
 from django.contrib.admin.views.decorators import staff_member_required
 from django.core.exceptions import ImproperlyConfigured
 from django.http import HttpResponse, Http404
+from django.shortcuts import get_object_or_404
 
 from mezzanine.conf import settings
 from mezzanine.pages import page_processors
@@ -13,34 +14,38 @@
 page_processors.autodiscover()
 
 
+def get_id(s):
+    id = s.split("_")[-1]
+
+    if id == 'null':
+        return None
+
+    return id
+
+
 def admin_page_ordering(request):
     """
     Updates the ordering of pages via AJAX from within the admin.
     """
-    get_id = lambda s: s.split("_")[-1]
-    for ordering in ("ordering_from", "ordering_to"):
-        ordering = request.POST.get(ordering, "")
-        if ordering:
-            for i, page in enumerate(ordering.split(",")):
-                try:
-                    Page.objects.filter(id=get_id(page)).update(_order=i)
-                except Exception, e:
-                    return HttpResponse(str(e))
-    try:
-        moved_page = int(get_id(request.POST.get("moved_page", "")))
-    except ValueError, e:
-        pass
-    else:
-        moved_parent = get_id(request.POST.get("moved_parent", ""))
-        if not moved_parent:
-            moved_parent = None
-        try:
-            page = Page.objects.get(id=moved_page)
-            page.parent_id = moved_parent
-            page.save()
-            page.reset_slugs()
-        except Exception, e:
-            return HttpResponse(str(e))
+    page = get_object_or_404(Page, id=get_id(request.POST['id']))
+
+    old_parent_id = page.parent_id
+    new_parent_id = get_id(request.POST['parent_id'])
+
+    if page.parent_id != new_parent_id:
+        page.parent_id = new_parent_id
+        page.save()
+        page.reset_slugs()
+
+        old_siblings = Page.objects.order_by('_order').filter(
+            parent_id=old_parent_id,
+        )
+        for i, old_sibling in enumerate(old_siblings):
+            Page.objects.filter(id=old_sibling.id).update(_order=i)
+
+    for i, new_sibling in enumerate(request.POST.getlist('siblings[]')):
+        Page.objects.filter(id=get_id(new_sibling)).update(_order=i)
+
     return HttpResponse("ok")
 admin_page_ordering = staff_member_required(admin_page_ordering)
 


Test patch: