python how to sort a list - python

i have to display a list shift wise like have to first show all day shift results then afternoon then night
but now it shows afternoon first then night then day
here is my code
views.py:
def get_queryset(self):
getall = self.request.GET.get("getall")
if self.request.user:
versions = LogVersion.objects.filter(
form__airport__id=self.request.user.aerosimple_user.airport_id
).exclude(status=DRAFT)
filters = self.request.GET.get("filters")
tags = self.request.GET.get("tags")
logs = Log.objects.none()
result = Log.objects.none()
for v in versions:
if len(v.operation_logs.order_by('-id').all())>0:
result = result | v.operation_logs.order_by('-id').all()
result = result.exclude(shift_name = None).exclude(shift_name='')
# if getall:
if getall:
return Log.objects.filter(
form__form__airport__id=self.request.user.aerosimple_user.airport.id)
if filters is not None:
filters = filters[:-2] if filters[-2:] == ',,' else filters
filters_list = filters.split(',,')
for filters in filters_list:
log = result.filter(Q(type = filters) | Q(subtype = filters))
if filters == 'Inspection Completed':
log = result.filter(Q(description = filters))
elif log != []:
for r in result:
if r.tags is not None and filters in r.tags:
log =result.filter(id=r.id)
else:
log = result.filter(Q(type = filters) | Q(subtype = filters))
logs = logs | log
return logs.all()
return result
how to sort it correctly

Example:
logs = sorted(logs, key=lambda x: dict(day=1, afternoon=2, night=3)[x.shift])

Related

SQLAlchemy - Filtering with multiple conditions

I append number of queries into a list and then filter the table using sqlachemies query function and or_. Table consists of warehouses, and I want to query them using names, available storage, prices and services. The logic should be correct but I get error
subquery must return only one column
#search.route('/search/filter', methods = ['POST'])
def filter():
name = request.form.get('name')
n_storage = request.form.get('n_storage')
#MIN PRICE MAX PRICE
min_p = request.form.get('min_p')
max_p = request.form.get('max_p')
#SERVICES
labelling = True if request.form.get('labelling') else False
manual_geo_data_entry = True if request.form.get('manual_geo_data_entry') else False
item_packaging = True if request.form.get('item_packaging') else False
palette_packaging = True if request.form.get('palette_packaging') else False
filters = []
if name:
filters.append(Warehouse.query.filter(Warehouse.name.match(name)))
if n_storage:
filters.append(Warehouse.query.filter(Warehouse.volume_available > n_storage))
#FILTERING BASED ON SERVICES
if labelling:
filters.append(Warehouse.query.filter(Warehouse.labelling.is_(True)))
if manual_geo_data_entry:
filters.append(Warehouse.query.filter(Warehouse.manual_geo_data_entry.is_(True)))
if item_packaging:
filters.append(Warehouse.query.filter(Warehouse.item_packaging.is_(True)))
if palette_packaging:
filters.append(Warehouse.query.filter(Warehouse.palette_packaging.is_(True)))
results = Warehouse.query.filter(or_(*filters)).all()
return render_template('search/search.html', title = 'Search', data = results)
sqlalchemy.exc.ProgrammingError: (psycopg2.errors.SyntaxError) subquery must return only one column
LINE 3: WHERE (SELECT "PilotApp_warehouse_test".id, "PilotApp_wareho...
^
[SQL: SELECT "PilotApp_warehouse_test".id AS "PilotApp_warehouse_test_id", "PilotApp_warehouse_test".name AS "PilotApp_warehouse_test_name", "PilotApp_warehouse_test".volume_available AS "PilotApp_warehouse_test_volume_available", "PilotApp_warehouse_test".volume_total AS "PilotApp_warehouse_test_volume_total", "PilotApp_warehouse_test".labelling AS "PilotApp_warehouse_test_labelling", "PilotApp_warehouse_test".manual_geo_data_entry AS "PilotApp_warehouse_test_manual_geo_data_entry", "PilotApp_warehouse_test".item_packaging AS "PilotApp_warehouse_test_item_packaging", "PilotApp_warehouse_test".palette_packaging AS "PilotApp_warehouse_test_palette_packaging", "PilotApp_warehouse_test".address AS "PilotApp_warehouse_test_address", "PilotApp_warehouse_test".email AS "PilotApp_warehouse_test_email", "PilotApp_warehouse_test".phone AS "PilotApp_warehouse_test_phone", "PilotApp_warehouse_test".owner AS "PilotApp_warehouse_test_owner"
FROM "PilotApp_warehouse_test"
WHERE (SELECT "PilotApp_warehouse_test".id, "PilotApp_warehouse_test".name, "PilotApp_warehouse_test".volume_available, "PilotApp_warehouse_test".volume_total, "PilotApp_warehouse_test".labelling, "PilotApp_warehouse_test".manual_geo_data_entry, "PilotApp_warehouse_test".item_packaging, "PilotApp_warehouse_test".palette_packaging, "PilotApp_warehouse_test".address, "PilotApp_warehouse_test".email, "PilotApp_warehouse_test".phone, "PilotApp_warehouse_test".owner
FROM "PilotApp_warehouse_test"
WHERE "PilotApp_warehouse_test".manual_geo_data_entry IS true) OR (SELECT "PilotApp_warehouse_test".id, "PilotApp_warehouse_test".name, "PilotApp_warehouse_test".volume_available, "PilotApp_warehouse_test".volume_total, "PilotApp_warehouse_test".labelling, "PilotApp_warehouse_test".manual_geo_data_entry, "PilotApp_warehouse_test".item_packaging, "PilotApp_warehouse_test".palette_packaging, "PilotApp_warehouse_test".address, "PilotApp_warehouse_test".email, "PilotApp_warehouse_test".phone, "PilotApp_warehouse_test".owner
FROM "PilotApp_warehouse_test"
WHERE "PilotApp_warehouse_test".item_packaging IS true)]
You should not pass to filter queries, but only conditions to avoid subqueries. I think it should work for you:
#search.route('/search/filter', methods = ['POST'])
def filter():
name = request.form.get('name')
n_storage = request.form.get('n_storage')
#MIN PRICE MAX PRICE
min_p = request.form.get('min_p')
max_p = request.form.get('max_p')
#SERVICES
labelling = True if request.form.get('labelling') else False
manual_geo_data_entry = True if request.form.get('manual_geo_data_entry') else False
item_packaging = True if request.form.get('item_packaging') else False
palette_packaging = True if request.form.get('palette_packaging') else False
filters = []
if name:
filters.append(Warehouse.name.match(name))
if n_storage:
filters.append(Warehouse.volume_available > n_storage)
#FILTERING BASED ON SERVICES
if labelling:
filters.append(Warehouse.labelling.is_(True))
if manual_geo_data_entry:
filters.append(Warehouse.manual_geo_data_entry.is_(True))
if item_packaging:
filters.append(Warehouse.item_packaging.is_(True))
if palette_packaging:
filters.append(Warehouse.palette_packaging.is_(True))
results = Warehouse.query.filter(or_(*filters)).all()
return render_template('search/search.html', title = 'Search', data = results)

MapReduce on several columns

I am new to MapReduce and have troubles with writing a MapReduce job which would work with several columns at once for a CSV file.
I would like to find for each garment group the most frequent product, the second most frequent section and the most frequent department so that the output would look according to the following schema: garment_group, product, section, department. This is based on the articles.csv dataset from kaggle.
So far I could only find for each garment group the most frequent product and do not understand how to incorporate the other columns. This is my code:
from mrjob.step import MRStep
from mrjob.util import log_to_stream, log_to_null
from mr3px.csvprotocol import CsvProtocol
import csv
import logging
log = logging.getLogger(__name__)
class MyMRJob1(MRJob):
OUTPUT_PROTOCOL = CsvProtocol # write output as CSV
def set_up_logging(cls, quiet=False, verbose=False, stream=None):
log_to_stream(name='mrjob', debug=verbose, stream=stream)
log_to_stream(name='__main__', debug=verbose, stream=stream)
def mapper(self, _, line):
result = next(csv.reader([line],quotechar=None)) # extract columns from line
garment_group_name = result[23]
prod_name = result[2]
#section_name = result[21]
#department_name = result[15]
# name = result[2]
#skip sparse entries and header
if prod_name == "prod_name" or prod_name == "" or garment_group_name == "": #skip sparse entries and header
return
yield (garment_group_name,prod_name), 1
def reducer(self,garmetProd,valuelist):
garmet, prod = garmetProd
output = sum(valuelist)
yield None,(garmet,prod,output)
def mapper_top(self, _, line):
result = line # input from last round already a list of strings
garmet = result[0]
prod = result[1]
nProd = result[2]
yield garmet, (prod,nProd)
def reducer_top(self,garmet,values):
mostProduct = "" # most favourite product per garmet group
maxBought = 0 # max amount of times bought
for (prod,nProds) in values:
if int(nProds) > maxBought:
maxBought = int(nProds)
mostProduct = prod
if maxBought > 0:
#CsvProtocol needs None key for output
yield None, (garmet,mostProduct)
def steps(self):
return [
MRStep(mapper = self.mapper,
reducer = self.reducer),
MRStep(mapper = self.mapper_top,
reducer = self.reducer_top)
]
if __name__ == '__main__':
MyMRJob1.run()

How can i add to a list in python without creating it

I have the following django view for finding the average score of a questionnaire.
#login_required
def statistics(request, slug=False):
qn = get_object_or_404(Questionnaire, slug=slug)
questions = Question.objects.filter(questionnaire=qn).count()
qs = Question.objects.filter(questionnaire=qn)
responses = Response.objects.filter(question__in=qs, user=request.user).count()
if questions == 0 or responses == 0 or not questions <= responses:
return render(request, "questionnaire/stats.html")
out = {}
for q in qs:
response = Response.objects.filter(question=q, user=request.user).order_by("session_datetime").first()
out[q.category] = {}
time = response.session_datetime
time_string = time.strftime("%d/%m/%Y")
out[q.category][time_string] = []
responses_in_time = Response.objects.filter(question=q, user=request.user, session_datetime__gte=time,
session_datetime__lt=time + datetime.timedelta(hours=24))
for res in responses_in_time:
out[q.category][time_string] += [res.value]
print(out)
for category in out.keys():
print("outcat"+ str(out[category]))
for time in out[category].keys():
out[category][time] = sum(out[category][time])/len(out[category][time])
print(out)
return render(request, "questionnaire/stats.html", context={"questionnaire": qn, "stats_json": json.dumps(out)})
and i am wondering if there is a way to put together the dictionary with a time from the model/record in the loop without reseting it each time, if i try += without creating it first it complains but i do not know the initial time inside the loop.
ok so i dont know why i can only think of an answer just after ive posted but here is the working code. by looping through twice, once to create the dict and once to fill it i have solved this.
#login_required
def statistics(request, slug=False):
qn = get_object_or_404(Questionnaire, slug=slug)
questions = Question.objects.filter(questionnaire=qn).count()
qs = Question.objects.filter(questionnaire=qn)
responses = Response.objects.filter(question__in=qs, user=request.user).count()
if questions == 0 or responses == 0 or not questions <= responses:
return render(request, "questionnaire/stats.html")
out = {}
response = Response.objects.filter(question=qs.first(), user=request.user).order_by("session_datetime").first()
time = response.session_datetime
time_string = time.strftime("%d/%m/%Y")
for q in qs:
out[q.category] = {}
out[q.category][time_string] = []
for q in qs:
responses_in_time = Response.objects.filter(question=q, user=request.user, session_datetime__gte=time,
session_datetime__lt=time + datetime.timedelta(hours=24))
for res in responses_in_time:
out[q.category][time_string] += [res.value]
print(out)
for category in out.keys():
print("outcat"+ str(out[category]))
for time in out[category].keys():
out[category][time] = sum(out[category][time])/len(out[category][time])
print(out)
return render(request, "questionnaire/stats.html", context={"questionnaire": qn, "stats_json": json.dumps(out)})

I can't make changes to a Django queryset then run filters on changed data

I tried putting the queryset in a list but then the list object has no method exclude(). I need to find all the start_date's that are in the last month if they have and end_date that is after 12 then I want to change the start_date's month to 1 so that when I exclude dates before 1-1-nextyear and 1-31-nextyear I will get back the remained of the dates that lie on the month of 1.
def next_month_request(request, id, currentyear, currentmonth):
if request.is_ajax():
if int(request.GET.get('currentmonth')) == 12:
nextyear = int(request.GET.get('currentyear')) + 1
qs = ContractorSchedule.objects.filter(firstname_id=int(request.GET.get('id')))
queryset = []
for i in qs:
if i.start_date.month == 12 and i.end_date.month == 1:
h,m = i.start_date.hour, i.start_date.minute
i.start_date = last_day_of_month(i.start_date) + datetime.timedelta(seconds=1)+ datetime.timedelta(hours=h) + datetime.timedelta(minutes=m)
queryset.append(i)
queryset[0] = queryset[0].exclude(
start_date__lt=last_day_of_month( datetime.datetime(int(request.GET.get('currentyear')), int(request.GET.get('currentmonth')),1)
)).exclude( start_date__gt=datetime.datetime(nextyear,1,31,23,59,59))
if queryset.exists():
htmlcalendar = next_last_month_contractor_calendar(queryset)
else:
htmlcalendar = LocaleHTMLCalendar().formatmonth(nextyear,1)

M2m relation breaks when passing filter parameters

I have a m2m relation between properties and images in my model like imageproperty = models.ManyToManyField(Property, blank = True). Im having an issue trying to filter properties with their associated images as whenever i pass a parameter in my query i get something like this and the images are not showing quiet good
. This is my code so far
def filter_properties(request, prop, p):
order = "creation_date"
if p["sort"]: order = p["sort"]
if p["asc_desc"] == "desc": order = '-' + order
results = Property.objects.filter(status = True)
for prop in results:
prop.images = prop.image_set.all()[:1] #Should i need to return in results so it brings values when filtering?
if p["name"] : results = results.filter(name__icontains=p["name"])
if p["price_from"] : results = results.filter(price__gte=int(p["price_from"]))
if p["price_to"] : results = results.filter(price__lte=int(p["price_to"]))
if p["category"]:
lst = p["category"]
or_query = Q(categories = lst[0])
for c in lst[1:]:
or_query = or_query | Q(categories = c)
results = results.filter(or_query).distinct()
return results
def search_properties_view(request):
try:
page = int(request.GET.get("page", '1'))
except ValueError:
page = 1
p = request.POST
prop = defaultdict(dict)
parameters = dict.fromkeys(
('name', 'price_from', 'price_to', 'currency_type', 'activity_type', 'sort', 'asc_desc'),
'',
)
parameters["category"] = []
for k, v in p.items():
if k == "category":
parameters[k] = [int(x) for x in p.getlist(k)]
elif k in parameters:
parameters[k] = v
elif k.startswith("name") or k.startswith("curency_type") or k.startswith("activity_type"):
k, pk = k.split('-')
prop[pk][k] = v
elif k.startswith("category"):
pk = k.split('-')[1]
prop[pk]["category"] = p.getlist(k)
if page != 1 and "parameters" in request.session:
parameters = request.session["parameters"]
else:
request.session["parameters"] = parameters
results = filter_properties(request, prop, parameters)
paginator = Paginator(results, 20)
try:
results = paginator.page(page)
except (InvalidPage, EmptyPage):
request = paginator.page(paginator.num_pages)
return render(request, 'propiedades/propiedades.html', {
'propiedades': request.POST,
'media_url': settings.MEDIA_URL,
'results': results,
'params': parameters,
'categories': PropertyCategory.objects.all()
})

Categories