Get Count of order on every day of week - django

Hi I have a model like :
class Order(models.Model):
user=models.ForeginKey(User)
startDatatime = models.DateTimeField(blank=True, null=True)
I want count orders on Each week day . like On all Mondays count of orders and on all week days etc
EDIT
Is that a good way to do that ?
data = []
weekdays = {'Sunday': 1, 'Monday': 2, 'Tuesday': 3, 'Wednesday': 4, ' Thursday': 5,
'Friday': 6, 'Saturday': 7}
for day, value in weekdays.items():
weekly_tasks_count = Task.objects.filter(
todo_list__for_user=request.user,
creation_date_time__week_day=value).count()
data.append({day: weekly_tasks_count})

You can use list comprehensions to tidy up your code a little bit more.
WEEKDAYS = {
'Sunday': 1,
'Monday': 2,
'Tuesday': 3,
'Wednesday': 4,
'Thursday': 5,
'Friday': 6,
'Saturday': 7
}
data = [
{
day: Task.objects.filter(
todo_list__for_user=request.user,
creation_date_time__week_day=value).count()
)}
for day, value in WEEKDAYS.items()
]
One more possible improvement is to build up the WEEKDAYS dictionary from values found in the datetime module, but so far having it defined your way doesn't harm readability.

Related

Put information from a dabtabse file into lists

import sqlite3
db = sqlite3.connect('newdb.db')
team_list = ['Munster', 'Leinster', 'Ulster', 'Glasgow']
cursor = db.cursor()
for i in range(len(team_list)):
team_names = team_list[i].upper()
searchStr = '%' + team_names + '%'
cursor.execute('select * from tickets where Name LIKE ?', (searchStr,))
teams_points = cursor.fetchall()
print teams_points
cursor.close()
db.close()
This is my python code used to display all data in the table 'tickets' in newdb.db. I have a list with the team names and i want to be able to search these team names in the database and calculate information on tickets sold.
picture of database
[(u'MUNSTER', 5, u'First Round'), (u'MUNSTER', 5, u'First Round'),
(u'MUNSTER', 8, u'Second Round'), (u'MUNSTER', 10, u'Both Rounds')]
[(u'LEINSTER', 2, u'Second Round'), (u'LEINSTER', 16, u'First Round'),
(u'LEINSTER', 5, u'Both Rounds'), (u'LEINSTER', 6, u'Both Rounds'),
(u'LEINSTER', 3, u'First Round')]
[(u'ULSTER', 10, u'Second Round')]
[(u'GLASGOW', 4, u'First Round')]
Above is my output when I run the script, i want to be able put each team into a list as
team_list=['team_name', 'total first round tickets', 'second round tickets']
munster_list = ['MUNSTER', '20', '18']
leinster_list = ['LEINSTER','30','13']
ulster_list = ['ULSTER','0','10']
glasgow_list = ['GLASGOW','4','0']
so then to print the list I can just use print munster_list
Use GROUP BY to get one output row from the rows in each group. Use CASE expressions to sum up only certain values:
SELECT Name,
sum(CASE WHEN Type IN ('First Round', 'Both Rounds')
THEN Amount
ELSE 0
END) AS "first round tickets",
sum(CASE WHEN Type IN ('Second Round', 'Both Rounds')
THEN Amount
ELSE 0
END) AS "second round tickets"
FROM tickets
GROUP BY Name
ORDER BY Name;

Can't query the sum of values using aggregators

I want to sum the values of all existing rows grouping by another field.
Here's my model structure:
class Answer(models.Model):
person = models.ForeignKey(Person)
points = models.PositiveIntegerField(default=100)
correct = models.BooleanField(default=False)
class Person(models.Model):
# irrelevant model fields
Sample dataset:
Person | Points
------ | ------
4 | 90
3 | 50
3 | 100
2 | 100
2 | 90
Here's my query:
Answer.objects.values('person').filter(correct=True).annotate(points_person=Sum('points'))
And the result (you can see that all the person values are separated):
[{'person': 4, 'points_person': 90}, {'person': 3, 'points_person': 50}, {'person': 3, 'points_person': 100}, {'person': 2, 'points_person': 100}, {'person': 2, 'points_person': 90}]
But what I want (sum of points by each person):
[{'person': 4, 'points_person': 90}, {'person': 3, 'points_person': 150}, {'person': 2, 'points_person': 190}]
Is there any way to achieve this using only queryset filtering?
Thanks!
Turns out I had to do the inverse filtering, by the Person's and not the Answers, like so:
Person.objects.filter(answer__correct=True).annotate(points=Sum('answer__points'))
Now I get the total summed points for each person correctly.

Break django values down into count of each value

I have a model defined similar to below
class MyModel(models.Model):
num_attempts = models.IntegerField()
num_generated = models.IntegerField()
num_deleted = models.IntegerField()
Assuming my data looked something like this:
|id|num_attempts|num_generated|num_deleted
1 1 2 0
2 2 0 1
3 3 2 1
4 3 1 2
I want to get a count of the instances at each possible value for each possible field.
For example, a return sample could look like this.
{
'num_attempts_at_1': 1,
'num_attempts_at_2': 1,
'num_attempts_at_3': 2,
'num_generated_at_0': 1,
'num_generated_at_1': 1,
'num_generated_at_2': 2,
'num_deleted_at_0': 1,
'num_deleted_at_1': 2,
'num_deleted_at_2': 1
}
This above example assumes a lot, like naming of the variables after and that it would be serialized. None of that matters but rather just how do I get it broken down like that from the database. It would be best to have this done in one query if possible.
We are using Postgres as the database.
Here is sorta close, but not quite.
qs.values_list('num_attempts','num_generated','num_deleted').annotate(Count('id'))
Gives this (not the same data as the example above)
[{'num_attempts': 4, 'id__count': 3, 'num_deleted': 3, 'num_generated': 6}, {'num_attempts': 3, 'id__count': 12, 'num_deleted': 2, 'num_generated': 2}, {'num_attempts': 2, 'id__count': 5, 'num_deleted': 0, 'num_generated': 6}]
Now with some custom python I was able to do this, but really want a database solution if possible.
def get(self, request, *args, **kwargs):
qs = self.get_queryset()
return_data = {}
for obj in qs:
count = obj.pop('id__count')
for k, v in obj.items():
key = "{}_at_{}".format(k, v)
value = return_data.get(key, 0) + count
return_data[key] = value
return Response(return_data)

Complex Django Query to Create Dictionary

models.py
class Event(models.Model):
name = models.CharField(max_length=100)
date = models.DateField()
class Result(models.Model):
event = models.ForeignKey(Event)
place = models.IntegerField()
person = models.CharField(max_length=100)
gender = models.CharField(max_length=1)
score = models.IntegerField()
Event sample data:
id, name, date
1, 'event1', '2015-01-01'
2, 'event2', '2015-02-01'
3, 'event3', '2015-03-01'
Result sample data:
event_id, place, person, gender, score
1, 1, 'al', 'M', 25
1, 2, 'bob', 'M', 22
1, 3, 'cindy', 'F', 21
1, 4, 'doug', 'M', 20
2, 1, 'elen', 'F', 30
2, 2, 'frank', 'M', 28
2, 3, 'gord', 'M', 20
2, 4, 'helen', 'F', 19
I want to query this and get a dictionary containing the male and female winners (with scores) for each event:
winnersdict = {event_id: (mwinner, mscore, fwinner, fscore), ...}
In this case the resulting dictionary would be:
{1: ('al', 25, 'cindy', 21), 2: ('frank', 28, 'elen', 30). 3: (None, None, None, None)}
Right now I am doing it like this:
events = Event.objects.all().order_by('date')
winnersdict = {}
for e in events:
femalewinner = Result.objects.filter(event_id=e.id, gender='F')[:1]
if len(femalewinner) == 0:
fwinner = None
fscore = None
else:
fwinner = femalewinner[0].person
fscore = femalewinner[0].score
malewinner = Result.objects.filter(event_id=e.id, gender='M')[:1]
if len(malewinner) == 0:
mwinner = None
mscore = None
else:
mwinner = malewinner[0].person
mscore = malewinner[0].score
winnersdict[e.id] = (mwinner, mscore, fwinner, fscore)
Surely there is a smarter way. I'm going to have thousands of events, looping through this way seems terrible. If it simplified things I would also be fine with generating a separate femalewinnersdict and malewinnersdict. I'm also fine (might even prefer) if we leave the None's out of the resulting dictionary, for this case I'm not interested in events that don't have results yet.
Any ideas?
Please try following query, it would give you male/female separately.
from django.db.models import Max
male_results = Event.objects.filter(result__gender='M') \
.annotate(max_score=Max('result__score')) \
.values('name', 'result__person', 'result__score')

Pandas: What is the best way to 'crop' as large dataframe to only the previous 1000 days?

I have a dataframe where the index is made up of datetimes. I also have an anchor date and I know that I only want the second dataframe to contain the 1000 days previous to the anchor date. What is the best way to do this?
Don't know if it's the best way, but it should work
Create example DataFrame:
>>> dates = [pd.datetime(2012, 5, 4), pd.datetime(2012, 5, 5), pd.datetime(2012, 5, 6), pd.datetime(2012, 5, 1), pd.datetime(2012, 5, 2), pd.datetime(2012, 5, 3)]
>>> values = [1, 2, 3, 4, 5, 6]
>>> df = pd.DataFrame(values, dates)
>>> df
>>> df
0
2012-05-04 1
2012-05-05 2
2012-05-06 3
2012-05-01 4
2012-05-02 5
2012-05-03 6
Suppose we want 2 days back from 2012-05-04:
>>> date_end = pd.datetime(2012, 5, 4)
>>> date_start = date_end - pd.DateOffset(days=2)
>>> date_start, date_end
(datetime.datetime(2012, 5, 2, 0, 0), datetime.datetime(2012, 5, 4, 0, 0))
Now let's try to get rows by label indexing:
>>> df.loc[date_start:date_end]
Empty DataFrame
Columns: [0]
Index: []
That's because our index is not sorted, so let's fix it:
>>> df.sort_index(inplace=True)
>>> df.loc[date_start:date_end]
0
2012-05-02 5
2012-05-03 6
2012-05-04 1
It's also possible to get rows by datetime indexing:
>>> df[date_start:date_end]
0
2012-05-02 5
2012-05-03 6
2012-05-04 1
Keep in mind that I'm still not an expert in Pandas, but I like it for Data Analysis very much.
Hope it helps.