How to upload and create multiple file objects with django - file-upload

I'm new to Django and I'm on the first stages for writing a web app. One of the features of the app requires users to upload multiple pictures to a database.
I have created an 'image' model for storing the pictures and later manipulate them. The user is supposed to upload more than one image at a time using a POST request (don't even know if that is possible).
Each picture uploaded is supposed to be an image object on the database, but for some reason, I'm failing to upload and also create that object. Nothing happens when I make the POST request. I might be failing at some point and in something simple. I'd appreciate some help.
models.py
from django.db import models
class image(models.Model):
image_field = models.FileField(upload_to='images/')
forms.py
from django import forms
from .models import image
class images_form(forms.ModelForm):
class Meta:
model = image
fields = ['image_field']
widgets = {
'image_field' : forms.ClearableFileInput(
attrs={'class': 'upload ','inputtype':'file','name':'images','multiple':True })}
views.py
from django.shortcuts import render
from django.http import HttpResponse
from .forms import images_form
from .models import image
def upload_files(request):
context = {'images_form': images_form}
if request.method == 'POST':
form_images = images_form(request.POST, request.FILES)
files = request.FILES.getlist('images')
if form_images.is_valid():
for file in files:
newimg = image(image_field = file)
print(newimg.name)
newimg.save()
return HttpResponse('images uploaded')
else:
return render(request, 'master_form/desk.html', context=context)
upload_images.html
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<title>Hello, world!</title>
</head>
<body>
<h1>Django Desk</h1>
<div class="container-fluid">
<h1> images</h1>
<form method = "post" enctype = "multipart/form-data">
{% csrf_token %}
{{ images_form.as_p }}
<button type = "submit"> Upload </button>
</form>
</body>
</html>

I found what the problem was.
files = request.FILES.getlist('images')
Was empty or didn't exist.
You have to use the same name you used when defining your model fields, in my case 'image_field', not 'images'.
The new code looks like this (views.py):
for file in request.FILES.getlist('image_field'):
img = image(image_field=file)
img.save()

Related

JWT not decoding

I'm using JWT (the PyJWT library not the flask-jwt) for authentication in my Flask app, but it always returns in the binary form. I use jwt.decode() but to no avail. What am I doing wrong.
Here is the code:
from flask import Flask,render_template,request,redirect,url_for,session
import model
import datetime
import os
from functools import wraps
import jwt
app = Flask(__name__)
app.config["SECRET_KEY"] = os.urandom(16)
def check_for_token(func):
#wraps(func)
def wrapped(*args,**kwargs):
token =request.args.get('token')
if not token:
return("ACCESS DENIED",403)
try:
data = jwt.decode(token,app.config["SECRET_KEY"])
except:
return("INVALID TOKEN",403)
return func
return wrapped
#app.route("/home",methods=["POST"])
def home():
usrname = request.form["username"]
psswrd = request.form["password"]
valid_user = model.username_password_validation(usrname,psswrd)
if not valid_user:
return render_template("login.html",infoMsg="INVALID USERNAME/PASSWORD")
else:
session['username'] = usrname
session['logged_in'] = True
token =jwt.encode({'user':request.form['username'],'exp':datetime.datetime.utcnow() + datetime.timedelta(seconds=3600)},app.config["SECRET_KEY"],algorithm='HS256')
occupied_days = []
user_id=model.get_user_id_from_username(usrname)
tasks = model.get_all_tasks_for_user(user_id)
for task in tasks:
occupied_days.append({"day":task[3].day,"month":task[3].month})
current_month = datetime.datetime.now().month
days = model.get_number_of_days_for_selected_month(current_month)
current_year = datetime.datetime.now().year
return render_template("home.html",username=usrname,tasks=tasks,current_month=current_month,current_year=current_year,days=days,occupied_days=occupied_days,token=token)
#app.route("/<string:username>/tasks?token=<string:token>",methods=["POST","GET"])
#check_for_token
def user_tasks(username,token):
occupied_days= []
token = jwt.decode(token,app.config["SECRET_KEY"],algorithms=['HS256'])
user_id = model.get_user_id_from_username(username)
tasks = model.get_all_tasks_for_user(user_id)
for task in tasks:
occupied_days.append({"day":task[3].day,"month":task[3].month})
current_month = datetime.datetime.now().month
days = model.get_number_of_days_for_selected_month(current_month)
current_year = datetime.datetime.now().year
if request.method=="GET":
return render_template("tasks.html",user_id=user_id,username=username,tasks=tasks,token=token)
else:
task_description=request.form['taskDescription']
task_date=request.form['taskDate']
model.update_existing_task(user_id,task_description,task_date)
return render_template("home.html",infoMsg=f"task for {task_date} updated successfully",tasks=tasks,current_month=current_month,current_year=current_year,days=days,username=username,occupied_days=occupied_days,token=token)
here is the template file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/static/style.css">
<link href="https://fonts.googleapis.com/css2?family=Jua&display=swap" rel="stylesheet">
{% block title %}
{% endblock %}
<nav id="navbar">
<ul>
<li> Home </li>
<li>My tasks</li>
<li>Log out</li>
</ul>
</nav>
{% block content %}
{% endblock %}
</head>
<body>
</body>
</html>
Perharps I could pass it in the cookie instead of the query string , but I am not sure how that is done.

Export Html to Pdf using JsReport in Asp.net core

I have a html page with images, tables and some styling with Bootstrap 4. I tried to convert the pages to pdf using the JsReportMVCService, the pdf doesnot load with the proper css class from bootstrap.
HTML CONTENT
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>WeekelyReport</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
</head>
<body>
<div class="jumbotron">
<h1> Hello John Doe,</h1>
<p>
This is a generic email about something.<br />
<br />
</p>
</div>
</body>
</html>
ASP.NET CORE IMPLEMENTATION
var generatedFile = await GeneratePDFAsync(htmlContent);
File.WriteAllBytes(#"C:\temp\hello.pdf", generatedFile);
async Task<byte[]> GeneratePDFAsync(string htmlContent)
{
var report = await JsReportMVCService.RenderAsync(new RenderRequest()
{
Template = new Template
{
Content = htmlContent,
Engine = Engine.None,
Recipe = Recipe.ChromePdf
}
});
using (var memoryStream = new MemoryStream())
{
await report.Content.CopyToAsync(memoryStream);
return memoryStream.ToArray();
}
}
How my Pdf Looks after the conversion to PDF.
It is possible to convert to pdf with the same bootstrap 4 layout? or am i missing something during the conversion here?
The pdf printing uses print media type and the bootstrap has quite different styles for printing. This causes that the pdf looks different than html, but it looks the same as you would print it. I would generally not recommend using responsive css framework as bootstrap for printing static pdf, but it is of course your choice.
To make your example looking the same on pdf you just need to change the media type on the chrome settings.
var report = await JsReportMVCService.RenderAsync(new RenderRequest()
{
Template = new Template
{
Content = htmlContent,
Engine = Engine.None,
Recipe = Recipe.ChromePdf,
Chrome = new Chrome {
MediaType = MediaType.Screen,
PrintBackground = true
}
}
});
make sure you have the latest jsreport.Types#2.2.2

Peerjs is not retrieved in vue js

I am trying to use peerjs in vue app. So I added the cdn script in vue index.html file's header like this.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta data-n-head="true" name="viewport" content="width=device-width, initial-scale=1.0">
<title>peer</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/peerjs/0.3.9/peer.min.js"></script>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
Now in a components' mounted hook, I am doing this to just console the id
var peer1 = new Peer();
peer1.on('open', function(id) {
console.log('My peer1 ID is: ' + id);
});
Nothing happens.
I then created a simple html file and run that html file I was able to see the id.
Next I tired to see XHR tab, I see when running a plain html file, two ajax calls is sent and in the result an ID is returned. But in vue, there is nothing like this. All I get a socket that returns this values
{websocket: true, origins: ["*:*"], cookie_needed: false, entropy: 1058218289}
cookie_needed
:
false
entropy
:
1058218289
origins
:
[":"]
websocket
:
true
One more thing, peers js documentations says to use api key, but if I use api key nothing happens in vue or html. Without the key, in html file I get the id.
Anyone knows please help me. Thank you.

Requests or Urllib - Login in a website, send download request to url, and save as xlsx

I am going crazy with the following problem. What I want to do is login into a website, download a file, while saving the download request as an xlsx.
I am pretty sure I need to use the requests librarybut don't seem to know exactly how to do it. This is what I have so far :
import requests
# URL Data
login_url = 'https://reporting.integralplatform.com/uaa/login#/'
report_url = 'https://integralplatform.com/home/brand-safety/firewall?period=%5B2016-09-01..2017-02-19%5D&publisher=all&placement=all&deliveryEnvironment=%5Bdesktop%5D&includeCampaign=true&campaigns=52921%3A52919%3A52931%3A52922%3A52933%3A54272%3A52934%3A54370%3A54363%3A54372%3A54362%3A54369%3A54368%3A54366%3A54365%3A54367&includePlacement=true&grouping=placementName&dateGroup=daily'
download_url = 'https://integralplatform.com/reportingservice/api/teams/3236/fw/campaigns/52921%253A52919%253A52931%253A52922%253A52933%253A54272%253A52934/report.xls?period=%5B2016-09-01..2017-02-19%5D&cutoff=250&mediaType=mixed&groups=%5Bcamp%3Apub%3Aplac%3Adaily%5D&tabs=%5Bfirewall%5D&settings=%7B%22Selected%20Report%22%3A%22Firewall%20Activity%22%2C%22Group%20Dates%20By%22%3A%22Day%22%2C%22Report%20By%22%3A%22Campaign%22%2C%22Campaign%22%3A%22%25%25CAMPAIGN_NAMES%25%25%22%2C%22Media%20Partner%22%3A%22All%22%2C%22Placement%22%3A%22Yes%22%2C%22Geo%20Level%22%3A%22Country%22%2C%22Cutoff%22%3A%22250%22%7D'
# Payload
payload = {
"username" : 'my username'
,
"password": 'my password',
"_csrf_uaa": "507be70c-d4ff-4ea7-a3bf-d45cad3faa47",
}
# Authenticate
login = requests.post(login_url, data=payload)
# Download File
download = requests.post(download_url, data=payload)
However, while I look at both login.content and download.content it seems like I fail to even login as the result is :
b'<!DOCTYPE html>\n<html lang="en" ng-app="iasLogin">\n<head>\n\n <meta charset="UTF-8">\n\n <title>IAS Login</title>\n\n\n <!-- Start Vendor CSS -->\n <link rel="stylesheet" href="css/ias-app-vendor.min.css">\n <!-- End Vendor CSS -->\n\n <!-- Start IAS CSS -->\n <link rel="stylesheet" href="css/ias-app.min.css">\n <!-- End IAS CSS -->\n\n</head>\n<body>\n\n <ias-headers></ias-headers>\n\n <div ui-view></div>\n\n <!-- Start Vendor JS -->\n <script src="js/ias-app-vendor.min.js"></script>\n <!-- End Vendor JS -->\n\n <!-- Start IAS JS -->\n <script src="js/ias-app.min.js"></script>\n <!-- End IAS JS -->\n\n</body>\n</html>'
What it seems to me is that I am clearly doing something wrong when it comes to the payload. However, I don't know how to fix it.
To clarify, the difference between report_url and download_url is that download_url is the url I receive when I right click the download button. The parameters are fixed.
Thanks for all the help
You'll likely need to include headers and form data that the page submits along with your current payload.

"Container is not defined" Google chart

I have solved my issue but can't answer it myself since I am too new to this site:
turns out I needed to use the following:
chart = new google.visualization.PieChart(document.getElementById('pie_today_div'));
I was using JQuery to access the element, $('#pie_today_div'). As of now the evidence points to the fact that the PieChart constructor has to have standard JS code, document.getElementById('pie_today_div')
Maybe something else going on, but changing the way I access the container element fixes my code
ORIGINAL ISSUE FOR REFERENCE TO MY SOLUTION
I am getting a "Container is not defined" error when I am trying to instantiate a Google PieChart object.
I validated my page at http://validator.w3.org/ and i get a pretty green banner saying it validates.
I receive no js errors when the page loads. My Ajax call is making a full round trip with the data I want from the DB.
Here is my HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<link href="/css/note.css?10022012" rel="stylesheet" type="text/css" media="screen">
<script type="text/javascript" language="javascript" src="/call/js/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">google.load('visualization', '1.0', {'packages':['corechart']});</script>
<script type="text/javascript" language="javascript" src="/call/js/init.js?10042012-2"></script>
<title>Call Stats</title>
</head>
<body>
Today Stats
<div id="pie_today_div"></div>
</body>
</html>
here is the js:
function drawPieChartToday() {
$.post('/call/ajax.php5',{
action:'pieToday'
}, function(ticketData) {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Count');
data.addColumn('number', 'Topic');
for (var key in ticketData){
data.addRow([key, ticketData[key]]);
}
options = {
title: 'Issue Topics'
};
alert($('#pie_today_div').attr('id'));
chart = new google.visualization.PieChart($('#pie_today_div'));
chart.draw(data, options);
},'json');
}
here is my debugging code to make sure the element was being found:
alert($('#pie_today_div').attr('id')); <-- alerts "pie_today_div"
I'm not a jquery fan, but I think that $('#pie_today_div') returns a set of matched elements. The attribute computation works because (from jquery documentation) it "gets the value of an attribute for the first element in the set of matched elements".
So try
chart = new google.visualization.PieChart($('#pie_today_div')[0]);
or directly
chart = new google.visualization.PieChart(document.getElementById('pie_today_div'));
A container error is exactly that, It is looking for the ID
example:
var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
You WILL get this error “Container is not defined” for Google Charts if you are missing
that ID
Thus a Div with that chart_div id would fix this
There must be line where you load the types of visualization you want to have in your web page. It looks like this
google.load("visualization", "1", {packages: ["corechart"]});
Here I am loading package corechart. Place this line as the first line after in the <script> tag inside your HTML page like index.html. That should solve he problem.
use $timeout before init, it works well, else you need to destroy the instance
Just wanted to mention, this happened for me after a simple mistake. I changed
var data = new google.visualization.DataTable(huh);
to the following in an effort to change the chart type:
var data = new google.visualization.BarChart(huh);
but this is all wrong, you change the chart where you mention the container:
var chart = new google.visualization.ComboChart(document.getElementById('chart_div'));