pythonflaskanki

How can I access view random created folder in flask?


I have implement simple app in flask. I can get data and process it also but how can I get random created folder. In this app, I tried to input some data to text area. When export deck button clicked then the data post to flask. I can get data and generate deck also but unable send generated deck file or redirect to the random folder.

I get the following error.

raise TypeError(
TypeError: The view function did not return a valid response. The function either returned None or ended without a return statement.)

So, How can I implement this? Redirect to new random generated folder or send the generated file as download link.

Thanks

app.py

from flask import Flask, render_template, request, redirect, url_for, flash, send_file, send_from_directory
import image_occ_deck_export
import random, os

app = Flask(__name__)
app.config["CACHE_TYPE"] = "null"

@app.route("/", methods=["GET","POST"])
def home():
    if request.method == "POST":
        print(request.form['notes'])
        notes = request.form['notes']
        # random folder

        data = request.form['notes']
        print(data)

        random_f = random.randrange(1 << 30, 1 << 31)
        create_random_folder(random_f, data)

    else:
        return render_template("index.html")

        
def create_random_folder(random_f, data):
    directory = str(random_f)
    parent_dir = "static/uploads/"
    path = os.path.join(parent_dir, directory)

    if not os.path.exists(path):
        os.mkdir(path)

    random_file = directory + ".txt"
    random_deck_name = directory + ".apkg"


    file_loc = path + "/" + random_file

    deck_loc = path + "/" + random_deck_name

    with open(file_loc, 'w') as f:
        f.write(str(data))

    image_occ_deck_export.exportDeck(file_loc, deck_loc)

    return redirect(url_for('uploaded', path=path))

@app.route('/uploaded/<path>', methods=['GET'])
def uploaded():
    return render_template("upload.html")

if __name__ == "__main__":
    app.run(debug=False)

index.js

function export() {
    var textToExport = document.getElementById("noteData").value;
    var formData = new FormData();

    formData.append("notes", textToExport);

    var request = new XMLHttpRequest();
    request.open("POST", "/");
    request.send(formData);
}

index.html

<html>
<textarea id="noteData"></textarea>
<button onclick="export()">Export Deck</button>
</html>

sample input

cordova-img-occ-note-1602529000819      <img src='art-1851483_640.jpg'></img>   <img src='cordova-img-occ-ques-1602529000819.svg'></img>                        <img src='cordova-img-occ-ans-1602529000819.svg'></img> <img src='cordova-img-occ-orig-1602529000819.svg'></img>
cordova-img-occ-note-1602529001248      <img src='art-1851483_640.jpg'></img>   <img src='cordova-img-occ-ques-1602529001248.svg'></img>                        <img src='cordova-img-occ-ans-1602529001248.svg'></img> <img src='cordova-img-occ-orig-1602529000819.svg'></img>
cordova-img-occ-note-1602529001673      <img src='art-1851483_640.jpg'></img>   <img src='cordova-img-occ-ques-1602529001673.svg'></img>                        <img src='cordova-img-occ-ans-1602529001673.svg'></img> <img src='cordova-img-occ-orig-1602529000819.svg'></img>

image_occ_deck_export.py The file use to generate anki deck from txt

import random
import genanki
import csv

import traceback

anki_deck_title = "learn"

anki_model_name = "image occ"

model_id = random.randrange(1 << 30, 1 << 31)

def exportDeck(data_filename, deck_filename):
   try:
        
      # front side
      front = """
{{#Image}}
<div id="io-header">{{Header}}</div>
<div id="io-wrapper">
<div id="io-overlay">{{Question Mask}}</div>
<div id="io-original">{{Image}}</div>
</div>
<div id="io-footer">{{Footer}}</div>

<script>
// Prevent original image from loading before mask
aFade = 50, qFade = 0;
var mask = document.querySelector('#io-overlay>img');
function loaded() {
var original = document.querySelector('#io-original');
original.style.visibility = "visible";
}
if (mask === null || mask.complete) {
loaded();
} else {
mask.addEventListener('load', loaded);
}
</script>
{{/Image}}

"""

      style = """
/* GENERAL CARD STYLE */
.card {
font-family: "Helvetica LT Std", Helvetica, Arial, Sans;
font-size: 150%;
text-align: center;
color: black;
background-color: white;
}

/* OCCLUSION CSS START - don't edit this */
#io-overlay {
position:absolute;
top:0;
width:100%;
z-index:3
}

#io-original {
position:relative;
top:0;
width:100%;
z-index:2;
visibility: hidden;
}

#io-wrapper {
position:relative;
width: 100%;
}
/* OCCLUSION CSS END */

/* OTHER STYLES */
#io-header{
font-size: 1.1em;
margin-bottom: 0.2em;
}

#io-footer{
max-width: 80%;
margin-left: auto;
margin-right: auto;
margin-top: 0.8em;
font-style: italic;
}

#io-extra-wrapper{
/* the wrapper is needed to center the
left-aligned blocks below it */
width: 80%;
margin-left: auto;
margin-right: auto;
margin-top: 0.5em;
}

#io-extra{
text-align:center;
display: inline-block;
}

.io-extra-entry{
margin-top: 0.8em;
font-size: 0.9em;
text-align:left;
}

.io-field-descr{
margin-bottom: 0.2em;
font-weight: bold;
font-size: 1em;
}

#io-revl-btn {
font-size: 0.5em;
}

/* ADJUSTMENTS FOR MOBILE DEVICES */

.mobile .card, .mobile #content {
font-size: 120%;
margin: 0;
}

.mobile #io-extra-wrapper {
width: 95%;
}

.mobile #io-revl-btn {
font-size: 0.8em;
}

"""

      # back side
      back = """
{{#Image}}
<div id="io-header">{{Header}}</div>
<div id="io-wrapper">
<div id="io-overlay">{{Answer Mask}}</div>
<div id="io-original">{{Image}}</div>
</div>
{{#Footer}}<div id="io-footer">{{Footer}}</div>{{/Footer}}
<button id="io-revl-btn" onclick="toggle();">Toggle Masks</button>
<div id="io-extra-wrapper">
<div id="io-extra">
{{#Remarks}}
<div class="io-extra-entry">
<div class="io-field-descr">Remarks</div>{{Remarks}}
</div>
{{/Remarks}}
{{#Sources}}
<div class="io-extra-entry">
<div class="io-field-descr">Sources</div>{{Sources}}
</div>
{{/Sources}}
{{#Extra 1}}
<div class="io-extra-entry">
<div class="io-field-descr">Extra 1</div>{{Extra 1}}
</div>
{{/Extra 1}}
{{#Extra 2}}
<div class="io-extra-entry">
<div class="io-field-descr">Extra 2</div>{{Extra 2}}
</div>
{{/Extra 2}}
</div>
</div>

<script>
// Toggle answer mask on clicking the image
var toggle = function() {
var amask = document.getElementById('io-overlay');
if (amask.style.display === 'block' || amask.style.display === '')
amask.style.display = 'none';
else
amask.style.display = 'block'
}

// Prevent original image from loading before mask
aFade = 50, qFade = 0;
var mask = document.querySelector('#io-overlay>img');
function loaded() {
var original = document.querySelector('#io-original');
original.style.visibility = "visible";
}
if (mask === null || mask.complete) {
loaded();
} else {
mask.addEventListener('load', loaded);
}
</script>
{{/Image}}
"""
      
      # print(self.fields)
      anki_model = genanki.Model(
          model_id,
          anki_model_name,
          fields=[{"name": "id"},{"name": "Header"}, {"name": "Image"}, {"name": "Question Mask"}, {"name": "Footer"}, {"name": "Remarks"}, {"name": "Sources"}, {"name": "Extra 1"}, {"name": "Extra 2"}, {"name": "Answer Mask"}, {"name": "Original"}],
          templates=[
              {
                  "name": "Card 1",
                  "qfmt": front,
                  "afmt": back,
              },
          ],
          css=style,
      )

      anki_notes = []

      with open(data_filename, "r", encoding="utf-8") as csv_file:
          csv_reader = csv.reader(csv_file, delimiter="\t")
          for row in csv_reader:
              flds = []
              for i in range(len(row)):
                  flds.append(row[i])

              anki_note = genanki.Note(
                  model=anki_model,
                  fields=flds,
              )
              anki_notes.append(anki_note)

      random.shuffle(anki_notes)

      anki_deck = genanki.Deck(model_id, anki_deck_title)
      anki_package = genanki.Package(anki_deck)

      for anki_note in anki_notes:
          anki_deck.add_note(anki_note)

      
      anki_package.write_to_file(deck_filename)

      print("Deck generated with {} flashcards".format(
          len(anki_deck.notes)))

   except Exception:
       traceback.print_exc()

Solution

  • create_random_folder() returns a redirect, but when you call it from your home() request handler, you don’t do anything with the returned value and you don’t return a response in that code branch of your home() handler. It seems you intend to return that redirect from your home() handler like so:

    return create_random_folder(random_f, data)
    

    Remember, when you return a value from a function, you’re returning the value to the calling code, not to the browser. If you call a function from a request handler and receive a return value, that doesn’t automatically get sent back to the browser; you need to return it from the request handler.