Preserve newlines in file rendered to HTML with Jinja - python

I am trying to print the content of a file in a web page. I want to print each line from the file on a separate line, but instead the line breaks are missing. How do I print the file and preserve newlines?
#app.route('/users')
def print_users():
v = open("users.txt","r").read().strip()
# also tried:
# v = open("users.txt","r").read().strip().split('\n')
return render_template('web.html', v=v)
{{ v|safe}}

You can use :
v = open("users.txt","r").readlines()
v = [line.strip() for line in v]
and then in your html something like (but feel free to play around with it):
<form action="/print_users" method="post" >
<div class="form-inline">
{% for line in v %}
<div>{{ line|safe}}</div>
{% endfor %}
<input class="btn btn-primary" type="submit" value="submit" >
</div>
</form>

While the other answers give great techniques and the current accepted solution works, I needed to do a similar task (rendering a text email template), but needed to extend this to preserve the processing of macros within the file, which led me to create what I think is the simplest and most elegant solution - using render_template_string.
def show_text_template(template_name):
"""
Render a text template to screen.
Replace newlines with <br> since rendering a template to html will lose the line breaks
:param template_name: the text email template to show
:return: the text email, rendered as a template
"""
from flask import render_template_string
txt_template = open(
'{}/emails/{}{}'.format(app.config.root_path + '/' + app.template_folder, template_name, '.txt'),
"r").readlines()
return render_template_string('<br>'.join(txt_template))

Related

Django-.csv file is not properly storing

views.py
def preprocessedDatafile(request):
file2 = request.FILES["myfile"]
dtf = pd.DataFrame(file2)
dtf.to_csv(
"E:/Preprocessed/preprocessed data.csv"
)
return render(request, "preprocessedDatafile.html")
In the above pd is the panadas library object.
.html
<form class="grid" method="POST" action="{% url 'preprocessedDatafile' %}" enctype="multipart/form-data">
{% csrf_token %}
<div style="border: 1px dashed rgb(148,10,34); width:59%" >
<br/><br/>
<input type="file" class='upload-box' accept=".csv" name='myfile'/>
<br/><br/><br/>
</div>
<button type="submit" id="btn" ><b>Submit</b></button>
</form>
I am making a web page, where I have to read a csv file and then store this csv file in a specific location. What I want to do is done but the new csv that I am storing have some garbage data and all data is storing in one column. I want to store new file data same as the original file data. For more understanding the picture of original file is:
and the picture of new file that is currently storing is:
I hope you understood what I am taking. Is there a way to get the same data as in the original file in the new file that I am storing.
I used the below code in the views.py file and my problem is resolved.
def preprocessedDatafile(request):
file2 = request.FILES["myfile"]
dtfb = pd.read_csv(file2)
dtf = pd.DataFrame(dtfb)
dtf.to_csv(
"E:/Preprocessed/preprocessed data.csv"
)
return render(request, "preprocessedDatafile.html")

How to implement an external python code to a Django web server?

as from the title, I am trying to implement an external python code to a Django web server.
I am quite new to programming so any hints will be surely helpful.
Long story short: I am trying to set up a form where the user have to insert an aminoacidic sequence. This sequence should pass to my python script, that is able to compare it with all the sequences already present in the database and gives as a result the most similar ones. My problem is that I am not able to let my form and my script talk each others.
I have followed the Django documentation here https://docs.djangoproject.com/en/3.2/topics/forms/ but this did't helped too much.
Also roaming online and browse already asked questions here was unfruitful.
Please find here below the files:
BLAST_page.html (tried both, commented and uncommented)
{% extends "base_generic.html" %}
{% block content %}
<div class="container-fluid" style="text-align: center;" ></div>
<form method="post" action= {% url 'BLAST-process' %}>
{% csrf_token %}
{{ blast }}
<label for="sequence">Type or paste your sequence in the box below</label><br><br>
<input type="text" id="sequence" class="input_text" name="sequence" value="{{ sequence }}" style="width:600px; height:200px;"><br><br>
<input type="submit" value="Submit">
</form>
</div>
{% endblock %}
<!--
<div class="container-fluid" style="text-align: center;" >
<form method="POST" action= {% url 'BLAST-process' %}>
{% csrf_token %}
<label for="sequence">Type or paste your sequence in the box below</label><br><br>
<input type="text" id="sequence" class="input_text" name="sequence" value="{{ sequence }}" style="width:600px; height:200px;"><br><br>
<input type="submit" value="Submit">
</form>
</div>
-->
In order to check if this form works, I have used this simple .php script. The reasoning behind is that if the form works correctly, the inserted data should be echoed. But this doesn't happen.
<html>
<body>
Sequence: <?php echo $_POST["sequence"]; ?><br>
<?php
echo "<h2>Your Input:</h2>";
echo $sequence;
?>
</body>
</html>
forms.py
from django import forms
class blast(forms.Form):
sequence = forms.CharField(help_text="Enter a sequence", label='sequence')
blast.py the script that should receive data from the form
from Bio.Blast.Applications import NcbiblastpCommandline
from io import StringIO
from Bio.Blast import NCBIXML
from Bio.Seq import Seq
from Bio.SeqRecord import SeqRecord
from Bio import SeqIO
import numpy as np
# Create two sequence files
#taken from the textArea.
sequence = sequence
seq1 = SeqRecord(Seq(sequence), id="x")
SeqIO.write(seq1, "seq1.fasta", "fasta")
#SeqIO.write(seq2, "seq2.fasta", "fasta")
# Run BLAST and parse the output as XML
output = NcbiblastpCommandline(query="seq1.fasta",
subject="/Users/santarpia/Documents/tutorial/codorenv/RepOdor/FASTA/db.fasta",
outfmt=5)()[0]
blast_result_record = NCBIXML.read(StringIO(output))
# Print some information on the result
for alignment in blast_result_record.alignments:
for hsp in alignment.hsps:
print('***Alignment****\n')
print('Alignment title', alignment.title)
print('Alignment Length:', alignment.length)
print('E-value:', hsp.expect)
print('Gaps:', hsp.gaps)
print('Identities:', hsp.identities)
print('Positives:', hsp.positives)
print('Score:', hsp.score)
print('Bits:', hsp.bits)
print('Coverage:', hsp.align_length)
print('% Identity:', np.round((hsp.identities / hsp.align_length) * 100, 2))
print("\n")
print (hsp.query[0:])
print("\n")
print (hsp.match[0:])
print("\n")
print (hsp.sbjct[0:])
print('****************************\n\n\n')
As said, any comment on how to set up this would be highly appreciated. If you need more files or information to answer to my question, feel free to ask for them.
So if you followed the documentation correctly after submitting the sequence to the form the code should "enter" the if request.method == 'POST' portion of the view. You can verify this by putting a print("hello world") statement under the if (or an import pdb; pdb.set_trace()). Once there, you can get the sequence from the form with sequence = form.cleaned_data['sequence']. Now to pass it to your script you need your script to be a method that can take in an input (the sequence) so wrap you script in something like def findMostSimilarSequence(sequence): and remove that first line sequence = sequence then in your view you can import the method and call it with the sequence varible from your form.

Django: Use text box data and write that text in a file

I am super new to Django and web development. Right now my objective is to create a google like interface and take the text from search box and write it to a file (in other words just want to access text data in the search box). I have created a search page like below
search.html
{% extends "header.html" %}
{% block content %}
<div style="display: flex; justify-content: center;">
<img src="/static/images/logo.jpg" class="responsive-img" style='max-height:300px;' alt="face" >
</div>
<form method="get" action="">
{% csrf_token %}
<div style="display: flex; justify-content: center;">
<input type="text" name="query" placeholder="Search here..." required size="70" >
<button type="submit">Go!</button>
</div>
<button type="submit">Search</button>
</form>
{% endblock %}
views.py
from django.shortcuts import render
def index(request):
return render(request, 'search.html')
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index')
]
Please give me a hint/example of how to go forward from here ? Thanks.
Your search field looks like this:
<input type="text" name="query">
The name of the input is query. Since it's a GET form, when you submit it, you must have noticed, the url looks something like this:
/?query=<value of the input>
The part after ? is called querystring. For every request, Django maintains a dictionary of the querystring. The request object has a dictionary called GET for GET requests. If you make a POST request, Django will save the form data in a dict called POST.
To access the value of the request querystring in Django, you can do this:
query = request.GET.get('query')
If it's a POST request, you'd do the same but use the POST dictionary this time:
some_value = request.POST.get('some_key')
Full docs on this can be found at - Request and response objects.
This should do it
views.py
def index(request):
query = request.GET.get('query')
# do a check here to make sure search_term exists before attempting write
with open('/path/to/file', 'rw') as f:
f.write(query)
return render(request, 'search.html')

django output writing to a text file as temporary storage (over-written with each submission)

I have managed to configure a system, using django, that allows me to upload a file to my media-folder. I have (using simple-html) included a drop-down menu that will specify parameters that will be considered when processing the uploaded file in a pipeline.
<form action="{% url "list" %}" method="post" enctype="multipart/form-data">
<tr>
{% csrf_token %}
<p>{{ form.non_field_errors }}</p>
<p>{{ form.docfile.label_tag }} {{ form.docfile.help_text }}</p>
<p>
{{ form.docfile.errors }}
{{ form.docfile }}
</p>
</tr>
<tr>
<th>Genome Dataset</th>
<TD WIDTH = 80% ALIGN=left VALIGN=top>
<SELECT NAME='genome' ID='genome'>
<OPTION>All</OPTION>
<OPTION>Neanderthal</OPTION>
<OPTION>hg38 Human</OPTION>
<OPTION>Denisovan</OPTION>
</SELECT>
</tr>
<p><input type="submit" value="Upload"/></p>
</form>
I need to send the selected dropdown option to a text file. and I have attempted to do so as follows in views.py. However. while the file uploads to the media folder successfully, no text file manifests in the media folder- which is needed.
def GenomesView(request):
if request.method == 'GET':
getgen = request.GET.get('genome')
content = ContentFile(getgen)
f = open(os.path.join(settings.MEDIA_ROOT, 'file.txt'), 'w')
myfile = File(f)
myfile.write(getgen)
myfile.close()
The location of the media folder is as below in settings.
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
Hence my question is how do I take the selected option forms the drop-down and each time the file is uploaded to the site, the selection is sent to text file that will be over-written for each new submission (acting as a temporary storage for the selected option parameter i.e "Neanderthall" etc. as seen in code above)?
It looks like you are using a form to POST this data, but only writing to the file if the request is a GET. Try changing it to a POST. Also, since request.POST.get('genome') should return a string for you to write to the file there is no need to wrap it in a ContentFile. Try this:
if request.method == 'POST':
getgen = request.POST.get('genome')
with open(os.path.join(settings.MEDIA_ROOT, 'file.txt'), 'w') as f:
f.write(getgen)
I also changed your file handling to use a context manager.

Django upload and process file with no data retention

Python: 2.7.11
Django: 1.9
I want to upload a csv file to Django and analyze it with a Python class. No saving is allowed and the file is only needed to reach the class to be analyzed. I'm using Dropzone.js for the form but I don't understand how I should configure/program the views to achieve this.
<form action="/upload/" method="post" enctype="multipart/form-data" class="dropzone" id="dropzone">
{% csrf_token %}
<div class="fallback">
<input name="file" type="file" multiple />
</div>
</form>
I have found an article about this but it describes saving and is based on Django 1.5.
view.py
def upload(request):
if request.method == 'POST':
file = FileUploadForm(request.POST)
if file.is_valid():
return HttpResponseRedirect('/upload/')
else:
file = FileUploadForm()
return render(request, 'app/upload.html', {'file': file})
forms.py
from django import forms
class FileUploadForm(forms.Form):
file = forms.FileField()
Closing Update:
The most important difference between the helping answer and my situation is that I had to decode my input.
See the following line as mine csv_file in handle_csv_data:
StringIO(content.read().decode('utf-8-sig'))
Access the csv file in the view function. If you are using python 3, you must wrap the InMemoryUploadedFile in a TextIOWrapper to parse it with the csv module.
In this example the csv is parsed and passed back as a list named 'content' that will be displayed as a table.
views.py
import csv
import io # python 3 only
def handle_csv_data(csv_file):
csv_file = io.TextIOWrapper(csv_file) # python 3 only
dialect = csv.Sniffer().sniff(csv_file.read(1024), delimiters=";,")
csv_file.seek(0)
reader = csv.reader(csv_file, dialect)
return list(reader)
def upload_csv(request):
csv_content=[]
if request.method == 'POST':
csv_file = request.FILES['file'].file
csv_content = handle_csv_data(csv_file)
return render(request, 'upload.html', {'content':content})
Your original code did not use django's form framework correctly, so I just dropped that from this example. So you should implement error handling when the uploaded file is invalid or missing.
upload.html
<form action="/upload/"
method="post"
enctype="multipart/form-data"
class="dropzone"
id="dropzone">
{% csrf_token %}
<div class="fallback">
<input name="file" type="file"/>
<input type="submit"/>
</div>
</form>
{% if content %}
<table>
{% for row in content %}
<tr>
{% for col in row %}
<td>{{ col }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
{% endif %}
I've added a 'submit' button so this works without the dropzone thing. I also removed 'multiple' from the file input, to keep the example simple. Finally there's a table if the template receives content from a parsed csv. But when using dropzone.js, you have to use a javascript callback function to display the table.

Categories