Форма и mptt mix в одностраничном приложении с django
Я занимаюсь разработкой веб-приложения, которое выглядит как настольное приложение. При запуске приложения определенные элементы видны по умолчанию. Среди которых, справа, у меня есть меню, показывающее структуру каталогов в виде дерева. Для этого я использую django-mptt и jquery.fancytree. У меня также есть выпадающее меню навигации с несколькими страницами формы. Эта форма изначально скрыта css. Когда пользователь нажимает на раскрывающийся список, отображается эта разбитая на страницы форма (для ясности программы показана только одна страница). Когда пользователь сохраняет (публикует) форму, я хочу опубликовать ее в единственном представлении, которое создало одну страницу.
I have two problems:
1) On form post, this error shows up (source of error line 192):
VariableDoesNotExist at / Failed lookup for key [drive_nodes] in "[{'True': True, 'False': False, 'None': None}, {}, {}]"
...
191 <ul id="drive-tree-data">
192 {% recursetree drive_nodes %}
193 <li class="context-menu-one">
...
2) On form cancel, the single page is reloaded!!
Я думаю, что мой URL не является правильным в обеих задачах, и именно поэтому переменная drive_nodes больше не определяется, и страница перезагружается! Хотя, я знаю, пост восходит к одной и той же записи, просмотр.
Пожалуйста, помогите мне решить проблему. Смотрите соответствующие коды ниже. И одна версия кода до того, как стать одностраничным приложением, развернута в облаке Google для тех из вас, кто хочет увидеть приложение. Просто зайдите на: www.rsmfront.com и зарегистрируйтесь по любому адресу электронной почты.
models.py
==========
from mptt.models import MPTTModel, TreeForeignKey
class RSMDriveModel(MPTTModel):
name = models.CharField(max_length=50, unique=False)
parent = TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True, on_delete=models.CASCADE)
def __str__(self):
return self.name
class MPTTMeta:
order_insertion_by = []
views.py
=========
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from .models import RSMDriveModel
from .forms import ControlElementForm
def rsmgui_home(request):
template_name = 'rsmgui_nav.html'
drive_nodes = RSMDriveModel.objects.all()
if request.POST:
form = ControlElementForm(request.POST)
if form.is_valid():
messages.success(request, 'Your data was saved successfully!')
return render(request, template_name)
else:
messages.error(request, form.errors)
boundfield_list = tuple(ControlElementForm())
page = request.GET.get('page', 1)
paginator = Paginator(boundfield_list, 10)
try:
elements = paginator.page(page)
except PageNotAnInteger:
elements = paginator.page(1)
except EmptyPage:
elements = paginator.page(paginator.num_pages)
context = {
'drive_nodes': drive_nodes,
'elements': elements,
}
return render(request, template_name, context)
urls.py
========
from .views import rsmgui_home
urlpatterns = [
url(r'^$', rsmgui_home, name='rsmgui_home'),
]
rsmgui_nav.html
===============
<!DOCTYPE html>
<!--[if IE 9]>
<html class="lt-ie10" lang="en"> <![endif]-->
<html class="no-js" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- load library tags -->
{% load static %}
{% load mptt_tags %}
<!-- bootstrap local css -->
<link href="{% static 'bootstrap-3.3.7/css/bootstrap.min.css' %}" rel="stylesheet" type="text/css"/>
<link href="{% static 'bootstrap-select-1.12.4/css/bootstrap-select.min.css' %}" rel="stylesheet" type="text/css"/>
<link href="{% static 'jQuery-contextMenu/dist/jquery.contextMenu.min.css' %}" rel="stylesheet">
<link href="//cdn.jsdelivr.net/npm/jquery.fancytree@2.27/dist/skin-win8/ui.fancytree.min.css" rel="stylesheet">
<!-- Add custom CSS in static file -->
<link rel="shortcut icon" type="image/png" href="{% static 'img/favicon.png' %}"/>
<link rel="stylesheet" type="text/css" href="{% static 'css/rsmgui_style.css' %}"/>
<script src="{% static 'jquery/jquery-3.3.1.min.js' %}"></script>
<script src="{% static 'jquery/jquery-ui.min.js' %}"></script>
<script src="{% static 'jQuery-contextMenu/dist/jquery.contextMenu.min.js' %}"></script>
<script src="{% static 'jQuery-contextMenu/dist/jquery.ui.position.min.js' %}"></script>
<script src="//cdn.jsdelivr.net/npm/jquery.fancytree@2.27/dist/jquery.fancytree-all-deps.min.js"></script>
<script>
$(function(){ // on page load
// Create the tree inside the div element.
$(".tree").fancytree({
expandLazy: true,
extensions: [],
}); // fancytree
// Note: Loading and initialization may be asynchronous, so the nodes may not be accessible yet.
}); // end of onload
</script>
</head>
<body>
<nav class="navbar navbar-default navbar-custom navbar-fixed-top" role="navigation">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#topNavBar"
aria-expanded="false" aria-controls="topNavBar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div> <!-- navbar-header -->
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="topNavBar">
<ul class="nav navbar-nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button">Input/Output<span
class="caret"></span>
</a>
<ul class="dropdown-menu" role="dropdown">
<li><a id="std_xmlinput" name="rsminput" href="">New XML Input File</a></li>
</ul>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
<div id="content" class="container-fluid">
<div class="row">
<div class="col-sm-8 col-md-8">
<div id="center_wrapper" class="container-fluid">
<br>
{% include 'messages.html' %}
<form class="form-horizontal hide" id="input-form" role="form" action="" method="post"
enctype="multipart/form-data">
{% csrf_token %}
<div class="card dragthis">
<!-- Card image -->
<div class="card-banner">
<div class="row">
<div class="col col-sm-7">
<p>Model Input: <Control Elements></p>
</div>
<div class="col col-sm-5 text-right">
<div class="btn-group" role="group" aria-label="input-xml">
<button id="input-submit" type="submit" class="btn btn-default btn-trans"
data-toggle="tooltip" data-placement="bottom" title="save">
<span class="glyphicon glyphicon-save"></span>
</button>
<button type="button" class="btn btn-default btn-trans" data-toggle="tooltip"
data-placement="bottom" title="reset">
<span class="glyphicon glyphicon-minus"></span>
</button>
<button id="input-close" type="button" class="btn btn-default btn-trans"
data-toggle="tooltip" data-placement="bottom" title="close">
<span class="glyphicon glyphicon-remove"></span>
</button>
</div>
</div>
</div>
</div>
<!-- Card content -->
<div class="card-body">
<br>
{% for boundfield in elements %}
<div class="form-group">
<label class="control-label col-sm-5" style="text-align:right;"
for="{{boundfield.id_for_label}}">{{ boundfield.label }}
</label>
<div class="col-sm-7" id="{{boundfield.id_for_label}}"
aria-describedby="{{boundfield.id_for_label}} | addstr:ex">{{ boundfield }}
</div>
</div>
{% if boundfield.help_text %}
<p class="col-sm-offset-5 col-sm-7">
<small style="color: grey">{{ boundfield.help_text|safe }}</small>
</p>
{% endif %}
{% for error in boundfield.errors %}
<div class="col-sm-offset-2 col-sm-10"><span class="text-danger small">{{ error }}</span>
</div>
{% endfor %}
{% endfor %}
</div>
<!-- For pagination-->
<div class="text-center">
{% if elements.has_other_pages %}
<ul class="pagination">
{% if elements.has_previous %}
<li><a href="?page={{ elements.previous_page_number }}">«</a></li>
{% else %}
<li class="disabled"><span>«</span></li>
{% endif %}
{% for i in elements.paginator.page_range %}
{% if elements.number == i %}
<li class="active"><span>{{ i }} <span class="sr-only">(current)</span></span></li>
{% else %}
<li><a href="?page={{ i }}">{{ i }}</a></li>
{% endif %}
{% endfor %}
{% if elements.has_next %}
<li><a href="?page={{ elements.next_page_number }}">»</a></li>
{% else %}
<li class="disabled"><span>»</span></li>
{% endif %}
</ul>
{% endif %}
</div>
</div>
<!-- Card Light -->
</form>
</div>
</div>
<div class="col-sm-4 col-md-4">
<div id="wrapper" class="active">
<div id="sidebar-wrapper">
<div class="rsm-menu-toolbar-wrapper container-fluid">
<ul id="rsm-menu-toolbar" class="nav nav-tabs" role="tablist">
<li class="nav-item active">
<a class="nav-link" id="drive-tab" data-toggle="tab" href="#drive"
role="tab" aria-controls="drive" aria-selected="false"
data-placement="bottom"
title="RSM read-only shared drive containing src, libraries, trainings, benchmarks, etc.">
<span class="glyphicon glyphicon-hdd" style="color:black"></span>
</a>
</li>
</ul>
<div class="tab-content" id="rsm-menu-toolbar-content">
<div class="tab-pane fade in active" id="drive" role="tabpanel" aria-labelledby="drive-tab">
<div class="tree">
<ul id="drive-tree-data">
{% recursetree drive_nodes %}
<li class="context-menu-one">
{{ node.name }}
{% if not node.is_leaf_node %}
<ul class="children context-menu-one">
{{ children }}
</ul>
{% endif %}
</li>
{% endrecursetree %}
</ul>
</div>
</div>
</div> <!-- end of tab-content -->
</div> <!-- end of rsm-menu-toolbar-wrapper -->
</div> <!-- end of sidebar-wrapper -->
</div> <!-- end of wrapper -->
</div> <!-- end of col-sm-4 -->
</div>
</div>
<script src="{% static 'bootstrap-3.3.7/js/bootstrap.min.js' %}"></script>
<script src="{% static 'bootstrap-select-1.12.4/js/bootstrap-select.min.js' %}"></script>
<script type="text/javascript">
$(document).ready(function() {
// for sidebar menu icon
$("#menu-toggle").click(function(e) {
e.preventDefault();
$("#wrapper").toggleClass("active");
});
// for all dropdown menus
$( "#std_xmlinput" ).click(function() {
$("#input-form").removeClass("hide").addClass("show");
});
$('#input-close').on('click',function() {
$("#input-form").removeClass("show").addClass("hide");
});
function expandNode(mynode, depth) {
// Expand this mynode
mynode.load(true).done(function(){
mynode.setExpanded(true);
});
// Reduce the depth count
depth--;
// If we need to go deeper
if (depth > 0) {
for (var i = 0; i < mynode.children.length; i++) {
// Go recursive on child nodes
expandNode(mynode.children[i], depth);
}
}
}
expandNode($("#drive-tree-data").fancytree("getRootNode"), 2);
}); // end of document
</script>
</body>
</html>