I have a filter class defined below.
filters.py
class CTAFilter(django_filters.FilterSet):
id = django_filters.NumberFilter(label="DSID")
class Meta:
model = CTA
fields = ['id', 'EmailID','id','Shift_timing']
Now I want to use this CTAFilter in normal template(table data)view and in download views.
I have observed that It is working fine for normal render view but when I am using it in my download views it is not working and I am getting all model data in the .xls file.
Please find the below questions which I have posted.
how to use Django filtered class data to 2 seperate view
I am not able to resolve this problem I have tried to check if I can define it globally so that the filter will work for all views(like RESTAPI).
Is there any way I can make my download view as a child view class of normal render view so that I will use the below code from the parent view(as it is working fine)?
cta_list = CTA.objects.all()
cta_filter = CTAFilter(request.GET, queryset=cta_list) allcta = cta_filter.qs
A>Normal View where the filter is working fine.
def retrievecta_view(request):
if request.method == 'GET':
allcta = CTA.objects.all()
allcta1 = allcta
allctagen = allcta1.filter(Shift_timing__exact='General')
allctamor = allcta1.filter(Shift_timing__exact='Morning')
allctseve = allcta1.filter(Shift_timing__exact='Evening')
allctatotal = allcta1.filter(Shift_timing__exact='Total')
# For filtering using 'django_filters',
cta_list = CTA.objects.all()
cta_filter = CTAFilter(request.GET, queryset=cta_list)
allcta = cta_filter.qs
paginator = Paginator(allcta, 50)
page_number = request.GET.get('page')
try:
allcts = paginator.page(page_number)
except PageNotAnInteger:
allcts = paginator.page(1)
except EmptyPage:
allcts = paginator.page(paginator.num_pages)
return render(request, 'abcd/cta.html', {'allcta': allcta, 'cta_filter': cta_filter, 'allcta1': allcta1,
'allctagen': allctagen, 'allctamor': allctamor,
'allctaeve': allctaeve,
'allctatotal': allctatotal})
b> Download view where I am trying to use the same filter but it is giving me all records.
def exportcts_data(request):
response = HttpResponse(content_type='application/ms-excel')
response['Content-Disposition'] = 'attachment; filename="CTA_ShiftTiming.xls"'
wb = xlwt.Workbook(encoding='utf-8')
ws = wb.add_sheet('CTS_ShiftChange Data') # this will make a sheet named Users Data
# Sheet header, first row
row_num = 0
font_style = xlwt.XFStyle()
font_style.font.bold = True
columns = ['id','idk','Shift_timing','EmailID','Vendor_Company','Project_name','SerialNumber','Reason','last_updated_time']
for col_num in range(len(columns)):
ws.write(row_num, col_num, columns[col_num], font_style) # at 0 row 0 column
# Sheet body, remaining rows
font_style = xlwt.XFStyle()
cts_list = CTA.objects.all()
cts_filter = CTAFilter(request.GET, queryset=cts_list)
allcts = cts_filter.qs
rows = allcts.values_list('id', 'idk', 'Shift_timing', 'EmailID', 'Vendor_Company', 'Project_name',
'SerialNumber', 'Reason', 'last_updated_time')
for row in rows:
row_num += 1
for col_num in range(len(row)):
ws.write(row_num, col_num, row[col_num], font_style)
wb.save(response)
return response
I'm not quite following why you want to have separate view for downloads which ultimately should be rendering the same data as the normal view if they are using the same filter. Maybe it is just my misunderstanding so I'm not sure if this will help you but let's see.
First off let me explain a little background. This is a task management application and in there I have an html page where the person logged in can view all of their completed tasks. (Nice and simple.) However the user may have tasks from many different projects so I have created a dropdown list that allows them to filter by a single project. They may also want to only see a specific period of tasks so I have allowed them to set a date range by providing a start and end date. (Nothing startling or earth shattering here.) Once the parameters are set, the user clicks a search button and the filtered results are displayed. The page also has an Export button which downloads the results of the filtered list to a .xls spreadsheet.
So how do I do this? Well first of all, I am using Django-Tables2 for rendering my tables. I simple predefine the table in tables.py and throw it the data I want from my views and it takes care of everything. Therefore my view code is minimal and very simple and looks like this.
from django_tables2.export.export import TableExport
from .tables import CompletedTable
def completedlist(request, page='0', name=''):
#Check to see if we have clicked a button inside the form
if request.method == 'POST':
return redirect ('tasks:tasklist')
else:
# Pre-filtering of user and Master = True etc is done in the MasterListFilter in filters.py
# Then we compile the list for Filtering by.
f = CompletedListFilter(request.GET, queryset=Task.objects.all(),request=request)
# Then we apply the complete list to the table, configure it and then render it.
completedtable = CompletedTable(f.qs)
rows = len(completedtable.rows)
if int(page) > 0:
RequestConfig(request, paginate={'page': page, 'per_page': 10}).configure(completedtable)
else:
RequestConfig(request, paginate={'page': 1, 'per_page': 10}).configure(completedtable)
export_format = request.GET.get('_export', None)
if TableExport.is_valid_format(export_format):
exporter = TableExport(export_format, completedtable)
return exporter.response('Completed Tasks.{}'.format(export_format))
return render (request,'tasks/completedlist.html',{'completedtable': completedtable, 'filter': f, 'rows': rows})
As you can see, every time the user hits either the search or export buttons, I am recompiling the queryset in variable f with the following line:
f = CompletedListFilter(request.GET, queryset=Task.objects.all(),request=request)
I have predefined the .xls format in the html page with this code:
<button class="btn btn-primary btn-xs" name="_export" value="xls" type="submit">Export</button>
So then I can test to see if the user clicked the Export button or not by getting the value of _export from the request like this:
export_format = request.GET.get('_export', None)
If the user did not click the export button, export_format will default to none. If they did, it will be .xls as defined in the html. Then I simply either export the data in line with the filters set by the user or I render the page with the same filtered list of data like this:
if TableExport.is_valid_format(export_format):
exporter = TableExport(export_format, completedtable)
return exporter.response('Completed Tasks.{}'.format(export_format))
return render (request,'tasks/completedlist.html',{'completedtable': completedtable, 'filter': f, 'rows': rows})
So there you have it. As you say your filter is working for the normal view I have not detailed my filter as that would seem to be unnecessary.
Maybe this solution is too simplistic for your requirements and yes, before I get shot down by other developers, there are several limitations, such as 'What if the user wants to use something other than .xls?' or 'What if they want to export more than one Project at a time?' Like everything, there is always room for improvement but when I'm bashing my head with an issue, I often find it helps to strip things back to basics and see what comes from that.
UPDATE!
My goal is to modify an existing Workbook ( example - master_v2.xlsm ) and produce a new workbook (Newclient4) based on the updates made to master_v2.
I'm using a single sheet within master_v2 to collect all the data which will be determining what the new workbook will be.
Currently using multiple if statements to find the value of the cells in this "repository" sheet. Based on specific cells, I'm creating and adding values to copies of an existing sheet called "PANDAS".
My goal right now is to create a dict based on two columns. The loop through
the keys so that every time I get a hit on a cell, I will gather values from specific keys.
That's listed below:
from openpyxl import load_workbook
# Start by opening the spreadsheet and selecting the main sheet
workbook = load_workbook(filename="master_v2.xlsm",read_only=False, keep_vba=True)
DATASOURCE = workbook['repository']
DATASOURCE["A:H"]
cell100 = DATASOURCE["F6"].value
CREATION = cell100
cell101 = DATASOURCE["F135"].value
CREATION2 = cell101
cell107 = DATASOURCE["F780"].value
CREATION7 = cell107
if CREATION.isnumeric():
source = workbook['PANDAS']
target = workbook.copy_worksheet(source)
ss_sheet = target
ss_sheet.title = DATASOURCE['H4'].value[0:12]+' PANDAS'
if CREATION2.isnumeric():
source = workbook['PANDAS']
target = workbook.copy_worksheet(source)
ss_sheet = target
ss_sheet.title = DATASOURCE['H133'].value[0:12]+' PANDAS'
if CREATION3.isnumeric():
source = workbook['PANDAS']
target = workbook.copy_worksheet(source)
ss_sheet = target
ss_sheet.title = DATASOURCE['H262'].value[0:12]+' PANDAS'
else:
print ("no")
workbook.save(filename="NewClient4.xlsm")
Instead of the many if statements I was hoping to be able to loop through the column as explained above,
once I found my value, gather data and copy it over to a copy of sheet which is then filled out by other cells. Each time the loop comples, I want to do repeat on the next match of the string.. but I'm only this far and it's not quite working.
Anyone have a way to get this working?
( trying to replace the many one to one mappings and if statements )
for i in range(1,3000):
if DATASOURCE.cell(row=i,column=5).value == "Customer:":
source = workbook['Design details']
target = workbook.copy_worksheet(source)
ss_sheet = target
ss_sheet.title = DATASOURCE['H4'].value[0:12]+' Design details'
else:
print ("no")
Thank you guys in advanced
Problem: I have a program that scrapes Twitter and returns the results in an excel file. Part of each entry is a column containing a hyperlink to the Tweet and image included in the Tweet if applicable. Entries and hyperlinks work fine except when I run the following code to remove duplicate posts:
#Remove duplicate posts.
values = []
i = 2
while i <= sheet.max_row:
if sheet.cell(row=i,column=3).value in values:
sheet.delete_rows(i,1)
else:
values.append(sheet.cell(row=i,column=3).value)
i+=1
After running the duplicate removal snippet the hyperlinks point to what I assume is the offset of deleted entries. Here is the code for creating a Twitter entry:
sheet.cell(row=row, column=8).hyperlink = "https://twitter.com/"+str(tweet.user.screen_name)+"/status/"+str(tweet.id)
sheet.cell(row=row, column=8).style = "Hyperlink"
Expected Results: Should be able to remove duplicate entries and keep the hyperlink pointed to the correct address.
The hyperlinks point to the correct addresses for whatever reason when I change the code to the this:
sheet.cell(row=row, column=8).value = "https://twitter.com/"+str(tweet.user.screen_name)+"/status/"+str(tweet.id)
sheet.cell(row=row, column=8).style = "Hyperlink"
Requires a rapid double click to work as a hyperlink in the excel sheet versus the one click when inserting using .hyperlink.
So fixed but not fixed.
I am trying to create a combobox in ttk that will take output from an SQL query and put it in its drop down menu. To do this I have used postcommand in my combobox as below:
self.Port_Drop_Down = ttk.Combobox(EDM_DB_frm, state="readonly", postcommand=self.upd_edm_ports)
and then have the SQL function it is calling working like below:
def upd_edm_ports(self):
portinfo_tpl = rgu.get_edm_ports("server", "database")
self.Port_Drop_Down["values"] = portinfo_tpl
The portinfo_tpl is generating a tuple looking like ("port1", "port2", ..., "portn").
But when I access the drop down nothing shows up.
I have a program written in python 3.5 which scans a directory and stores the info in a SQLITE3 db. This info can be displayed in a ttk.treeview in the client.
The 2 main functions are 1) "scan" which adds the information to the db and 2) viewFiles which is below (it just grabs data from the db and displays it in the treeview).
During the scan function, a second tkinter window is opened and displays information on whats been scanned. If I try to use the viewFiles fucntion without a restart, the data displayed is invisible but I know the data is there because I can copy paste it into a text document). If I restart the client, the text is displayed correctly after pressing the button linked to the viewFiles function.
I think it must be something to do with the the focus shift thanks to this 2nd window opening during the scan process but I'm not sure and can't find any similar case to learn from.
def viewFiles(self):
global dataTreeView
results = []
foldersContentsToView = yieldFoldersToView()
for dpath in foldersContentsToView:
sqlstring= "SELECT * FROM DBDATA WHERE directorypath=:dpath"
values = {"dpath": dpath}
[results.append(i) for i in databaseFunctions.getDBobject().returnSelectQueryResults(sqlstring, values)]
for e in results:
dataTreeView.insert('', 'end', values=list(e))
Does anyone have any ideas?
The issue was that the columns were being set up in the moment the treeview was created by querying the fields in the database. However before the first scan, there were no records in the db and so the columns were not being configured properly until a restart, after which data existed and could be queried on treeview creation.
To fix the issue, I moved the column configure data to the viewFiles function like so:
def viewFiles(self):
global dataTreeView
audioDataTree['columns'] = returnListTableFields()
#Configure Columns
for column in listofdbtablefields():
dataTree.column(column,width=len(column)*10)
dataTree.heading(column, text=column)
dataTree.column(column, anchor='center')
#Hide First Column (TreeLabel)
dataTree.column('#0',width=0)
results = []
foldersContentsToView = yieldFoldersToView()
for dpath in foldersContentsToView:
sqlstring= "SELECT * FROM DBDATA WHERE directorypath=:dpath"
values = {"dpath": dpath}
[results.append(i) for i in databaseFunctions.getDBobject().returnSelectQueryResults(sqlstring, values)]
for e in results:
dataTreeView.insert('', 'end', values=list(e))