Hallo Leute,
ich hab mit Django ein Webinterface geschrieben was mir mehrere Textdateien schreibt. Jetzt suche ich nach einer brauchbaren Lösung wie ich die erstellten Dateien zur Verfügung stelle.
Das senden der Informationen aus dem Interface zu meinem Pythonscript geschieht über AJAX an einen View.
Mein Problem, das erstellen der Dateien kann schon mal mehrere Minuten dauern. Dh, meine view sollte irgendetwas zurückgeben, damit der AJAX Request nicht abgebrochen wird.
Meine Idee war einen Link zu einem Ordner zurück zu geben. In diesem Ordner will ich die Textdateien speichern, damit der User diese runterladen kann.
Kann mir jemand sagen welchen return ich in dem View machen muss? Wie kann ich das mit der Zeit lösen, also das ein User schon den Link bekommt, obwohl das ganze Script noch nicht fertig ist.
Django und erstellte Dateien downloaden
Hallo Jens,jens hat geschrieben:Der User bekommt keinen direkten Link zu einer Datei, sondern immer den selben Link zu einer Art "persönlichen Download Ordner" in dem alle schon fertig generierten Dateien aufgelistet werden.
ich würde gerne Deine Idee aufgreifen, mir fehlen im Moment ein paar Hinweise wie ich da vorgehen sollte.
Zum einen, was muss ich dem Browser für einen return geben, damit im Hintergrund mein pythoncode weiter arbeiten kann.
Zum anderen dieser quasi persönliche ordner, ich denke den muss ich doch irgendwie in meine urls.py eintrage damit ich da von außen drauf kann, oder?
Ich hab leider echt keine Idee wie ich da vorgehen soll und wäre für einen Hinweis dankbar...
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Einen Redirect zur generierten Datei. Oder, und das macht der MVV so, eine Seite mit "Datei anfordern" Link.würmchen hat geschrieben:Zum einen, was muss ich dem Browser für einen return geben, damit im Hintergrund mein pythoncode weiter arbeiten kann.
Wieso? Ich würde das in die statischen Dateien tun, das ist ja Unsinn es von Django ausliefern zu lassen.würmchen hat geschrieben:Zum anderen dieser quasi persönliche ordner, ich denke den muss ich doch irgendwie in meine urls.py eintrage damit ich da von außen drauf kann, oder?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Der Persönliche Ordner ist ja quasi nichts anderes, als die Daten welche Datei welcher User laden darf.
Als erstes würde ich mal das Model dazu aufbauen. Dann ein view der die Daten des Models anzeigt und da abhängig davon welcher User gerade eingeloggt ist.
Die urls muß natürlich auf diesen view zeigt...
EDIT: Das Grundproblem bleibt aber: Die sicherheit das nur ein berechtigter Anwender die Dateien laden kann.
Man kann die Dateien nicht im http doc root legen. Somit sind diese nicht per Apache downloadbar. Dann muß die django app selber die Dateien ausliefern, was etwas mehr Preformance kosten.
Eine andere Variante wäre es evtl. eine .htaccess dynamisch zu generieren und die Passwörter von django darein zu stecken. Oder aber den Zugriff auf die IP Adresse zu limitieren (was aber wohl nicht ganz sicher ist)...
Als erstes würde ich mal das Model dazu aufbauen. Dann ein view der die Daten des Models anzeigt und da abhängig davon welcher User gerade eingeloggt ist.
Die urls muß natürlich auf diesen view zeigt...
EDIT: Das Grundproblem bleibt aber: Die sicherheit das nur ein berechtigter Anwender die Dateien laden kann.
Man kann die Dateien nicht im http doc root legen. Somit sind diese nicht per Apache downloadbar. Dann muß die django app selber die Dateien ausliefern, was etwas mehr Preformance kosten.
Eine andere Variante wäre es evtl. eine .htaccess dynamisch zu generieren und die Passwörter von django darein zu stecken. Oder aber den Zugriff auf die IP Adresse zu limitieren (was aber wohl nicht ganz sicher ist)...
Einen Redirect zur generierten Datei. Oder, und das macht der MVV so, eine Seite mit "Datei anfordern" Link.
[/quote]
Genau so hab ich mir das auch vorgestellt. Mein Problem ist, das ich diese Abfrage mit AJAX sende und da auf eine Antwort gewartet wird. Ich mache das mit Jquery:
Meine view sieht an der Stelle so aus:
Jetzt fängt bei dem Funktionsaufruf createAllPdbFiles() mein Script an zu arbeiten und das brauch eben seine Zeit. WÄREND das arbeitet würde ich gerne auf eine Seite umleiten die mir diesen Link präsentiert auf dem der User dann nach XX Minuten die fertigen Dateien downloaden kann.
Ich hab aber keine Ahnung wie ich das vorzeitig "melde"...
Wäre für einen Tip nochmal dankbar.
[/quote]
Genau so hab ich mir das auch vorgestellt. Mein Problem ist, das ich diese Abfrage mit AJAX sende und da auf eine Antwort gewartet wird. Ich mache das mit Jquery:
Code: Alles auswählen
$("#get_all_pdb").livequery("click",function(){
var pdb_keys = ""
$("td.entry_key input[@type=checkbox][@checked]").each(function() {
pdb_keys = pdb_keys+" "+$(this).attr("value");
});
$.ajax({
type: "POST",
timeout: 600000,
data: "entry_key_string="+pdb_keys+"&database="+$("p input[@type=radio][@checked]").attr("value"),
url: "createpdb/",
beforeSend: function(){
$("#loader").show();
},
success: function(data) {
$('#result').after(data)
},
complete: function() {
$("#loader").hide();
}
});
});
Code: Alles auswählen
def createAllPdb(request):
from bif.interface.interface import WebInterface
from bif.interface.writer import CreatePdbFiles
from bif.interface import output
interface = WebInterface(request.POST['database'],
request.session.get('tablename'))
cursor = interface.getCursor()
creator = CreatePdbFiles(cursor,'logfile.log')
creator.createAllPdbFiles(request.POST['entry_key_string'])
return render_to_response('interface/addinfo.html',
{'result': 'nix',
'string':''})
Ich hab aber keine Ahnung wie ich das vorzeitig "melde"...
Ich dachte mir jetzt auch das ich das mit richtigen Dateien mache und diese in einem Ordner der eben direkt zugänglich ist bereit stelle.Leonidas hat geschrieben:Wieso? Ich würde das in die statischen Dateien tun, das ist ja Unsinn es von Django ausliefern zu lassen.
Wäre für einen Tip nochmal dankbar.
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Ich würde im View eine Art Token generieren, was an den User zurückgeschickt wird und gleichzeitig an den Dateigenerator in einem anderen Thread. Somit sieht der User den Link und die Dateil kann im Hintergrund erstellt werden.
Letztendlich hat man da dummerweise Race Conditions, d.h. der User kann schneller klicken als das die Datei erstellt wird.
Letztendlich hat man da dummerweise Race Conditions, d.h. der User kann schneller klicken als das die Datei erstellt wird.

My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Bin am überlegen wie ich das mit dem Token machen sollte. Ich denke gerade an sowas wie ein Systemaufruf mit & oder sowas in der Art. Mit Python threading habe ich keine Erfahrung. gibt es Befehle wie ich einen Funktionsaufruf im Hintergrund starten kann?Leonidas hat geschrieben:Ich würde im View eine Art Token generieren, was an den User zurückgeschickt wird und gleichzeitig an den Dateigenerator in einem anderen Thread. Somit sieht der User den Link und die Dateil kann im Hintergrund erstellt werden.
Letztendlich hat man da dummerweise Race Conditions, d.h. der User kann schneller klicken als das die Datei erstellt wird.
Mit der Race Condition will ich mir eine view erstellen, die den Inhalt des Ordners anzeigt, und somit die fertigen Dateien, wenn eine bestimmte Datei (xyz.log) vorhanden ist. Diese wollte ich dann einfach erstellen lassen wenn mein Script fertig ist. Ansonsten eben sowas wie "Dateien noch nicht ganz fertig, versuchen Sie es in wenigen Minuten noch einmal" oder sowas.
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Klar, geht beides. Mit Prozessen nutzt du einfach subprocess und lässt es asynchron laufen und mit Threads gibt es das Thread und threading Modul. Gerade ``thread.start_new_thread()`` ist, obwohl ich es nicht so besonders mag, sehr einfach zu nutzen.würmchen hat geschrieben:Bin am überlegen wie ich das mit dem Token machen sollte. Ich denke gerade an sowas wie ein Systemaufruf mit & oder sowas in der Art. Mit Python threading habe ich keine Erfahrung. gibt es Befehle wie ich einen Funktionsaufruf im Hintergrund starten kann?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Damit ich das richtig verstehe, dazu muss ich aber ein ausführbares python Script schreiben, wessen ich mit ARGV oder so Übergabeparameter übergebe. Ich kann nicht in meiner View das erzeugte Objekt und NUR die Funktion in einem extra Thread aufrufen, oder?
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Genau.würmchen hat geschrieben:Damit ich das richtig verstehe, dazu muss ich aber ein ausführbares python Script schreiben, wessen ich mit ARGV oder so Übergabeparameter übergebe.
Doch. Jetzt mal vorrausgesetzt das ganze ist threadsafe, aber sonst ja.würmchen hat geschrieben:Ich kann nicht in meiner View das erzeugte Objekt und NUR die Funktion in einem extra Thread aufrufen, oder?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Also das ganze sollte Threadsave sein, lesen tue ich Daten aus einer Datenbank, schreiben werde ich dann in einen eigenen Ordner...
Es würde dann ein Thread alle Dateien erstellen.
Hast Du zufällig ein gutes Beispiel für die Arbeit mit Threads? Hatte mal in Java mit Threads programmiert, also Grundkenntnisse sind da. Ich denke ich muss dann ein Threadclasse erzeugen und dieser dann das Objekt übergeben, die Threadklasse ruft dann die Funktion auf, was im Moment die View macht.
Hm, geht es dann direkt weiter in meiner view oder wird dann auch noch auf einen Rückgabewert gewartet oder sowas?
Es würde dann ein Thread alle Dateien erstellen.
Hast Du zufällig ein gutes Beispiel für die Arbeit mit Threads? Hatte mal in Java mit Threads programmiert, also Grundkenntnisse sind da. Ich denke ich muss dann ein Threadclasse erzeugen und dieser dann das Objekt übergeben, die Threadklasse ruft dann die Funktion auf, was im Moment die View macht.
Hm, geht es dann direkt weiter in meiner view oder wird dann auch noch auf einen Rückgabewert gewartet oder sowas?
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Ich habe dir doch gesagt was du brauchst, jetzt kannst du in der Dokumentation nachschlagen und/oder die Suchfunktion benuten um Beispiele zu finden.würmchen hat geschrieben:Hast Du zufällig ein gutes Beispiel für die Arbeit mit Threads? Hatte mal in Java mit Threads programmiert, also Grundkenntnisse sind da. Ich denke ich muss dann ein Threadclasse erzeugen und dieser dann das Objekt übergeben, die Threadklasse ruft dann die Funktion auf, was im Moment die View macht.
Auf was für einen Rückgabewert willst du denn warten? Wenn du den Thread synchronisierst, wozu brauchst du ihn dann überhaupt?würmchen hat geschrieben:Hm, geht es dann direkt weiter in meiner view oder wird dann auch noch auf einen Rückgabewert gewartet oder sowas?

My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Hallo, ich hab erst jetzt wieder Zeit um mich um dieses Problem zu kümmern und wollte jetzt nochmal um Hilfe bitten.
Das mit den Threads funktioniert und ich kann mir einen Link zurück geben lassen.
Ich wollte fragen, ob ich diesen Link gleich in einem neuen Fenster öffnen kann? Sozusagen als popup?
Sollte möglichst beides geschehen, also einmal den Link anzeigen und zum anderen den Link gleich in einem neuen Fenster öffnen.
Danke für eure Hilfe
Das mit den Threads funktioniert und ich kann mir einen Link zurück geben lassen.
Ich wollte fragen, ob ich diesen Link gleich in einem neuen Fenster öffnen kann? Sozusagen als popup?
Sollte möglichst beides geschehen, also einmal den Link anzeigen und zum anderen den Link gleich in einem neuen Fenster öffnen.
Danke für eure Hilfe
Suchst du dies?
Stefan
Code: Alles auswählen
<a href="..." target="_blank">Download</a>
Danke für die Antwort,
ich habe es mittlerweile so erledigt, dass ich einen button erzeuge, mit dem ich auf meine Downloadseite komme.
Diese ist dann einfach nur eine Liste mit Dateien, die bereits fertig erstellt wurden.
Dazu hab ich ein Model erzeugt, was userid, einen key, filename und location und so speichert und zusätzlich, ob die datei noch in arbeit ist oder schon fertig geschrieben wurde.
diese seite lasse ich mit javascript alle 20 sekunden neu laden, bis alle dateien erstellt wurden.
danke für eure hilfe
ich habe es mittlerweile so erledigt, dass ich einen button erzeuge, mit dem ich auf meine Downloadseite komme.
Diese ist dann einfach nur eine Liste mit Dateien, die bereits fertig erstellt wurden.
Dazu hab ich ein Model erzeugt, was userid, einen key, filename und location und so speichert und zusätzlich, ob die datei noch in arbeit ist oder schon fertig geschrieben wurde.
diese seite lasse ich mit javascript alle 20 sekunden neu laden, bis alle dateien erstellt wurden.
danke für eure hilfe