How can I output the data to csv after producing data - python

Currently, my application is to select the stock data, then analyzing it by using another python script and output the result(in JSON format).
Now I would like to add a button to output the result(w_df_split) to CSV, then when the user clicks the button and download the csv file.
But I am stuck in how to return the output CSV function in this view.
views.py:
def efficient_frontier_select(request):
user_holding = Position.objects.filter(created_by = request.user)
selected_stock = None
w_df_split = None
if request.method == 'POST':
selected_stock = request.POST.getlist('stock_symbol')
ta, tb, tc = ef.combination_frontier(selected_stock)
fy_df, fx_df, w_df, fxfy_df, ef_df = ef.transform_frontier_todf(ta,tb,tc, selected_stock)
w_df_split = json.loads(ef.json_format_split(w_df))
context = {
'w_df_split' : w_df_split,
}
return render(request, 'portfolio/efficient_frontier.html', context)

Asumming df is a dataframe, you you could use pandas's df.to_csv(). Like that: csv_data = w_df.to_csv(). You could do the same to json with w_df.to_json()

Just an update!
Django view design - export CSV from user-generated content
This works by setting the hidden input field to store the JSON data.

Related

Why serializing a QuerySet I iobtain a string?

I'm using a js function to obtain some data from my django models. Concretely, I want to obtain the last value from my sensors.
I'm doing the following,
from django.core import serializers
def getData(request):
ctx = {}
if request.method == 'POST':
select = int(request.POST['Select'])
last_val = DevData.objects.order_by('dev_id','-data_timestamp').distinct('dev_id')
data = serializers.serialize('json', last_val)
print(data)
print('****************')
print(data[0]) # I just obtain a "[" then is a string not a list
ctx = {'Select':data}
return JsonResponse(ctx)
My question is, why the output is a string? How can I convert it to a Json object and then pass it to my js function?
Thank you very much!!
You obtain a string, because JSON is a text format. You can for example use json.loads to convert it back to a list of dictionaries:
from json import loads as jsonloads
from django.core import serializers
def getData(request):
ctx = {}
if request.method == 'POST':
select = int(request.POST['Select'])
last_val = DevData.objects.order_by('dev_id','-data_timestamp').distinct('dev_id')
data = jsonloads(serializers.serialize('json', last_val))
ctx = {'Select':data}
return JsonResponse(ctx)
The JSON serialization in Django is just a special JsonEncoder named DjangoJSONEncoder [GitHub], that has some special cases for a datetime object, etc.

Read a csv file and fill in database with it's data in django application

in my Django application, i created a form which permit user to upload csv file.
What i want is when user upload the csv file, the contained data is read and database is filled in with them.
It works but not correctly. data are saved as tuples.
Here's my code
forms.py
class SupplierCSVForm(forms.ModelForm):
class Meta:
model = SuplierCsv
fields = '__all__'
exclude = ('slug',)
views.py
#login_required
def l_supplier(request):
suppliers_list = Supplier.objects.all()
paginator = Paginator(suppliers_list, 3, 2)
page = request.GET.get('page')
suppliers = paginator.get_page(page)
# Supplier csv form
if request.method == 'POST':
form = SupplierCSVForm(request.POST, request.FILES)
if form.is_valid():
uploaded_file = request.FILES['csvfile']
with open('f.csv', 'wb') as destination:
for chunk in uploaded_file.chunks():
destination.write(chunk)
destination.close()
#csvfile = io.TextIOWrapper(open('f.csv', 'rb'))
with open('f.csv', 'r') as the_source:
source_reader = csv.reader(sthe_source)
next(source_reader)
for Name, Email, Contact, City, Website, Activity, Cc, slug in source_reader:
new_supplier = Supplier()
new_supplier.name=Name,
new_supplier.email=Email,
new_supplier.contact=Contact,
new_supplier.city=City,
new_supplier.website=Website,
new_supplier.activity=Activity,
new_supplier.cc=Cc,
new_supplier.slug=slug,
new_supplier.save()
return redirect('good:l_good')
else:
form = SupplierCSVForm()
context = {
'suppliers': suppliers,
'form': form,
}
return render(request, 'supplier/l_supplier.html', context)
Remove the commas where you are assigning the new_supplier objects. Python converts your string objects into tuples if there are any trailing commas.
You have unnecessary commas at the end of your lines:
new_supplier.name=Name,
should be
new_supplier.name=Name
Python thinks that you are creating a tuple
i.e. x, == (x,)

How to import CSV to web2py Table?

im new in python and web2py, im stuck in creating a form to input csv file and the code to import the csv file.
here's my simple code
MODELS = db_tables.py
# -*- coding: utf-8 -*-
db = DAL('sqlite://storage.sqlite')
db.define_table('csvfile',
Field('nomor','integer'),
Field('nama'),
Field('umur','integer'),
migrate=False,
format = '%(name)s'
)
CONTROLLER = default.py
#auth.requires_login()
def index():
grid = SQLFORM.grid(db.csvfile, user_signature = False)
response.flash = T("Hello World")
return locals()
#def import_csv():
# form = FORM('Value:', INPUT(_value = 'name'), INPUT(_type = 'submit'))
# db.csvfile.import_from_csv_file(open('filename.csv'))
# return dict(form = form)
def import_csv():
form = FORM(INPUT(_type = 'file', _name = 'csv_file'),
INPUT(_type = 'submit', _value = T('Import')))
return(form=form)
VIEWS = default/index.html
{{left_sidebar_enabled,right_sidebar_enabled=False,('message' in globals())}}
{{extend 'layout.html'}}
<table>
<tr>{{=form}}
<td>{{pass}}
</td>
</tr>
</table>
actually i already show the table, but i cant make a form to input csv file and create a code to input the csv file with same header in 'csvfile' header
help me, thankyou!
You need to process the form by using form.process() to actually do something with the data.
See http://web2py.com/books/default/chapter/29/07/forms-and-validators#The-process-and-validate-methods

Download SQL data in xlsx format with Django

I have to write a function which on input has a name of a table and conditionals/filters for that query, on output it returns a link which should be automatically be download by the client (browser).
How to implement this task using python/django?
E.g. I've written a small piece of code, but I'm not sure that it works correctly and there is no implementation of query conditionals parsing (I don't know how to implement it):
direct_db.py:
from django.db import connection
class DirectSQL:
def __init__(self,in_sql):
self.sql=in_sql
self.cursor = connection.cursor()
self.cursor.execute(in_sql)
def getDescription(self):
columns = [desc[0] for desc in self.cursor.description]
return columns
def getResult(self):
row = self.cursor.fetchall()
return row
def getResultAsDict(self):
desc = self.cursor.description
return [dict(zip([col[0].lower() for col in desc], row)) for row in self.cursor.fetchall()]
excel.py:
from ecc.direct_db import DirectSQL
import pandas as ps
class Excel:
def __init__(self, table_name):
self.table_name = table_name
def convert(in_args):
q = DirectSQL("select * from self.table_name" ) # where... order by... like...
columns = [desc[0] for desc in q.getDescription()]
data = q.getResults()
df = ps.DataFrame(list(data), columns)
writer = ps.ExcelWriter('converted.xlsx')
df.to_excel(writer, sheet_name='converted')
writer.save()
I've worked in something like this before, I used xlsxwriter, you can check its docs to find out how to create a xlsx and how set data into it. Then you should need some view:
from django.views.generic import View
from django.http import HttpResponse
class CreateReport(View):
def get_data(self):
# Query your data here, probably using self.request to get query string
...
return data
def generate_report(self):
# Here you will create xlsx doc and populate with data according to docs linked before
...
return workbook
def get(self, request, *args, **kwargs):
document = self.generate_report()
_file = open(document.filename, 'r')
response(HttpResponse(_file, content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'))
response['Content-Disposition'] = 'attachment; filename=%s' % document.filename.split('/')[-1] # Here will return a full path, that's why probably you will need a split to get only the filename
add_never_cache_headers(response=response) # To avoid download the same file with out of date data.
return response
Then you will need an url
from myapp.views import CreateReport
url(r'^create_report/(?P<some_param_if_needed>[-\w]+)',
CreateReport.as_view(),
name='create_report'),
and finally in template
Download Report
EDIT
Here's a more complete example for get_data() method.
get_data(self):
# Let's supose you have a `MyElements` model
elements = MyElements.objects.all()
# And let's supose you want to filter data with some GET parameter
filter = self.request.GET.get('filter_name', None)
if filter is not None:
elements = elements.filter(filter_field=filter)
return elements

Filter only if the value is defined in Django

I have the following view:
def process(request):
if request.method == 'POST':
data = request.POST
results = Specs.objects.filter(screenGroup = data['screen_user'], storage = data['storage_user'], mSystem = data['system_user'] )
context = {'results' : results}
return render(request, 'process.html', context)
When the user inputs the three values it filters correctly, but when it just inputs one or two (or nothing), then it filters passing the value None. Is there any way to ignore the filter if it's not set?
Thanks!
EDIT:
The following code is working, but it's obviously a very unefficient way:
def process(request):
if request.method == 'POST':
data = request.POST
if(data['screen_user'] != None):
results = Specs.objects.filter(screenGroup = data['screen_user'])
elif (data['storage_user'] != None):
results = Specs.objects.filter(storage = data['storage_user'])
else:
results = Specs.objects.all()
#plus all the other options...
context = {'results' : results}
return render(request, 'process.html', context)
You can build the filter beforehand:
def process(request):
if request.method == 'POST':
data = request.POST
spec_filter = {}
for attribute in ['screenGroup', 'storage', 'mSystem']:
if attribute in data and data[attribute]:
spec_filter[attribute] = data[attribute]
results = Specs.objects.filter(**spec_filter)
context = {'results' : results}
return render(request, 'process.html', context)
NB: To use this verbatim you would have to change the names of the variables being passed in the request.POST to match those in the Specs model. I did this just to illustrate, but you can easily use the same principle with your variable names. In that case you'll have to be a bit more verbose.
It's called validating your form.. There are two ways of doing this:
create a django form and use myform.is_valid(). You can read about it in the docs
validate it yourself with a few 'if' statements (either on server side or with javascript before sending the ajax call)

Categories

Resources