Exporting Django models to Excel (different sheets) using Django-tables2 - django

I've checked django-tables2 documentation, however I haven't find an easy way to export models to different sheets in Excel. To make it simple, let's suppose I have two different models: Sales and Products. I would like to export an excel document with two different sheets: Sales and Products. I can export the first model with the code shown below, but I'm not sure if there's a way to export the Products model to another sheet. Any help would be appreciated.
export_format = request.GET.get('_export', None)
if TableExport.is_valid_format(export_format):
table = [[Sales Table Object]]
exporter = TableExport(export_format, table)
return exporter.response('File_Name.{}'.format(export_format)) ```

So, I came with a simple solution, probably not the most efficient, by using pandas. Convert the queryset to pandas dataframe and use pandas ExcelWriter to generate the excel and it can be done for different sheets. Probably for deployment with large data, might be better to use libraries like xlsxwriter but it works for what I wanted to do.
iden= request.GET["id"]
output = BytesIO()
queryset = Efectivo.objects.filter(Q(id1=iden)).values()
df = pd.DataFrame(queryset)
writer = pd.ExcelWriter(output,engine='xlsxwriter')
df.to_excel(writer,sheet_name='Efectivo')
writer.save()
output_name = 'example'
output.seek(0)
response = HttpResponse(output,
content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
response['Content-Disposition'] = f'attachment; filename={output_name}.xlsx'
return response```

Try using xlsxwriter:
response = HttpResponse(content_type='application/vnd.ms-excel')
# tell the browser what the file is named
response['Content-Disposition'] = 'attachment;filename="file_name.xlsx"'
writer = pd.ExcelWriter(response, engine = 'xlsxwriter')
#d1 and d2 are pandas dataframe
d1.to_excel(writer, sheet_name='Sheet1',index=False)
d2.to_excel(writer, sheet_name='Sheet2',index=False)
writer.save()

Related

Django: serialize an annotated and aggregated queryset to GeoJSON

I am trying to use Django ORM (or any other way using Django) to execute this query (PostgreSQL) AND send the result back to the front end in GeoJSON format.
I am using Django 2.2.15
SELECT string_agg(name, '; '), geom
FROM appname_gis_observation
where sp_order = 'order1'
GROUP BY geom;
The model looks like this (models.py)
from django.db import models
from django.contrib.gis.db import models
class gis_observation(models.Model):
name = models.CharField(max_length=100,null=True)
sp_order = models.CharField(max_length=100,null=True)
geom = models.MultiPointField(srid=4326)
So I thought this would work (views.py)
from django.core.serializers import serialize
from .models import *
from django.shortcuts import render
from django.contrib.postgres.aggregates.general import StringAgg
def show_observation(request):
results = gis_observation.objects.values('geom').filter(sp_order='order1').annotate(newname=StringAgg('name', delimiter='; '))
data_geojson = serialize('geojson', results, geometry_field='geom', fields=('newname',))
return render(request, "visualize.html", {"obs" : data_geojson})
The ORM query works fine in the Django shell but Django complains at the serialize step: AttributeError: 'dict' object has no attribute '_meta'.
Even if the serialize step worked, I suspect it would skip my annotated field (by reading other posts)
Apparently I am not the only one who met that same problem but I could not find a solution for it.
This is the solution I came up with. Frankly I'd be glad to accept another answer, so any proposal still welcome!
In the end, I built a Geojson array by looping though the result set. I guess I could as well have gone for a cursor sql query instead and skip the orm api entirely.
queryset = gis_species_observation.objects.values('geom').filter(sp_order='order1').annotate(name=StringAgg('name', delimiter='; '))
mydict = []
results = list(queryset)
for result in results:
rec = {}
rec["type"] = "Feature"
rec["geometry"] = json.loads(result["geom"].geojson)
rec["properties"] = {"name":result["name"]}
mydict.append(rec)
data_geojson = json.dumps(mydict)
return render(request, "visualize_romania.html", {"mynames" :data_geojson})

How can I pass my sqlite data to django, and make chart?

I'm trying to make line chart using data in sqlite database.
But I have no idea how to pass my data to views.py and html template file.
I want to make line chart ( x-axle : date , y-axle : count by date )
I tried to make it using raw queryset and other things...
requestCnt = ActivityLog.objects.raw("SELECT date(doDate), count(requestType) FROM mainApp_activitylog GROUP BY doDate")
OR
requestCnt = ActivityLog.objects.values('doDate').annotate(Count('requestType'))
AND ETC...
Models.py
class ActivityLog(models.Model):
doDate = model.DateTimeField()
userIP = models.CharField(max_length=200)
userName =models.CharField(max_length=200)
requestType = models.CharField(max_length=200)
Below is my raw sqlite query.
sqlite> SELECT date(doDate), count(requestType) FROM mainApp_activitylog GROUP BY doDate;
and the result is as below
2019-04-15|3
2019-04-16|16
2019-04-17|13
2019-04-18|10
2019-04-19|13
2019-04-22|24
How can I pass those results above to X-Axle and Y-axle ?
I want to make line chart (X-Axle:date , Y-axle: request count by date)
I have a little idea that I should use Json dumps or things like that.
I've already encountered error such as " cannot be serialized as Json file (?) "
I really hope someone can solve my problem.
Thx for your help in advance.
You can send the queryset to the template in the context and use the values there.
class YourTemplate(TemplateView):
def get_context_data(self, **kwargs):
requestCnt = ActivityLog.objects.annotate(request_count=Count('requestType')).values('doDate', 'request_count')
context = super().get_context_data(**kwargs)
context["data"] = requestCnt
return context
Then in your template, you can use data variable to get the data for both the axis. The data will be of the format:
[{"doDate":"...", "request_count":"..."}, {"doDate":"...", "request_count":"..."}]

"SELECT...AS..." with related model data in Django

I have an application where users select their own display columns. Each display column has a specified formula. To compute that formula, I need to join few related columns (one-to-one relationship) and compute the value.
The models are like (this is just an example model, actual has more than 100 fields):
class CompanyCode(models.Model):
"""Various Company Codes"""
nse_code = models.CharField(max_length=20)
bse_code = models.CharField(max_length=20)
isin_code = models.CharField(max_length=20)
class Quarter(models.Model):
"""Company Quarterly Result Figures"""
company_code = models.OneToOneField(CompanyCode)
sales_now = models.IntegerField()
sales_previous = models.IntegerField()
I tried doing:
ratios = {'growth':'quarter__sales_now / quarter__sales_previous'}
CompanyCode.objects.extra(select=ratios)
# raises "Unknown column 'quarter__sales_now' in 'field list'"
I also tried using raw query:
query = ','.join(['round((%s),2) AS %s' % (formula, ratio_name)
for ratio_name, formula in ratios.iteritems()])
companies = CompanyCode.objects.raw("""
SELECT `backend_companycode`.`id`, %s
FROM `backend_companycode`
INNER JOIN `backend_quarter` ON ( `backend_companycode`.`id` = `backend_companyquarter`.`company_code_id` )
""", [query])
#This just gives empty result
So please give me a little clue as to how I can use related columns preferably using 'extra' command. Thanks.
By now the Django documentation says that one should use extra as a last resort.
So here is a query without extra():
from django.db.models import F
CompanyCode.objects.annotate(
growth=F('quarter__sales_now') / F('quarter__sales_previous'),
)
Since the calculation is being done on a single Quarter instance, where's the need to do it in the SELECT? You could just define a ratio method/property on the Quarter model:
#property
def quarter(self):
return self.sales_now / self.sales_previous
and call it where necessary
Ok, I found it out. In above using:
CompanyCode.objects.select_related('quarter').extra(select=ratios)
solved the problem.
Basically, to access any related model data through 'extra', we just need to ensure that that model is joined in our query. Using select_related, the query automatically joins the mentioned models.
Thanks :).

Django: Querying time from datetime fields

On o postgresql db based Django, how can I filter by time for a datetimefield as below?
class Foo(models.Model):
start_date = models.DateTimeField()
end_date = models.DateTimeField()
IE: I want to filter Foo objects with "16:30" start_date and "19:00" end_date.
Thanks.
What about adding in a TimeField?
http://docs.djangoproject.com/en/dev/ref/models/fields/#timefield
Otherwise you would need to write a custom query to take advantage of the databaseĀ“s time capabilites since DateTimeFields don't have that capability natively in Django.
You could consider writing a function to denormalize hours and minutes from start_date to a new start_time field and then query the start_time field.
Solution to my own q:
def query_by_times(start_hour, start_min, end_hour, end_min):
query = 'EXTRACT(hour from start_date) = %i and EXTRACT(minute from start_date) = %i and EXTRACT(hour from end_date) = %i and EXTRACT(minute from end_date) = %i' % (start_hour, start_min, end_hour, end_min)
return Foo.objects.extra(where=[query])
In your situation, database normalization looks like thebest solution, since execution time and system load will rise as your related database table keeps more records...
Another solution to do this without using database filer functions is using filter alongside lambda:
from datetime import time
records = Foo.objects.all()
filtered = filter(lambda x: (time(16,30)==x.start_date.time() and time(19,0)==x.end_date.time()), records)
But using this on a large dataset will need too much time and system resource.
Try
Foo.objects.filter(start_date = MyDate1, end_date = MyDate2)
where MyDate1 and MyDate2 are your defined datetime objects. It should work, right?
I think which you need uses the range[1].
[1]http://docs.djangoproject.com/en/1.2/ref/models/querysets/#range

django date filter gte and lte

I need to find data within a certain set of parameters
I am building a small booking system, that lets user see what vehicles are available for booking for their little safari trip.
The system has bookings that have been entered previously or made previously by a client.
If a booking's pickup_date = 2011-03-01 and dropoff_date = 2011-03-15 and I run a query with pickup=2011-03-09 and dropoff=2011-03-14 in my views as below, it doesn't return any results to see if a booking within that timeframe has been made.
views.py
def dates(request, template_name='groups/_dates.html'):
pickup=request.GET.get('pickup','None');
dropoff=request.GET.get('dropoff','None');
order = Order.objects.filter(pick_up__lte=pickup).filter(drop_off__gte=dropoff)
context = {'order':order,}
return render_to_response(template_name,context,
context_instance=RequestContext(request))
Any suggestions on how to do this?
Or should I be looking at an alternate way of running this query?
Could it be posible that as your passing the raw string to the queryset is not on the correct format, try converting the strings to datetime objects.
Later you can try using the range lookup is more efficient on some DB engines and more simple to read and code.
from django.db.models import Q
start_date = datetime.date(2005, 1, 1)
end_date = datetime.date(2005, 3, 31)
orders = Order.objects.filter(drop_off__gte=start_date, pick_up__lte=end_date)
# Or maybe better
orders = Order.objects.filter(Q(drop_off__gte=start_date), Q(pick_up__lte=end_date))
Can you try this :
order = Order.objects.filter(pick_up**__date__**lte=pickup).filter(drop_off**__date__**gte=dropoff)
https://docs.djangoproject.com/fr/2.0/ref/models/querysets/#date