Want to prompt browser to save csv - python

Want to prompt browser to save csv using pyramid.response.Response searched for clues and found here's a link Django answer but i can't use it with Pyramid wsgi my code looks like this:
from pyramid.response import Response
def get_list_names_emails(request):
session, env = request.db, request.client_env
response = Response(content_type='text/csv')
output = StringIO()
writer = csv.writer(output)
writer.writerow(['SomeName', 'SomeEmail', 'CompanyName])
csv_output = output.getvalue()
return csv_output

As a cleaner way to do that, you can register a renderer.
In your configuration set-up, add:
config.add_renderer(name='csv',
factory='mypackage.renderers.CSVRenderer')
then in mypackage/renderers.py:
class CSVRenderer(object):
def __init__(self, info):
pass
def __call__(self, value, system):
fout = StringIO.StringIO()
writer = csv.writer(fout, delimiter=';', quoting=csv.QUOTE_ALL)
writer.writerow(value['header'])
writer.writerows(value['rows'])
resp = system['request'].response
resp.content_type = 'text/csv'
resp.content_disposition = 'attachment;filename="report.csv"'
return fout.getvalue()
After that, you can decorate your view with the renderer:
#view_config(..., renderer='csv')
def myview(self):
header = ['name', 'surname', 'address']
rows = [
(
row['name'],
row['surname'],
row['address'],
)
for row in query_rows(.....)
]
return {
'header': header,
'rows': rows
}
The advantage of this approach is better testable view code (you just check for the dictionary values, no need to parse anything) and you can also add a XLS or whatever renderer to the same view:
#view_config(..., renderer='xls')
#view_config(..., renderer='csv')
def myview(self):
...

Try adding Content-Disposition:
response['Content-Disposition'] = 'attachment; filename="report.csv"'

It's better to set content type as well
response['Content-type'] = 'text/csv'
response['Content-Disposition'] = 'attachment; filename="report.csv"'

Related

How to include a dropdown query into a HttpResponse view

I would like to convert to excel contents of a model after passing a filter from the dropdown selection . Here is the view.
def ConvertToExcelView(request):
response = HttpResponse(content_type='text/csv')
writer = csv.writer(response)
writer.writerow([('name'), ('adm'),('form'),('stream') ])
for member in Marks.objects.filter(student__school__name=request.user.school).values_list('student__name', 'student__adm', 'student__klass__name', 'student__stream__name':
writer.writerow(member)
response['Content-Disposition'] = 'attachment; filename="members.csv"'
return response
Is there a way I can incorporate this into the view????
query = request.GET.get('view_classes')
if query:
queryset = (Q(student__klass__name__icontains = query))
return render(request,'students_marks.html',all_mark_results)
Please ask for more clarifications incase I'm not clear with this.
This is fairly simple. Simply include the get request and give a name to the form you intend to get the selection from i.e.
def ConvertToExcelView(request):
details = request.GET.get('s_details') #Assuming the form name is s_details
queryset = (Q(student__klass__name__exact = details))
response = HttpResponse(content_type='text/csv')
writer = csv.writer(response)
writer.writerow([('name'), ('adm'),('form'),('stream') ])
for member in Marks.objects.filter(queryset).distinct().filter(student__school__name=request.user.school).values_list('student__name', 'student__adm', 'student__klass__name', 'student__stream__name':
writer.writerow(member)
response['Content-Disposition'] = 'attachment; filename="members.csv"'
return response
This will work like charm.
Revert if there are explanations you need.

CSV Download of User Info Django

I am trying to download some user data into a csv file. I am able to generate the User fields just fine but when I try to access the onetoone relation field I am running into issues!
Tried numerous different way to get here. Just can't seem to figure out how to get the correct related data.
def export_to_csv (modeladmin, request, queryset):
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
from wsgiref.util import FileWrapper
cols = ['username','email','first_name','last_name','my_profile.dealer_num']
# get qs values
data = list( queryset.values_list(*cols) )
if not data:
messages.error(request, 'No data to export')
return HttpResponseRedirect( request.get_full_path() )
# create empty csv
csv_file = StringIO()
csv_writer = csv.writer(csv_file, quoting = csv.QUOTE_ALL)
# add headers
csv_writer.writerow( cols )
# add qs values
for row in data:
csv_writer.writerow( [s.encode('utf-8') for s in row] )
csv_file.flush()
csv_file.seek(0)
response = HttpResponse(FileWrapper( csv_file ), content_type='text/csv')
response['Content-Disposition'] = "attachment; filename=user-csv-export.csv"
return response
export_to_csv.short_description = "Export to CSV"
Models.py
class MyProfile(UserenaBaseProfile):
user = models.OneToOneField(User,
unique=True,
verbose_name=_('user'),
related_name='my_profile')
dealer_num = models.CharField(blank=True,
max_length=15,
verbose_name="Dealer Number")
Should return everything including a 5 digit dealer number in a csv
You are not accessing the field correctly, you need to use __ as in a query.
Change cols to:
cols = ['username','email','first_name','last_name','my_profile__dealer_num']

Storing the blank file using Django and Python

I need some help. I need to save the .csv file into local folder using Python but its storing the blank file. I am explaining my code below.
views.py:
report = Reactor.objects.all()
filename = str(uuid.uuid4()) + '.csv'
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename='+filename
with open(settings.FILE_PATH + filename, 'w') as csv_file:
file_writer = csv.writer(csv_file)
response_writer = csv.writer(response)
file_writer.writerow(['Name', 'Status', 'Date'])
response_writer.writerow(['Name', 'Status', 'Date'])
for rec in report:
if rec.status == 1:
status = 'Start'
if rec.status == 0:
status = 'Stop'
if rec.status == 2:
status = 'Suspend'
file_writer.writerow([rec.rname, status, rec.date])
response_writer.writerow([rec.rname, status, rec.date])
return response
settings.py:
FILE_PATH = os.getcwd()+'/upload/'
Here I am also downloading the file and I need to save that file into folder but here some blank file is storing. Please help me.
As jasonharper said you are only writing the csv data to the response and not to the file on the disk. Start by creating another writer object:
file_writer = csv.writer(open(settings.FILE_PATH + filename, 'w'))
Now each time you call writerow on writer also do this for the file_writer:
file_writer.writerow(['Name', 'Status', 'Date'])
...
file_writer.writerow([rec.rname, status, rec.date])
It is best to use the with statement to let python automatically close the file:
with open(settings.FILE_PATH + filename, 'w') as csv_file:
file_writer = csv.writer(csv_file)
response_writer = csv.writer(response)
file_writer.writerow(['Name', 'Status', 'Date'])
response_writer.writerow(['Name', 'Status', 'Date'])
for rec in report:
...
file_writer.writerow([rec.rname, status, rec.date])
response_writer.writerow([rec.rname, status, rec.date])
return response

Save a writable file into database?

I am using django 1.8 and python 3.4 and trying to create a json file and then writing into it, after that I need to save it to my database but on save it returns me an error '_io.TextIOWrapper' object has no attribute '_committed'. Can anyone please help where I am doing wrong?
Here is my models.py
class ConvertedFile(models.Model):
file = models.FileField(upload_to='json/upload', max_length=5000)
created_on = models.DateTimeField(auto_now_add=True)
My views.py is-
def convert_file(request):
url = request.GET.get('q', None)
r = requests.get(url, stream=True)
with open('file.csv', 'wb') as out_file:
shutil.copyfileobj(r.raw, out_file)
csvfile = open("file.csv", "r")
jsonfile = open("file.json", "w")
csv_rows = []
reader = csv.DictReader(csvfile)
title = reader.fieldnames
try:
for row in reader:
csv_rows.extend([{title[i]: row[title[i]] for i in range(len(title))}])
except:
pass
jsonfile.write(json.dumps(csv_rows, sort_keys=False, indent=4, separators=(',', ': '), ensure_ascii=False))
os.remove("file.csv")
jsonfile.close()
new_json = ConvertedFile.objects.create()
new_json.file = jsonfile
new_jsone.save()
The error raises on model.save() in the last line, right? The line above new_json.file = jsonfile is the problem. You pass the reference to a closed (plain python) file object to the FileField from django and it does not know how to deal with it (_commited is missing for example).
Have a look at Django - how to create a file and save it to a model's FileField?

Exporting items from a model to CSV Django / Python

I'm fairly new to django and Python and want to be able to export a list of items in my model i.e products. I'm looking at the documentation here - https://docs.djangoproject.com/en/dev/howto/outputting-csv/
I'm persuming I need will need to create a variable that stores all the data that I want. But not sure where it would within the snippet of code on the link above.
Apologies as this is a very noobish question but would really Any help at all.
Here is the code to my script so far:
import csv
from products.models import Product
from django.http import HttpResponse
def export_to_csv(request):
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="mytest.csv"'
Have a look at the python csv module.
You'll probably want to get the models fields with
def get_model_fields(model):
return model._meta.fields
Then use
getattr(instance, field.name)
to get the field values (as in this question).
Then you'll want something like
with open('your.csv', 'wb') as csvfile:
writer = csv.writer(csvfile)
# write your header first
for obj in YourModel.objects.all():
row = ""
for field in fields:
row += getattr(obj, field.name) + ","
writer.writerow(row)
It's a bit verbose (and untested), but it should give you an idea. (Oh and don't forget to close your file)
Depending on the scenario - you may want to have a CSV of your model. If you have access to the Django Admin site, you can plug in a generic action for any model displayed as a list (google: django admin actions)
http://djangosnippets.org/snippets/790/
If you're operating with a console (python manage.py ...), you can use such a script, which I just used:
(place it in: yourapp/management/commands/model2csv.py)
"""
Prints CSV of all fields of a model.
"""
from django.core.management.base import BaseCommand, CommandError
import csv
import sys
class Command(BaseCommand):
help = ("Output the specified model as CSV")
args = '[appname.ModelName]'
def handle(self, *app_labels, **options):
from django.db.models import get_model
app_name, model_name = app_labels[0].split('.')
model = get_model(app_name, model_name)
field_names = [f.name for f in model._meta.fields]
writer = csv.writer(sys.stdout, quoting=csv.QUOTE_ALL)
writer.writerow(field_names)
for instance in model.objects.all():
writer.writerow([unicode(getattr(instance, f)).encode('utf-8') for f in field_names])
This does not catch any exceptions etc., but as an Admin you won't cause them to be raised, right?
Use it like:
./manage.py model2csv my_ecommerce.Product > products.csv
You can also make a template to assist in formatting!
The template is a common Django template
from django.template import loader
def export_to_csv(request):
response = HttpResponse(mimetype='text/csv')
response['Content-Disposition'] = 'attachment; filename="products-list.csv"'
template = loader.get_template('templates/products_template.csb')
response.write(template.render(Context({'products': Products.objects.all()})))
return response
Using django.db.models.query.QuerySet.values results in more optimised queries for my use case.
import csv
from datetime import datetime
from django.http import HttpResponse
# Populate this list with your model's fields
# Replace MODEL with your model
fields = [f.name for f in MODEL._meta.fields]
# The following code will live inside your view
timestamp = datetime.now().isoformat()
response = HttpResponse(content_type="text/csv")
response[
"Content-Disposition"
] = f"attachment; filename={timestamp}.csv"
writer = csv.writer(response)
# Write the header row
writer.writerow(fields)
# Replace MODEL with your model
for row in MODEL.objects.values(*fields):
writer.writerow([row[field] for field in fields])
return response
I use this on my code. A function called from view.
It automatically get model fields to make columns.
You can also customize the field list you want to export.
Function
import csv
from django.http import HttpResponse
from .models import Books
def export_qs_to_csv(model_class = None, qs = None, field_names = None):
if model_class and not qs:
qs = model_class.objects.all()
if qs and not model_class:
model_class = qs.model
meta = model_class._meta
if not field_names:
field_names = [field.name for field in meta.fields]
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename={}.csv'.format(meta)
writer = csv.writer(response)
writer.writerow(field_names)
for obj in qs:
row = writer.writerow([getattr(obj, field) for field in field_names])
return response
Usage
#user_passes_test(lambda u: u.is_superuser)
def export_books(request):
return export_qs_to_csv(model_class = Books)
# or
return export_qs_to_csv(qs = Books.objects.filter(published = True))
# or
return export_qs_to_csv(
qs = Books.objects.filter(published = True),
field_names = [
"title",
"price",
"publishing_date",
]
)
Original answer
It works, and it needs only to define model class in model_class variable.
This Django view let use downloads CSV. CSV name is Django_app.model_name.csv.
import csv
from django.http import HttpResponse
from .models import Trade
def export_to_csv(request):
# The only line to customize
model_class = Trade
meta = model_class._meta
field_names = [field.name for field in meta.fields]
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename={}.csv'.format(meta)
writer = csv.writer(response)
writer.writerow(field_names)
for obj in model_class.objects.all():
row = writer.writerow([getattr(obj, field) for field in field_names])
return response
Here is a potential solution, based on #tomasz-gandor 's answer, but updated to 2020:
"""
Prints CSV of all fields of a model.
"""
import csv
from django.core.management.base import BaseCommand, CommandError
class Command(BaseCommand):
help = ("Output the specified model as CSV")
def add_arguments(self, parser):
parser.add_argument('model',
nargs=1,
type=str,
help='Model name to export, like <app.model> or "members.Member"')
parser.add_argument('outfile',
nargs=1,
type=str,
help='Save path, like </path/to/outfile.csv> or "/data/members.csv"')
def handle(self, *app_labels, **options):
from django.apps import apps
app_name, model_name = options['model'][0].split('.')
model = apps.get_model(app_name, model_name)
field_names = [f.name for f in model._meta.fields]
writer = csv.writer(open(options['outfile'][0], 'w'), quoting=csv.QUOTE_ALL, delimiter=',')
writer.writerow(field_names)
for instance in model.objects.all():
writer.writerow([str(getattr(instance, f)) for f in field_names])
Can easily be used with:
python manage.py model2csv members.Member /data/members_export.csv
If you don't care about fieldnames and want all the fields, just do this.
with open('file_name.csv', 'w') as csvfile:
writer = csv.writer(csvfile)
for obj in YourModel.objects.values_list():
row = list(obj)
writer.writerow(row)
I combined some of the previous answers, because I needed to import some data from production and change some of it along the way. So here is my solution, which you can use to override some field values while writing the CSV file.
Export some queryset data into CSV file:
import csv
from myapp.models import MyModel
from user.models import User
# Make some queryset manually using Django shell:
user = User.objects.get(username='peterhil')
queryset = MyModel.objects.filter(user=user)
def query_to_csv(queryset, filename='items.csv', **override):
field_names = [field.name for field in queryset.model._meta.fields]
def field_value(row, field_name):
if field_name in override.keys():
return override[field_name]
else:
return row[field_name]
with open(filename, 'w') as csvfile:
writer = csv.writer(csvfile, quoting=csv.QUOTE_ALL, delimiter=',')
writer.writerow(field_names) # write the header
for row in queryset.values(*field_names):
writer.writerow([field_value(row, field) for field in field_names])
# Example usage:
query_to_csv(queryset, filename='data.csv', user=1, group=1)
Use this solution for model csv file.might being helpful
# Create the HttpResponse object with the appropriate CSV header.
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment;
filename="somefilename.csv"'
writer = csv.writer(response);
writer.writerow(["username","Email"]);
for i in User.objects.all():
writer.writerow([i.username,i.email])
return response
I used the django-queryset-csv package.
Follow these steps:
pip install django-queryset-csv
Your views.py:
import djqscsv
from products.models import Product
def get_csv(request):
qs = Product.objects.all()
return djqscsv.render_to_csv_response(qs)

Categories

Resources