Avoid Django to strip text file upload - django

I've been asked to convert a Python application into a Django one but I'm totally new to Django.
I have the following problem, when I upload a file text that must be read to save its content into a database I find that Django is striping the "extra" whitespaces and I must keep those whitespaces.
This is my template
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test</title>
</head>
<body>
{% if newdoc %}
<ul>
{% for line in newdoc %}
<li>{{ line }} </li>
{% endfor %}
</ul>
{% endif %}
<form action="{% url 'exam:upload' %}" method="post" enctype="multipart/form-data" content-type="text/plain">
{% 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>
<p><input type="submit" value="Upload" /></p>
</form>
</body>
This is what I have in the views.py
def upload(request):
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
newdoc = request.FILES['docfile']
form = DocumentForm()
return render(request, 'exam/upload.html', {'newdoc': newdoc, 'form': form})
else:
form = DocumentForm() # A empty, unbound form
return render(request, 'exam/upload.html', {
'form': form,
})
And this is my forms.py:
from django import forms
class DocumentForm(forms.Form):
docfile = forms.FileField(
label='Select a file',
help_text='max. 42 megabytes'
)
Now when I upload the file, it shows a random line like this:
"09000021009296401 02 b a b a b b b d b b d d a +8589 +03+6942 +03+1461 +00+5093 +00+2 +00+9237 +01+60 +01+00 +00"
While it should be this:
"09000021009296401 02 b a b a b b b d b b d d a +8589 +03+6942 +03+1461 +00+5093 +00+2 +00+9237 +01+60 +01+00 +00 "
I must keep the extra spaces and they save this information into a database, which I cannot correctly do if I don't have all the spaces that the file has.
Also, before you ask, It is not related with the print format of Django, since in a previous test I already tryed to save the information into the model, but it has the same problem with spaces.
Thanks everyone.

Change the template as follow:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test</title>
</head>
<body>
{% if newdoc %}
<pre><code>{% for line in newdoc %}{{ line|safe }}{% endfor %}</code></pre>
{% endif %}
<form action="{% url 'exam:upload' %}" method="post" enctype="multipart/form-data" content-type="text/plain">
{% 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>
<p><input type="submit" value="Upload" /></p>
</form>
</body>

Related

Using Flask and WTForms, how should one reference a server variable to modify upon form submit with POST?

If one wanted to operate the on the "next_object" what would need to be done to the code below to allow for the objects or an id of the object to be passed back to "send_and_receive():" with a post method?
For the sake of the people who want to immediately close this as a duplicate of referencing in an insecure way, I am asking for doing this with POST not GET.
routes.py code
#app.route('/statistics', methods=['POST'])
def send_and_receive():
reference_form = ReferenceForm()
if reference_form.object_approved.data:
library.approve_object(??reference_object_id_or_object??)
return redirect('index')
if reference_form.object_rejected.data:
library.reject_object(??reference_object_id_or_object??)
return redirect('index')
next_object = library.get_next()
return render_template('site.html', reference_form=reference_form, next_object=next_object)
site.html
{% extends "base.html" %}
{% block content %}
<form action="" method="post">
<p>{{next_object.string()}}</p>
<p>{{ reference_form.object_approved() }}</p>
<p>{{ reference_form.object_rejected() }}</p>
</form>
{% endblock %}
Forms.py code
class ReferenceForm(FlaskForm):
object_approved = SubmitField("Approve")
object_rejected = SubmitField("Reject")
Make sure that you set the app's SECRET_KEY and render out the hidden fields in the html template, including the automatically added (see documentation) csrf_token hidden field.
A simple example:
app.py
from flask import Flask, render_template, flash
from flask_wtf import FlaskForm
from wtforms import SubmitField, HiddenField
class ReferenceForm(FlaskForm):
object_id = HiddenField()
object_approved = SubmitField("Approve")
object_rejected = SubmitField("Reject")
app = Flask(__name__)
app.config['SECRET_KEY'] = '123456790'
#app.route('/', methods=['GET', 'POST'])
def index():
_form = ReferenceForm()
_form.object_id.data = 42
if _form.validate_on_submit():
flash('Object ID:{}'.format(_form.object_id.data))
print(_form.object_approved.data)
print(_form.object_rejected.data)
print(_form.object_id.data)
# process form blah blah
# would be usual to return a redirect here
return render_template('index.html', reference_form=_form)
if __name__ == '__main__':
app.run()
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class=flashes>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
<form action="" method="post">
{{ reference_form.object_id() }}
{{ reference_form.csrf_token() }}
<p>{{ reference_form.object_approved() }}</p>
<p>{{ reference_form.object_rejected() }}</p>
</form>
</body>
</html>
Note how the html gets rendered, especially the two hidden fields, object_id and csrf_token:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="" method="post">
<input id="object_id" name="object_id" type="hidden" value="42">
<input id="csrf_token" name="csrf_token" type="hidden" value="IjBjNGIwNWE2NDA5NDVmZjhiMjU3Y2E5YTIwY2QwMGVlMTMxYzViYzUi.X0oupA.g9KjI79vZvfEIW1mwzR7nvHc6Yc">
<p><input id="object_approved" name="object_approved" type="submit" value="Approve"></p>
<p><input id="object_rejected" name="object_rejected" type="submit" value="Reject"></p>
</form>
</body>
</html>

How do I style my user registration form using Bootstrap in DJango?

So I have the following user registration form which I want to style. My forms.py look something like this. :
from django.contrib.auth.models import User
from django import forms
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ['username','email','password']
Now this is my views.py:
class UserFormView(View):
form_class =UserForm
template_name = 'visit/registration/register.html'
def get(self,request):
form = self.form_class(None)
return render(request,self.template_name,{'form':form})
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
user =form.save(commit=False)
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user.set_password(password)
user.save()
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request,user)
return redirect('visit:index')
return render(request, 'visit/registration/register.html', {'form': form})
Now What I am getting a bit confused in HTML, since there is only one line which passes all these fields in the page together. So how M I supposed to style these fields separately.
{% extends 'visit/base.html'%}
{%block content%}
<!DOCTYPE html>
<html>
{% load staticfiles %}
<link rel = "stylesheet" type = "text/css" href = "{% static "visit/registration.css"%}">
<head>
<title></title>
</head>
<body>
<form method="POST" class = "sign-up-form">
{% csrf_token %} {{ form.as_p }}
<button type="submit">Submit</button>
</form>
</body>
</html>
{%endblock%}
You have multiple options, each one with its pros and cons:
1. Add custom css classes within forms.py
To use the simplicity of {{ form.as_p }} approach you could manually add classes to all your forms fields, e.g.:
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput(
attrs={'class' : 'your-custom-class'})
)
Note that it could be a challenge to render the form to be perfectly aligned with Bootstrap's style.
2. Render the form manually
You could write your form by hand within your template, e.g.:
<div class="form-group">
<label for="{{ form.password.id_for_label }}">
{% trans 'Password' %}
</label>
<input type="text" id="{{ form.password.id_for_label }}"
name="{{ form.password.html_name }}"
{% if form.password.field.required %}required{% endif %}
class="form-control{% if form.password.errors %} is-invalid{% endif %}"
value="{% if form.password.value %}{{ form.password.value }}{% endif %}">
{% if form.password.help_text %}
<small class="text-muted">
{{ form.password.help_text }}
</small>
{% endif %}
{% for err in form.password.errors %}
<span class="invalid-feedback">{{ err }}</span>
{% endfor %}
</div>
More info on rendering form fields manually can be found here.
The above snippet will use most of the functionality existing in the default django form renders methods, but on the other hand forces you to write a lot of boilerplate code which is harden to maintain in the long run.
3. Use 3rd party app as a mix of the first two options
You could use custom app to handle the rendering of the forms, a good example would be django-crispy-forms.
You can simply use django-bootstrap
This will automatically render the bootstrap form for you.
{% extends 'visit/base.html'%}
{% load bootstrap3 %}
{%block content%}
<!DOCTYPE html>
<html>
{% load staticfiles %}
<link rel = "stylesheet" type = "text/css" href = "{% static "visit/registration.css"%}">
<head>
<title></title>
</head>
<body>
<form method="POST" class = "sign-up-form">
{% csrf_token %}
{% bootstrap_form form %}
<button type="submit">Submit</button>
</form>
</body>
</html>
{%endblock%}

How to use Django template context processor and form together?

I am a newbie to Django. In a project I have to take inputs for multiple models in Django using forms.
For every model I have written functions (in views.py) and its corresponding Django template (in template folder).
Such as,my Add Teacher function is,
def add_teacher(request):
form = TeacherForm()
if request.method=="POST":
form = TeacherForm(request.POST)
if form.is_valid():
form.save(commit=True)
return index(request)
else:
print(form.errors)
return render(request,"billing/add_teacher.html",{"form":form})
And billing/add_teacher.html template is,
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Add Teacher</title>
</head>
<body>
<h1>Add a Discipline</h1>
<div>
<form id="teacher_form" method="post" action="/billing/add_teacher/">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
{{ field.errors }}
{{ field.help_text }}
{{ field }}
{% endfor %}
<input type="submit" name="submit" value="Add Teacher"/>
</form>
</div>
</body>
</html>
Now, I want to use a template for all of my functions.Such as, I want to use this template for all functions with the help of Django template context processor.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ title }}</title>
</head>
<body>
<h1>{{ h1 }}</h1>
<div>
<form id={{ form_id }} method="post" action="{{ action }}">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
{{ field.errors }}
{{ field.help_text }}
{{ field }}
{% endfor %}
<input type="submit" name="submit" value={{ value }}/>
</form>
</div>
</body>
</html>
But when I return render() function I only can set either context or form.Such as, I can use one of these,
return render(request,"billing/add_teacher.html",{"form":form})
or,
return render(request,"billing/add_teacher.html",context= context_dict)
How can I use both of these together?
Something like,
return render(request,"billing/add_teacher.html",{"form":form},context =context_dict)
Thank you.
Try the following
context_dict.update({"form":form})
return render(request, "billing/add_teacher.html", context=context_dict)

Display the content of many to many fields in django template

I want to know how it is possible to display many-to-many relations in the django template. I posted my views.py and my models.py. I tried to find the solution by myself but I didn't really understand how to solve the problem :/
models.py
class topic(models.Model):
topic = models.TextField(verbose_name = 'Thema')
learningObjectivesTopic = models.ManyToManyField(learningObjective, verbose_name = "Lernziel")
class learningObjective(models.Model):
learningObjectives = models.TextField(verbose_name = 'Lernziel')
views.py
#login_required(login_url='login')
def themen(request):
return render(request, 'themen.html')
#login_required(login_url='login')
def create_themen(request):
neueThemen=topic(topic=request.POST['thema'])
neueThemen.save()
neueThemen_Lernziel=learningObjective(learningObjectives=request.POST['Lernziel'])
neueThemen_Lernziel.save()
neueThemen.learningObjectivesTopic.add(neueThemen_Lernziel)
return render(request, 'themen.html', {'thema': topic.objects.all(), 'lernziel': learningObjective.objects.all()})
and my unfinished template "themen.html"
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<form action="{% url 'create_themen' %}" method="post">
{% csrf_token %}
<br>Hallo Benutzer: {{ user.username }}</br>
<br>Thema: <textarea name="thema" rows="3" cols="45"></textarea></br>
<br>Lernziel: <textarea name="Lernziel" rows="3" cols="45"></textarea></br>
<input type="submit" value="Absenden" />
<br>Aktuelle Themen:</br>
</form>
{% for thema_ in thema %}
{{ thema_.topic }}<br/>
{{ thema_.
{% endfor %}
</body>
</html>
Given the thema object, if you want to display the many to many fields,
{% for topic in thema %}
{{topic.topic}}
{% for lo in topic.learningObjectivesTopic.all %}
{{lo.learningObjectivesTopic}}
{% endfor %}
{% endfor %}

How to delete files in Django?

I followed this tutorial: Need a minimal Django file upload example
Obviously it works. But I want to be able to delete a file as well. Now even if I delete it manually from disc, it still appears on list, even after reconnecting to a server (why?)
I changed the list.html file by adding another form in the loop:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Minimal Django File Upload Example</title>
</head>
<body>
<!-- List of uploaded documents -->
{% if documents %}
<ul>
{% for document in documents %}
<li>{{ document.docfile.name }}
{% if user.is_staff %}
<form action="{% url 'delete' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="submit" value="Delete" />
</form>
{% endif %}
</li>
{% endfor %}
</ul>
{% else %}
<p>No documents.</p>
{% endif %}
<!-- Upload form. Note enctype attribute! -->
<form action="{% url 'list' %}" method="post" enctype="multipart/form-data">
{% 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>
<p><input type="submit" value="Upload" /></p>
</form>
</body>
</html>
As you can see, I added Delete button in a form. By doing so, I have a button near each file. I added this to my views :
def delete(request):
if request.method != 'POST':
raise HTTP404
else:
docId = request.POST.get('docfile', None)
if docId is not None:
docToDel = Document.objects.get(pk=docId)
docToDel.delete()
form = DocumentForm(request.POST, request.FILES)
documents = Document.objects.all()
return HttpResponseRedirect(reverse('myapp.views.list'))
But that does not do anything, just reloads the page.
As I said, now I cannot even delete them manually.
What am I doing wrong?
First of all file on disk and model in DB are different things. To delete file from disk and DB you may try this
from django.shortcuts import get_object_or_404
def delete(request):
if request.method != 'POST':
raise HTTP404
docId = request.POST.get('docfile', None)
docToDel = get_object_or_404(Document, pk = docId)
docToDel.docfile.delete()
docToDel.delete()
return HttpResponseRedirect(reverse('myapp.views.list'))
Also you forgot to specify ID of Document to delete
<!-- List of uploaded documents -->
{% if documents %}
<ul>
{% for document in documents %}
<li>{{ document.docfile.name }}
{% if user.is_staff %}
<form action="{% url 'delete' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="hidden" name="docfile" value="{{ document.pk }}" />
<input type="submit" value="Delete" />
</form>
{% endif %}
</li>
{% endfor %}
</ul>
{% else %}
<p>No documents.</p>
{% endif %}