from django.forms import model_to_dict from django.shortcuts import redirect from django.http import JsonResponse from django.views import generic from django.views.generic.edit import CreateView from django.contrib.auth.mixins import LoginRequiredMixin from django.core.exceptions import PermissionDenied from .models import TemaVCisleNode, RocnikNode, CisloNode, UlohaVzorakNode, UlohaZadaniNode, TreeNode, CastNode, TextNode, ReseniNode, PohadkaNode, OrgTextNode from .models.pomocne import Text, Obrazek from treenode import treelib import treenode.forms as f import treenode.templatetags as tnltt import treenode.serializers as vr import logging logger = logging.getLogger(__name__) class TNLData(object): def __init__(self,anode,parent=None, index=None): self.node = anode self.sernode = vr.TreeNodeSerializer(anode) self.children = [] self.parent = parent self.tema_in_path = False self.index = index if parent: self.tema_in_path = parent.tema_in_path if isinstance(anode, TemaVCisleNode): self.tema_in_path = True def add_edit_options(self): self.deletable = tnltt.deletable(self) self.editable_siblings = tnltt.editableSiblings(self) self.editable_children = tnltt.editableChildren(self) self.text_only_subtree = tnltt.textOnlySubtree(self) self.can_podvesit_za = tnltt.canPodvesitZa(self) self.can_podvesit_pred = tnltt.canPodvesitPred(self) self.appendable_children = tnltt.appendableChildren(self) print("appChld",self.appendable_children) if self.parent: self.appendable_siblings = tnltt.appendableChildren(self.parent) else: self.appendable_siblings = [] @classmethod def public_above(cls, anode): """ Returns output of verejne for closest Rocnik, Cislo or Problem above. (All of them have method verejne.)""" parent = anode # chceme začít už od konkrétního node včetně while True: rocnik = isinstance(parent, RocnikNode) cislo = isinstance(parent, CisloNode) uloha = (isinstance(parent, UlohaVzorakNode) or isinstance(parent, UlohaZadaniNode)) tema = isinstance(parent, TemaVCisleNode) if (rocnik or cislo or uloha or tema) or parent==None: break else: parent = treelib.get_parent(parent) if rocnik: return parent.rocnik.verejne() elif cislo: return parent.cislo.verejne() elif uloha: return parent.uloha.verejne() elif tema: return parent.tema.verejne() elif None: print("Existuje TreeNode, který není pod číslem, ročníkem, úlohou" "ani tématem. {}".format(anode)) return False @classmethod def all_public_children(cls, anode): for ch in treelib.all_children(anode): if TNLData.public_above(ch): yield ch else: continue @classmethod def from_treenode(cls, anode, user, parent=None, index=None): if TNLData.public_above(anode) or user.has_perm('auth.org'): out = cls(anode,parent,index) else: raise PermissionDenied() if user.has_perm('auth.org'): enum_children = enumerate(treelib.all_children(anode)) else: enum_children = enumerate(TNLData.all_public_children(anode)) for (idx,ch) in enum_children: outitem = cls.from_treenode(ch, user, out, idx) out.children.append(outitem) out.add_edit_options() return out @classmethod def from_tnldata_list(cls, tnllist): """Vyrobíme virtuální TNL, který nemá obsah, ale má za potomky všechna zadaná TNLData""" result = cls(None) for idx, tnl in enumerate(tnllist): result.children.append(tnl) tnl.parent = result tnl.index = idx result.add_edit_options() return result @classmethod def filter_treenode(cls, treenode, predicate): tnll = cls._filter_treenode_recursive(treenode, predicate) # TreeNodeList List :-) return TNLData.from_tnldata_list(tnll) @classmethod def _filter_treenode_recursive(cls, treenode, predicate): if predicate(treenode): return [cls.from_treenode(treenode)] else: found = [] for tn in treelib.all_children(treenode): result = cls.filter_treenode(tn, predicate) # Result by v tuhle chvíli měl být seznam TNLDat odpovídající treenodům, jež matchnuly predikát. for tnl in result: found.append(tnl) return found def to_json(self): #self.node = anode #self.children = [] #self.parent = parent #self.tema_in_path = False #self.index = index out = {} out['node'] = self.sernode.data out['children'] = [n.to_json() for n in self.children] out['tema_in_path'] = self.tema_in_path out['index'] = self.index out['deletable'] = self.deletable out['editable_siblings'] = self.editable_siblings out['editable_children'] = self.editable_children out['text_only_subtree'] = self.text_only_subtree out['can_podvesit_za'] = self.can_podvesit_za out['can_podvesit_pod'] = self.can_podvesit_pred out['appendable_children'] = self.appendable_children out['appendable_siblings'] = self.appendable_siblings return out def __repr__(self): return("TNL({})".format(self.node)) class TreeNodeView(generic.DetailView): model = TreeNode template_name = 'treenode/treenode.html' def get_context_data(self,**kwargs): context = super().get_context_data(**kwargs) context['tnldata'] = TNLData.from_treenode(self.object,self.request.user) return context class TreeNodeJSONView(generic.DetailView): model = TreeNode def get(self,request,*args, **kwargs): self.object = self.get_object() data = TNLData.from_treenode(self.object,self.request.user).to_json() return JsonResponse(data) class TreeNodePridatView(generic.View): type_from_str = { 'rocnikNode': RocnikNode, 'cisloNode': CisloNode, 'castNode': CastNode, 'textNode': TextNode, 'temaVCisleNode': TemaVCisleNode, 'reseniNode': ReseniNode, 'ulohaZadaniNode': UlohaZadaniNode, 'ulohaVzorakNode': UlohaVzorakNode, 'pohadkaNode': PohadkaNode, 'orgText': OrgTextNode, } def post(self, request, *args, **kwargs): ######## FIXME: ROZEPSANE, NEFUNGUJE, DOPSAT !!!!!! ########### node = TreeNode.objects.get(pk=self.kwargs['pk']) kam = self.kwargs['kam'] co = self.kwargs['co'] typ = self.type_from_str[co] raise NotImplementedError('Neni to dopsane, dopis to!') if kam not in ('pred','syn','za'): raise ValidationError('Přidat lze pouze před nebo za node nebo jako syna') if co == TextNode: new_obj = Text() new_obj.save() elif co == CastNode: new_obj = CastNode() new_obj.nadpis = request.POST.get('pridat-castNode-{}-{}'.format(node.id,kam)) new_obj.save() elif co == ReseniNode: new_obj = m pass elif co == UlohaZadaniNode: pass elif co == UlohaReseniNode: pass else: new_obj = None if kam == 'pred': pass if kam == 'syn': if typ == TextNode: text_obj = Text() text_obj.save() node = treelib.create_child(node, typ, text=text_obj) else: node = treelib.create_child(node, typ) if kam == 'za': if typ == TextNode: text_obj = Text() text_obj.save() node = treelib.create_node_after(node, typ, text=text_obj) else: node = treelib.create_node_after(node, typ) return redirect(node.get_admin_url()) class TreeNodeSmazatView(generic.base.View): def post(self, request, *args, **kwargs): node = TreeNode.objects.get(pk=self.kwargs['pk']) if node.first_child: raise NotImplementedError('Mazání TreeNode se syny není zatím podporováno!') treelib.disconnect_node(node) node.delete() return redirect(request.headers.get('referer')) class TreeNodeOdvesitPrycView(generic.base.View): def post(self, request, *args, **kwargs): node = TreeNode.objects.get(pk=self.kwargs['pk']) treelib.disconnect_node(node) node.root = None node.save() return redirect(request.headers.get('referer')) class TreeNodePodvesitView(generic.base.View): def post(self, request, *args, **kwargs): node = TreeNode.objects.get(pk=self.kwargs['pk']) kam = self.kwargs['kam'] if kam == 'pred': treelib.lower_node(node) elif kam == 'za': raise NotImplementedError('Podvěsit za není zatím podporováno') return redirect(request.headers.get('referer')) class TreeNodeProhoditView(generic.base.View): def post(self, request, *args, **kwargs): node = TreeNode.objects.get(pk=self.kwargs['pk']) treelib.swap_succ(node) return redirect(request.headers.get('referer')) #FIXME ve formulari predat puvodni url a vratit redirect na ni class SirotcinecView(generic.ListView): model = TreeNode template_name = 'treenode/orphanage.html' def get_queryset(self): return TreeNode.objects.not_instance_of(RocnikNode).filter(root=None,prev=None,succ=None,father_of_first=None) # FIXME pouzit Django REST Framework class TextWebView(generic.DetailView): model = Text def get(self,request,*args, **kwargs): self.object = self.get_object() return JsonResponse(model_to_dict(self.object,exclude='do_cisla')) class VueTestView(generic.TemplateView): template_name = 'treenode/vuetest.html' class NahrajObrazekKTreeNoduView(LoginRequiredMixin, CreateView): model = Obrazek form_class = f.NahrajObrazekKTreeNoduForm def get_initial(self): initial = super().get_initial() initial['na_web'] = self.request.FILES['upload'] return initial def form_valid(self,form): print(self.request.headers) print(self.request.headers['Textid']) print(form.instance) print(form) self.object = form.save(commit=False) print(self.object.na_web) self.object.text = Text.objects.get(pk=int(self.request.headers['Textid'])) self.object.save() return JsonResponse({"url":self.object.na_web.url})