I'm writing my first Django app by following along with this book:
http://chimera.labs.oreilly.com/books/1234000000754/ch05.html#_passing_python_variables_to_be_rendered_in_the_template
In the book there is a test that is verifying that the html is being returned as it is supposed to. Here is the test:
def test_home_page_returns_correct_html(self):
request = HttpRequest()
response = home_page(request)
expected_html = render_to_string('home.html')
print(expected_html)
print(response.content.decode())
self.assertEqual(response.content.decode(), expected_html)
My test is failing on the assertEqual test because I have added a csrf token in my HTML using the Django Template Language. Here is what my HTML page looks like:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>To-Do lists</title>
</head>
<body>
<h1>Your To-Do list</h1>
<form method="POST">
<input name="item_text" id="id_new_item" placeholder="Enter a to-do item"/>
{% csrf_token %}
</form>
<table id="id_list_table">
<tr><td>{{ new_item_list }}</td></tr>
</table>
</body>
</html>
My assert is failing due to the render_to_string method not including the token. Here is what my two print statements included in my test print out:
F<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>To-Do lists</title>
</head>
<body>
<h1>Your To-Do list</h1>
<form method="POST">
<input name="item_text" id="id_new_item" placeholder="Enter a to-do item"/>
</form>
<table id="id_list_table">
<tr><td></td></tr>
</table>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>To-Do lists</title>
</head>
<body>
<h1>Your To-Do list</h1>
<form method="POST">
<input name="item_text" id="id_new_item" placeholder="Enter a to-do item"/>
<input type='hidden' name='csrfmiddlewaretoken' value='VAiGvXZLHCjxWEWdjhgQRBwBSnMVoIWR' />
</form>
<table id="id_list_table">
<tr><td></td></tr>
</table>
</body>
</html>
F.
He doesn't have this problem in the book (he's using 1.8), so I was wondering if the method behavior has changed, or how I would write this test to pass.
The request argument was added to render_to_string in Django 1.8. You could try changing the line in your test to:
expected_html = render_to_string('home.html', request=request)
It's only required to make this change in Django 1.9+, the test passes without the request in Django 1.8.
I found this solution which has worked for the latest Django version - 3.0.6
#add a function to the post request test function
def remove_csrf_tag(text):
"""Remove csrf tag from TEXT"""
return re.sub(r'<[^>]*csrfmiddlewaretoken[^>]*>', '', text)
...
# then change assertion
def test_home_page_can_save_a_POST_request(self):
...
self.assertEqual(
remove_csrf_tag(response.content),
remove_csrf_tag(expected_html)
)
Related
I Am trying To Send Post request to The Django using Axios But it Is Not Working
instead it sending get request after the submit button is pressed.
I don't know why this happening I Hvae configured Everything corretelty but it is not working
Any Has Any solution to this then please help me
My Html Code Is
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Out</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.1.3/axios.min.js" integrity="sha512-0qU9M9jfqPw6FKkPafM3gy2CBAvUWnYVOfNPDYKVuRTel1PrciTj+a9P3loJB+j0QmN2Y0JYQmkBBS8W+mbezg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
{% load static %}
</head>
<body>
<div align = "center">
<form action="" name = "out" id ="out" >
{% csrf_token %}
<table>
<th>Name</th>
<th>Stock_out</th>
<tr>
<td><input type="text" id="name" name="name"></td>
<td><input type="text" id="stock_out" name="stock_out"></td>
</tr>
<tr >
<td><span id ="name_er"></span></td>
<td><span id ="stock_err"></span></td>
</tr>
</table>
<input type="button" value="Submit" form = "out" onclick="submit()">
</form>
</div>
<script src="{% static 'out.js/'%}"></script>
</body>
</html>
Here Is My Js Script
function submit(){
let nam = document.getElementById('name').value;
let out = document.getElementById('stock_out').values
if(nam=="" | nam==null){
document.getElementById('nam-er').innerHTML="Name Insert please"
return false
}else{
let form = document.getElementById('out');
var data = new FormData(form);
data.append('name', document.getElementById('name').value);
data.append('stock_out', document.getElementById('stock_out').value);
data.append("csrfmiddelwaretoken",'{{csrf_token}}');
// form.reset();
axios.post('add/product_out',data).then(function(resp){
window.location.href = "add/success";
console.log(resp);
})
.catch(function (error) {
console.log(error);
})
}
}
Here Is My Django Views
def product_out(request):
if request.method =='POST':
name = request.POST.get('name')
stock = request.POST.get('stock_out')
Stock_Out.objects.create(
name=name,
stock_out=stock
)
resp = {
"status":'success'
}
return JsonResponse(resp)
urls.py
from django.urls import path
from add import views
urlpatterns =[
path('add',views.add, name='add'),
path('success',views.success, name='success'),
path('stock_out',views.stock_out, name = 'stock_out'),
path('product_out',views.product_out, name = 'product_out')
]
I Want Send The to The Server from input field Which is Shown on the picture that come from http response from the browser(https://i.stack.imgur.com/3FrMS.png)
I think the issue is that the browser's default submit is triggering making it skip all your javascript part. Try preventing it with preventDefault():
Pass the event to your js (note the e in the parenthesis)
<input type="button" value="Submit" form = "out" onclick="submit(e)">
Prevent the default behaviour:
function submit(e){
e.preventDefault()
// ..the rest of your script here
}
Alternatively, you could change the submit button from being a <input type="submit" /> to a <button type="button">Submit</button>
I have an application that can upload files in every format I want to be encrypted and saved to database I also created decrypt functionality but I dont know how to show this decrypted file to the user or django templates.
i have tried many ways like TemFile library but still I cant pass my decrypted data to the templates
here is my code for encryption
def encrypt (request):
if request.method == 'POST':
upload_file = request.FILES.get("like")
# key generation
key = Fernet.generate_key()
encode_key = urlsafe_base64_encode(force_bytes(key))
print(encode_key)
document = FileEncrypt.objects.create(document = upload_file,key=encode_key)
# using the generated key
fernet = Fernet(key)
# opening the original file to encrypt
with open(document.document.path, 'rb') as file:
original = file.read()
# encrypting the file
encrypted = fernet.encrypt(original)
with open(document.document.path, 'wb') as encrypted_file:
encrypted_file.write(encrypted)
document.save()
return redirect("decrypt_and_show", id=document.id)
else:
return render(request,"index.html",{
})
after redirecting to decrypt page it's not showing the file
here is my decrypt def
def decrypt(request,id):
document = FileEncrypt.objects.get(pk=id)
decode_key =force_text(urlsafe_base64_decode(document.key))
print(decode_key)
fernet = Fernet(decode_key)
# opening the encrypted file
with open(document.document.path, 'rb') as enc_file:
encrypted = enc_file.read()
# decrypting the file
decrypted = fernet.decrypt(encrypted)
tmpfile = tempfile.NamedTemporaryFile(delete=False,suffix='.JPEG')
tmpfile.seek(0)
tmpfile.write(decrypted)
return render(request,"index2.html",{
"d" : tmpfile.name
})
in my template is
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="{% static 'fileuploads/js/script.js' %}" defer></script>
</head>
<body>
<img src="{{d}}" />
</body>
</html>
in my index template is
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="{% static 'fileuploads/js/script.js' %}" defer></script>
</head>
<body>
<form action"" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" name="like" />
{% comment %} {{form}} {% endcomment %}
<button type="submit">Upload</button>
</form>
</body>
</html>
could you please help me with.
I am new to Django. I am trying to create a website with two input textboxes. When the submit button clicked, I need to update the results from django view to the same template without reloading the webpage.
Here is my code so far:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test</title>
</head>
<body>
<H1>Welcome to Test</H1>
<div class="input-group" >
Input Text:<br>
<textarea class="form-control" rows="20" cols="70" name="InputText"
placeholder="Enter your Input Text here" form="myForm">
</textarea>
<span class="input-group-addon"><br></span>
Input TextFSM Template:<br>
<textarea class="form-control" rows="20" cols="70" name="InputTemplate"
placeholder="Enter your template here" form="myForm">
</textarea>
<form action="" method="post" id="myForm">
{% csrf_token %}
<input type="submit" value="Submit">
</form>
</div>
<div id="resultid">
<p>Result:</p>
{{result}}
</div>
</body>
</html>
views.py
class HomePageView(TemplateView):
template_name = "index.html"
def get(self, request, **kwargs):
form = ParserForm()
return render(request, self.template_name, {"form": form})
def post(self, request, **kwargs):
form = ParserForm(request.POST)
if form.is_valid():
inputtext = form['InputText'].value()
template = form['InputTemplate'].value()
# Process the data and get the result
print(result)
return render(request, self.template_name, {'result': result})
How to pass the result to index.html from view but the text entered in the textboxes should be persistent.
There is no direct way to update result in django templates or django views without reloading the page. In addition, once page in rendered you need second request to update that page. You could use jquery ajax to do fetch data from server without reloading page.
Ajax is asynchronous javascript extension which is use to send request with out reloading page. This would help you to do exactly that you want.
You could get more help from here
See following example for an instance.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test</title>
<body>
<H1>Welcome to Test</H1>
<div class="input-group" >
Input Text:<br>
<textarea class="form-control" rows="20" cols="70" name="InputText"
placeholder="Enter your Input Text here" form="myForm">
</textarea>
<span class="input-group-addon"><br></span>
Input TextFSM Template:<br>
<textarea class="form-control" rows="20" cols="70" name="InputTemplate"
placeholder="Enter your template here" form="myForm">
</textarea>
<form id="my-form" action="" method="post" id="myForm">
{% csrf_token %}
<input type="submit" value="Submit">
</form>
</div>
<div id="resultid">
<p>Result:</p>
{{result}}
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
(function($){
function processForm( e ){
$.ajax({
url: '/url-to-call/', //replace this with url that you want to hit without reloading the page
dataType: 'text',
type: 'post',
contentType: 'application/x-www-form-urlencoded',
data: $(this).serialize(),
success: function( data, textStatus, jQxhr ){
// manipulate stuff or action
},
error: function( jqXhr, textStatus, errorThrown ){
// This is executed when some error occures
}
});
e.preventDefault();
}
$('#my-form').submit( processForm );
})(jQuery);</body>
</html>
I want to put an html in a string, NOT a file, like:
t = """
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>foo</title>
</head>
<body>
{{ script|safe }}
</body>
</html>
"""
script = ...
render_template_string(t, script=script)
However when I go to the actual webpage, I don't see an html page with a script, I see garbage:
"\n<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <title>foo</title>\n</head>\n\n<body>\n \n<script\n src=\"http://localhost:5006/bkapp/autoload.js?bokeh-autoload-element=ff639949-97c5-40b8-9cc2-28b78be802d1&bokeh-app-path=/bkapp&bokeh-absolute-url=http://localhost:5006/bkapp\"\n id=\"ff639949-97c5-40b8-9cc2-28b78be802d1\"\n data-bokeh-model-id=\"\"\n data-bokeh-doc-id=\"\"\n></script>\n</body>\n</html>"
How do I fix this?
EDIT: even a very simple
t = '{{ script|safe }}'
does not work, I get, in the browser:
"\n<script\n src=\"http://localhost:5006/bkapp/autoload.js?bokeh-autoload-element=07a43696-66af-4e54-a4e3-9a09ac242e38&bokeh-app-path=/bkapp&bokeh-absolute-url=http://localhost:5006/bkapp\"\n id=\"07a43696-66af-4e54-a4e3-9a09ac242e38\"\n data-bokeh-model-id=\"\"\n data-bokeh-doc-id=\"\"\n></script>"
EDIT 2: I have also tried
t = '{% autoescape false %}{{ script|safe }}{% endautoescape %}'
but that didn't work either.
I'm using Connexion if that matters.
I am following the book "Test-Driven Development in Python" and have the following functions:
tests.py:
def testHomePageCanSaveAPostRequest(self):
request = HttpRequest()
request.method = 'POST'
request.POST['itemText'] = 'A new list item'
response = homePage(request)
if response:
response = response.content.decode('UTF-8')
self.assertIn('A new list item', response)
expectedHTML = render(request, 'lists/home.html', {'itemText':'A new list item'})
if expectedHTML:
expectedHTML = expectedHTML.content.decode('UTF-8')
print(response)
print(expectedHTML)
if response==expectedHTML:
print('Same')
self.assertIn('A new list item', expectedHTML)
self.assertEqual(response, expectedHTML)
views.py
def homePage(request):
print(request.POST.get('itemText'))
return render(request, 'lists/home.html', {'itemText':request.POST.get('itemText')})
home.html:
...
<form method=POST>
<input id=newItem name=itemText placeholder="Enter a to-do item">
</form>
<table id=listTable>
<tr><td>{{itemText}}</td></tr>
</table>
...
Both assertIn(..., response) and assertIn(..., expectedHTML) are successful, which means both response and expectedHTML have 'A new list item' in them.
I also print out response and expectedHMTL, and they look exactly the same. The comparison also print out 'Same' showing that they are the same.
However, the assertEqual fails with the following line by line comparison:
...
<table id=listTable>
- <tr><td>None</td></tr>
? ----
+ <tr><td></td></tr>
</table>
...
One is None and the other is empty.? What did I do wrong?
EDIT:
The entire test output is listed in the following:
Creating test database for alias 'default'...
A new list item
<!doctype html>
<html>
<head>
<title>To do list</title>
<meta charset=utf-8>
</head>
<body>
<h1>Your to do list</h1>
<form method=POST>
<input id=newItem name=itemText placeholder="Enter a to-do item">
</form>
<table id=listTable>
<tr><td>A new list item</td></tr>
</table>
</body>
</html>
<!doctype html>
<html>
<head>
<title>To do list</title>
<meta charset=utf-8>
</head>
<body>
<h1>Your to do list</h1>
<form method=POST>
<input id=newItem name=itemText placeholder="Enter a to-do item">
</form>
<table id=listTable>
<tr><td>A new list item</td></tr>
</table>
</body>
</html>
Same
.None
F.
======================================================================
FAIL: testHomePageReturnsCorrectHTML (lists.tests.HomePageTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/yltang/course/TDD/lecture/python/webapps/git/superlists/superlists/lists/tests.py", line 27, in testHomePageReturnsCorrectHTML
self.assertEqual(response, expectedHTML)
AssertionError: '<!do[231 chars]stTable>\n <tr><td>None</td></tr>\n</table>\n</body>\n</html>' != '<!do[231 chars]stTable>\n <tr><td></td></tr>\n</table>\n</body>\n</html>'
<!doctype html>
<html>
<head>
<title>To do list</title>
<meta charset=utf-8>
</head>
<body>
<h1>Your to do list</h1>
<form method=POST>
<input id=newItem name=itemText placeholder="Enter a to-do item">
</form>
<table id=listTable>
- <tr><td>None</td></tr>
? ----
+ <tr><td></td></tr>
</table>
</body>
</html>
----------------------------------------------------------------------
Ran 3 tests in 0.017s
FAILED (failures=1)
Destroying test database for alias 'default'...
You have added the print statements to a different test. The print statements are in testHomePageCanSaveAPostRequest, which is passing.
The failing test is testHomePageReturnsCorrectHTML, which you have not included in your question.