Django: Make HTML page from SQL query - python

This works but..
views.py
from django.http import HttpResponse
from django.db import connection
def query():
with connection.cursor() as cursor:
cursor.execute('SELECT some, stuff FROM here;')
row = cursor.fetchall()
return row
def index(request):
return HttpResponse(query())
What if I want to get a filtered response that is restricted to a user or group from the admin?
For example, if the user is in the BAIT group they could filter results WHERE email LIKE 'bob#bait.com';

I did it like this...
/opt/my_project/my_app/templates/my_app/generate_html.html
<html>
<h1>Generate HTML</h1>
<form method="POST" action="">
{% csrf_token %}
{{ form }}
<button type="submit">Submit Query</button>
</form>
</html>
/opt/my_project/my_project/settings.py
'DIRS': ['/opt/my_project/my_app/templates/my_app'],
/opt/my_project/my_app/urls.py
path('generate_html/', generate_html, name = "generate_html"),
/opt/my_project/my_app/forms.py
from django import forms
class InputForm(forms.Form):
email = forms.EmailField(max_length = 100)
/opt/my_project/my_app/views.py
def query(email):
with connection.cursor() as cursor:
query = '''SELECT some, stuff
FROM here
WHERE email = %s
ORDER BY stuff;
'''
values = (email,)
cursor.execute(query, values)
select = cursor.fetchall()
return select
def generate_html(request):
if request.method == 'POST':
email = request.POST.get('email', None)
try:
html = '<!DOCTYPE html><html><body>'
for row in query(email):
some, stuff = row
html += 'Row: ' + some + ' ' + stuff + '<br>'
html += '<br><br>' + 'Search Again!' + '</body></html>'
return HttpResponse(html)
except Exception as e:
return HttpResponse(str(e))
else:
context ={}
context['form']= InputForm()
return render(request, "generate_html.html", context)

Related

Can a GET POST be implemented in a return jsonify(data) function?

I have:
server:
#app.route('/')
def index():
return render_template("index.html")
#app.route('/indexGetData', methods=['GET', 'POST'])
def loadData():
if (request.method == 'POST'):
myval = request.form.get('user_ID')
query = "select * from abc where xyz = :myval"
cursor.execute(query, myval=myval)
# convert the result to json
return jsonify(data)
form:
<form method="post" action ="/indexGetData">
<input type="text" id="userID" name="user_ID">
<input type="submit" value="Search"
</form>
and would like to get values from the user form in the index.html template to pass to the sql query. Please advise... I have been getting Method not allowed error
query = "select * from abc where xyz = " + str(myval)
data = db.engine.execute(query)
ret= []
for i in data:
ret.append(
{
"key": i.key
}
)
return jsonify(ret)

Django outputting errorlist as string instead of html

I'm trying to customize the default error list in django. I've tried following the docs, but the problem is that the supposed html gets outputted as text istead of html:
I'm not quite sure why this is happening, as the code is pretty much copy-paste from the docs. Code:
forms.py
class DivErrorList(ErrorList):
def __str__(self):
return self.as_divs()
def as_divs(self):
if not self: return ''
return '<div class="test">%s</div>' % ''.join(['<div class="error">%s</div>' % e for e in self])
views.py
def addUser(request):
add_user_form = AddUserForm()
messages.warning(request, 'message')
if request.method == 'POST':
add_user_form = AddUserForm(request.POST, error_class=DivErrorList)
if add_user_form.is_valid():
user = add_user_form.save()
customer_group = Group.objects.get(name = 'group_name')
user.roles.add(customer_group)
messages.success(request, 'message')
return redirect('users')
else:
messages.error(request, 'message')
context = {
'add_user_form': add_user_form,
}
return render(request, 'users/backend/user/user_add.html', context)
html
<div class="w-full mt-6">
{% include 'components/typography/form_label.html' with label='Gjenta passord' %}
{{ add_user_form.password2 }}
{{ add_user_form.password2.errors }}
</div>
You need to mark the string as "safe", i.e. this:
return '<div class="test">%s</div>' % ''.join(['<div class="error">%s</div>' % e for e in self])
should be
return mark_safe('<div class="test">%s</div>' % ''.join(['<div class="error">%s</div>' % e for e in self]))
where mark_safe comes from:
from django.utils.safestring import mark_safe

single entry SQL/python

im trying to do a blog post simple app in witch you can write and than edit or delete a post.
I got so far that i can show post but i can not edit them
i did a /edit.html page on witch i would like to have a single blog post and than edit it. The problem is that the post does not appear
app.py
from flask import Flask, render_template, request
from flask_mysqldb import MySQL
import yaml
from flask_bootstrap import Bootstrap
app=Flask(__name__)
bootstrap = Bootstrap(app)
db = yaml.load(open('db.yaml'))
app.config['MYSQL_HOST'] = db['mysql_host']
app.config['MYSQL_USER'] = db['mysql_user']
app.config['MYSQL_PASSWORD'] = db['mysql_password']
app.config['MYSQL_DB'] = db['mysql_db']
mysql = MySQL(app)
#app.route('/', methods=['GET','POST'])
def index():
if request.method == 'POST':
form = request.form
user_name = form['user_name']
besedilo = form['besedilo']
cur = mysql.connection.cursor()
cur.execute("INSERT INTO post(user_name, besedilo) VALUES(%s, %s)", (user_name, besedilo))
mysql.connection.commit()
return render_template('index.html')
#app.route('/post/')
def post():
cur = mysql.connection.cursor()
result_value = cur.execute("SELECT * FROM post")
if result_value > 0:
posts = cur.fetchall()
return render_template('post.html',posts = posts)
#app.route('/edit/<int:id>/', methods=['GET','POST'])
def edit(id):
cur = mysql.connection.cursor()
result_value = cur.execute("SELECT * FROM post WHERE post_id = {}".format(id))
if result_value > 0:
post = cur.fetchone()
return render_template('edit.html', post = post)
## here i would like to single out one entry and show it on
#app.route('/delete/')
def delete():
return render_template('delete.html')
if __name__ == '__main__':
app.run(debug=True)
edit.html
{% extends 'base.html' %}
{% block sub_content %}
<h1>{{post['user_name']}}</h1>
<h1>{{post['besedilo']}}</h1>
{% if posts %}
{% for post in posts %}
<h3> {{edit['title']}}</h3>
{%endfor%}
{% endblock %}
this should show single entry
You may need to pass a properly prepared sql query not dynamic.
Try modifying your view like:
#app.route('/edit/<int:id>/', methods=['GET','POST'])
def edit(id):
cur = mysql.connection.cursor()
query = "SELECT * FROM post WHERE post_id = {}".format(id)
result_value = cur.execute(query)
if result_value > 0:
post = cur.fetchone()
return render_template('edit.html', post = post)
Alternatively;
result_value = cur.execute("SELECT * FROM post WHERE post_id = %s", (id,))

'str' does not support the buffer interface while uploading and submitting csv file in Django

I want to upload a csv file and store it in a database. My Django version is 1.9 and Python3.4. Below is the code. My app name is 'pft'
pft/utils.py
from .models import Account
import csv
def handle_uploaded_file(file, valid_fields_method, record_creation_function):
file.seek(0)
# !importtant
# csv file must be encoded in UTF-8
sniffdialect = csv.Sniffer().sniff(file.read(10000), delimiters='\t,;')
file.seek(0)
#print sniffdialect.fieldnames
data = csv.DictReader(file, dialect=sniffdialect)
if not valid_fields_method(data.fieldnames):
return False, -1
result, rows_error = record_creation_function(data)
return result, rows_error
def account_valid_fields(field_names):
required_fields = ('species', 'x', 'y')
for field in required_fields:
if field not in field_names:
return False
return False
def create_account_in_db(dict_data):
list_data = []
result = False
rows_error = 0
for record in dict_data:
species = record['species']
x = record['x']
y = record['y']
account = models.Account(species=species,\
x=x,\
y=y)
list_data.append(account)
if list_data:
# bulk_create will create multiple object in a single query
created_accounts = models.Account.objects.bulk_create(list_data)
if len(list_data) == len(created_accounts):
result=True
else:
rows_error = len(list_data) - len(created_accounts)
return result, rows_error
models.py
class Account(models.Model):
species=models.CharField(max_length=255)
x=models.IntegerField()
y=models.IntegerField()
last_modified = models.DateTimeField(auto_now = True)
first_created = models.DateTimeField(auto_now_add = True)
def __str__(self):
return "%s %s %s" % (self.species, self.x,self.y)
views.py
def add_multiple_accounts(request):
if request.method == 'POST':
csv_upload_form = UploadFileForm(request.POST, request.FILES)
if csv_upload_form.is_valid():
file = csv_upload_form.cleaned_data['file']
csv_result, rows_error = utils.handle_uploaded_file(file, utils.account_valid_fields, utils.create_account_in_db)
if csv_result:
message = 'Successfully imported accounts from the csv file to the database.\n'
message += 'The system is creating Active Directory Accounts using those information in the background.\n'
message += 'Please wait...'
messages.add_message(request, messages.INFO, message)
else:
message = 'There are some errors occured. Please try again.'
messages.add_message(request, messages.INFO, message)
else:
csv_upload_form = UploadFileForm()
return render_to_response('add_multiple.html', locals(), context_instance=RequestContext(request))
urls.py
url(r'^csv',add_multiple_accounts),
add.mutilple.html
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ csv_upload_form.as_p }}
<button type="submit" class="action green btn-center" name="action" value="add_csv"><span class="label">Upload</span></button>
<input type="submit" />
</form>
When I click the submit button I get the above error. How can I solve this?
try:
file_content = bytes(file.read(10000), 'UTF-8')
sniffdialect = csv.Sniffer().sniff(file_content, delimiters='\t,;')
it is because string in Python3.x is not the same as in python2.x, you need to cast it with bytes and encode as utf-8

Passing values using python and flask

I'm quite new to python and flask. Basically I'm building a very basic web app that allows an admin to add/edit/delete a list of users. The list is display at the main menu and the admin can add/edit/delete first time around. However when I try to add/edit/delete a second time it doesn't work, also it fails if I redirect back to the main menu (where the list of users are) after an add/edit/delete. Any idea's what could be the issue?
from flask import Flask, url_for, request, render_template, redirect;
from app import app;
import pypyodbc;
myConnection = pypyodbc.connect('Driver={SQL Server};'
'Server=local'
'Database=All;'
'uid=sa;pwd=23232')
myCursor = myConnection.cursor()
myCursor.execute('SELECT * FROM Users')
rows = myCursor.fetchall();
for r in rows:
print(r)
#app.route('/')
def home():
"""Renders a sample page."""
createLink = "<a href='" + url_for("display") + "'>Admin</a>";
createLink2 = "<a href='" + url_for("user") + "'>User login</a>";
createLink3 = "<a href='" + url_for("delete") + "'>Delete</a>";
createLink4 = "<a href='" + url_for("edit") + "'>Edit</a>";
return """<html>
<head>
<title>First page</title>
</head>
<body>
<h1>Menu</h1>
<div>
""" + createLink + """
</div>
<div>
""" + createLink2 + """
</div>
<div>
""" + createLink3 + """
</div>
<div>
""" + createLink4 + """
</div>
</body>
</html>"""
#app.route('/display', methods=['GET', 'POST'])
def display():
if request.method == 'GET':
myCursor = myConnection.cursor()
myCursor.execute('SELECT * FROM Users')
rows = [dict(id=row[0], name=row[1], email=row[2], password=row[3]) for row in myCursor.fetchall()]
return render_template('DisplayAll.html', rows = rows)
else:
return"<h2>Error</h2>"
#app.route('/add', methods=['GET', 'POST'])
def add():
if request.method == 'GET':
return render_template('Add.html');
elif request.method == 'POST':
name = request.form['AddName'];
email = request.form['AddEmail'];
password = request.form['AddPassword'];
SQLCommand = ("INSERT INTO Users "
"(Name, Email, Pword) "
"VALUES (?,?,?)")
values = [name, email, password]
myCursor.execute(SQLCommand,values)
myConnection.commit();
#print("works")
#myCursor.execute('SELECT * FROM Users')
#rows = [dict(id=row[0], name=row[1], email=row[2], password=row[3]) for row in myCursor.fetchall()]
myConnection.close();
return ridirect(url_for('display'));
else:
return "<h2>Error</h2>";
#app.route('/delete', methods=['GET', 'POST'])
def delete():
if request.method == 'GET':
return render_template('Delete.html');
elif request.method == 'POST':
try:
DeleteId = request.form['DeleteId'];
SQLCommand = ("DELETE FROM Users "
"WHERE UsererId = "
+ DeleteId)
myCursor.execute(SQLCommand)
myConnection.commit();
#myCursor.execute('SELECT * FROM Users')
#rows = [dict(id=row[0], name=row[1], email=row[2], password=row[3]) for row in myCursor.fetchall()]
myConnection.close();
#return render_template("DisplayAll.html", rows = rows);
return redirect(url_for('display'));
except:
return "<h2>Doesn't work</h2>"
else:
return "<h2>Error</h2>";
#app.route('/edit', methods=['GET', 'POST'])
def edit():
if request.method == 'GET':
return render_template('Edit.html');
elif request.method == 'POST':
try:
Name = request.form['EditName'];
Email = request.form['EditEmail'];
Password = request.form['EditPassword'];
EditId = request.form['EditId'];
SQLCommand = ("UPDATE Users "
"SET Name = '" + Name +
"', Email = '" + Email +
"', Pword = '" + Password +
"' WHERE UsererId = "
+ EditId)
myCursor.execute(SQLCommand)
myConnection.commit();
#print("works")
#myCursor.execute('SELECT * FROM Users')
#rows = [dict(id=row[0], name=row[1], email=row[2], password=row[3]) for row in myCursor.fetchall()]
myConnection.close();
#return render_template("DisplayAll.html", rows = rows);
return redirect(url_for('display'));
except:
return "<h2>Doesn't work</h2>"
else:
return "<h2>Error</h2>";
First off, you have a typo in add() function.
This line:
return ridirect(url_for('display'));
should be
return redirect(url_for('display'));
Next, in display() you define myCursor and then you work with it. That is ok
myCursor = myConnection.cursor()
However, in functions add, delete and edit you are missing this definition, but you are still using it. You can not omit this definition, since the first one is valid only inside display() due to variable scope.
Try adding this definition to other functions as well.
If that does not work, it might be because you also need to make a new connection for every request, not just at the beginning of the file. Then, each function would begin with
myConnection = pypyodbc.connect('Driver={SQL Server};'
'Server=local'
'Database=All;'
'uid=sa;pwd=23232')
myCursor = myConnection.cursor()
Please, let us know if this works for you.
Note: I have just noticed you are actually closing the connection after adding/removing/editing with myConnection.close(). Therefore, you definitely need to reopen the connection upon each request with the code above.

Categories

Resources