Search code examples
javascriptpythonhtmldjangobpmn.io

Embedded BPMN editor needs a working download button with django


Currently I have a HTML Page which is embedding a BPMN Modeler via https://bpmn.io/. They way it works is that I've an empty .bpmn file in my media directory and everytime I visit my page e.g. it loads the empty .bpmn file and the user is free to model his own diagram from there.

Now I'd like for the user to be able to download his .bpmn file which he created on the page.

I've never worked with JS and Django before. I don't really know how to pass my modified .bpmn diagram back to my django view downlad function.

Let me show the code I've so far, starting with the bpmn.io script which enables the user to work with the diagram(modeler.html):

<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/assets/diagram-js.css"/>
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/assets/bpmn-font/css/bpmn.css"/>

<script src="https://unpkg.com/[email protected]/dist/bpmn-modeler.development.js"></script>
<script>
    function fetchDiagram(url) {
        return fetch(url).then(response => response.text());
    }

    var bpmnJS = new BpmnJS({
        container: '#canvas',
        width: '100%',
        height: '600px',
    });

    async function openDiagram() {
        const diagram = await fetchDiagram('static/bpmn/empty_bpmn.bpmn');
        try {
            await bpmnJS.importXML(diagram);
            viewer.get('canvas').zoom('fit-viewport');
        } catch (err) {

            console.error('something went wrong:', err);
        }
    }
    openDiagram();
</script>

and the belonging view functions to this(views.py):

def modeler(request):
    return render(request, 'core/modeler.html')

def download_bpmn(request):

    response = HttpResponse(content_type='application/bpmn')
    response['Content-Disposition'] = 'attachment; filename="your_diagram.bpmn"'
    return response

the download button(modeler.html):

<div class="col-2">
    <a class="btn btn-primary" href="{% url 'download_bpmn' %}"> Download </a>
</div>

TLDR: Is there a way to pass my bpmn diagram back to django so I can create a view function which enables the user to download his diagram?


Solution

  • I used ajax to do that. I send the XML to a view that creates and saves the document in a model that has a FileField, then you can provide the url of the document to the user.

    AJAX:

    async function exportDiagram() {
        const csrftoken = getCookie('csrftoken');
        try {
            var result = await bpmnModeler.saveXML({ format: true });
            $.ajax({
                type: 'POST',
                url: url,
                headers: {'X-CSRFToken': csrftoken},
                data: {'data' : result.xml},
                success: function(response){
                },
            })
    
        } 
        catch (err) {
            console.error('Erro ao salvar BPMN 2.0', err);
        }
    }
    $('#save-button').click(exportDiagram);
    

    VIEW:

    def modeler(request, pk):
        if request.method == "POST":
            content = request.POST.get('data')
            bpmn = Bpmn() 
            bpmn.Filefield.save(f'{diagrama.titulo}.bpmn', ContentFile(content))  
        return render(request, 'bpmn.html')