if request.method == 'POST':
product=request.POST.get('product')
upload_month = request.POST.get('upload_month')
un_month= Planning_quantity_data.objects.values('month').filter(product=product,upload_month=upload_month).distinct()
print(un_month)
<QuerySet [{'month': 'Mar_22'}, {'month': 'Apr_22'}, {'month': 'May_22'}, {'month': 'Jun_22'}]>
I want to get only the values without key and store it in a new list in
views.py file:
like newlist = ['Mar_22' , 'Apr_22', 'May_22','Jun_22']
while I am using
un_month1=list(un_month.values())
print(un_month1)
It is showing like something this:
[{'id': 1, 'upload_month': 'Mar_22', 'product': 'MAE675', 'material_code': 'MAE675 (MEMU â OB) RCF', 'order_type': 'Onhand', 'BOM_CODE': '675MEMU', 'month': 'Mar_22', 'quantity': 3, 'po_value': '37/5', 'remarks': 'Qty in Rakes. 3-5 rakes partial qty dispatched', 'empid': None}, {'id': 2, 'upload_month': 'Mar_22', 'product': 'MAE675', 'material_code': 'MAE675 (MEMU â OB) RCF', 'order_type': 'Onhand', 'BOM_CODE': '675MEMU', 'month': 'Apr_22', 'quantity': 3, 'po_value': '37/5', 'remarks': 'Qty in Rakes. 3-5 rakes partial qty dispatched', 'empid': None}, {'id': 3, 'upload_month': 'Mar_22', 'product': 'MAE675', 'material_code': 'MAE675 (MEMU â OB) RCF', 'order_type': 'Onhand', 'BOM_CODE': '675MEMU', 'month': 'May_22', 'quantity': 3, 'po_value': '37/5', 'remarks': 'Qty in Rakes. 3-5 rakes partial qty dispatched', 'empid': None}]
If you use values_list() [django-docs] with a single field, you can use flat=True to return a QuerySet of single values, I mean:
if request.method == 'POST':
product=request.POST.get('product')
upload_month = request.POST.get('upload_month')
newlist = list(Planning_quantity_data.objects.filter(product=product,upload_month=upload_month).values_list('month', flat=True))
print(newlist)
And this will print just ['Mar_22', 'Apr_22', 'May_22', 'Jun_22'] for you.
Related
I am trying to query and the group is the Order of the last 6 months.
and this is my models:
class Order(models.Model):
created_on = models.DateTimeField(_("Created On"), auto_now_add=True)
and this is my method to parse month:
from django.db.models import Func
class Month(Func):
"""
Method to extract month
"""
function = 'EXTRACT'
template = '%(function)s(MONTH from %(expressions)s)'
output_field = models.IntegerField()
And this is my query:
current_date = date.today()
months_ago = 6
six_month_previous_date = current_date - timedelta(days=(months_ago * 365 / 12))
order = Order.objects.filter(
created_on__gte=six_month_previous_date,
).annotate(
month=Month('created_on')
).values(
'month'
).annotate(
count=Count('id')
).values(
'month',
'count'
).order_by(
'month'
)
In my database order table, there is only on entry:
So it is returning
[{'month': 10, 'count': 1}]
But i dont want like this, i want like these of last 6 month, if in one month, there is no sales, it should return the count: 0
Like thise bellow:
[
{'month': 10, 'count': 1},
{'month': 9, 'count': 0}
{'month': 8, 'count': 0}
{'month': 7, 'count': 0}
{'month': 6, 'count': 0}
{'month': 5, 'count': 0}
]
A database works under the closed world assumption, so it will not insert rows with 0. You can however post-process the list.
from django.utils.timezone import now
order = Order.objects.filter(
created_on__gte=six_month_previous_date,
).values(
month=Month('created_on')
).annotate(
count=Count('id')
).order_by('month')
order = {r['month']: r['count'] for r in order}
month = now().month
result = [
{'month': (m % 12)+1, 'count': order.get((m % 12) + 1, 0)}
for m in range(month-1, month-8, -1)
]
Note that Django already has an ExtractMonth function [Django-doc].
I'm having trouble performing a simple transformation with the django orm.
Desired outcome should look like this:
2018-08
2018-07
2018-06
...
And is created with this sql:
select
distinct
strftime('%Y',a."Buchung") || "-" ||
strftime('%m',a."Buchung") as YearMonth
from
hhdata_transaktion a
order by
1 desc
I need it for a ModelChoiceField as queryset, so I'm bound to the ORM here?
My try
from django.db.models.functions import TruncMonth, TruncYear
Transaktion.objects
.annotate(year=TruncYear('Buchung'),
month=TruncMonth('Buchung'))
.distinct()
.order_by('-year', '-month')
.values('year','month')
returns:
<QuerySet [{'year': datetime.date(2018, 1, 1), 'month': datetime.date(2018, 8, 1)}, {'year': datetime.date(2018, 1, 1), 'month': datetime.date(2018, 7, 1)}, {'year': datetime.date(2018, 1, 1), 'month': datetime.date(2018, 6, 1)}, {'year': datetime.date(2018, 1, 1), 'month': datetime.date(2018, 5, 1)}, {'year': datetime.date(2018, 1, 1), 'month': datetime.date(2018, 4, 1)}, {'year': datetime.date(2018, 1, 1), 'month': datetime.date(2018, 3, 1)}, {'year': datetime.date(2018, 1, 1), 'month': datetime.date(2018, 2, 1)}, {'year': datetime.date(2018, 1, 1), 'month': datetime.date(2018, 1, 1)}, {'year': datetime.date(2017, 1, 1), 'month': datetime.date(2017, 12, 1)}, {'year': datetime.date(2017, 1, 1), 'month': datetime.date(2017, 11, 1)}, {'year': datetime.date(2017, 1, 1), 'month': datetime.date(2017, 10, 1)}, {'year': datetime.date(2017, 1, 1), 'month': datetime.date(2017, 9, 1)}, {'year': datetime.date(2017, 1, 1), 'month': datetime.date(2017, 8, 1)}]>
I have the feeling I'm miles away from the desired result..
If you want to obtain the year or month, you can use ExtractYear [Django-doc] and ExtractMonth [Django-doc] respectively. Truncating will give you the start of the year or month.
So we can rewrite the query to:
from django.db.models.functions import ExtractMonth, ExtractYear
qs = Transaktion.objects.annotate(
year=ExtractYear('Buchung'),
month=ExtractMonth('Buchung')
).order_by('-year', '-month').values('year','month').distinct()
Although it is possible to do the processing at SQL level, I think it will make work more complex. For example if you concatenate the numbers in SQL, it will probably require some work to get leading zeros for months (less than 10). Furthermore it is likely that the query contains "SQL dialect"-specific features making it less portable.
Therefore I suggest to do the post processing at the Django/Python level. For exampe with:
from django.db.models.functions import ExtractMonth, ExtractYear
class MyForm(forms.Form):
my_choice_field = forms.ChoiceField()
# ...
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
qs = Transaktion.objects.annotate(
year=ExtractYear('Buchung'),
month=ExtractMonth('Buchung')
).order_by('-year', '-month').values('year','month').distinct()
self.fields['my_choice_field'].choices = [
(row['year']*100+row['month'], '{}-{:02d}'.format(row['year'], row['month'])
for row in qs
]
Here we thus generate a list of 2-tuples where the first element is some sort of number we use to identify the choice (I here multiplied the year by 100, such that 201804 is april 2018). The second element of the tuple is the string that determines the format.
If you want a list of strings like 2018-06, something like that should work:
[ '%i-%02i' % (x.Buchung.year, x.Buchung.month) for x in Transaktion.objects.order_by(-Buchung) ]
I have two tables:
Ticket Table
id paid_with_tax location
1 5 A
2 6 B
3 7 B
TicketAdjustment Table
id ticket_id value_with_tax
1 1 2
2 1 1
3 1 2
4 1 3
5 2 5
The query I use:
Ticket.objects.all().annotate(
paid_amount=Sum(
F('paid_with_tax') +
Coalesce(F('ticketadjustment__value_with_tax'), 0)
)
).values(
'paid_amount', 'location'
).annotate(
Count('id)
)
the query would return the following:
[
{
id__count: 6,
paid_amount__sum: 28,
location: A
},
{
id__count: 2,
paid_amount__sum: 18,
location: B
},
]
but the above is incorrect since the Ticket Table id=1 values are duplicated by the TicketAdjustment Table values.
how can i get the query to sum the TicketAdjustment Table values before adding them up.
Some constraints:
- the order of the calls would ideally stay the same, as I have a function which returns the queryset to be filtered thurther
The final result should look as followins:
[
{
id__count: 1,
paid_amount__sum: 13,
location: A
},
{
id__count: 2,
paid_amount__sum: 18,
location: B
},
]
models.py:
class Ticket(models.Model):
paid_with_tax = models.DecimalField(max_digits=6, decimal_places=4)
location = models.ForeignKey(Location)
class TicketAdjustment(models.Model):
value_with_tax = models.DecimalField(max_digits=6, decimal_places=4)
ticket = models.ForeignKey(Ticket)
As I understand this aggregation can not be done even using raw sql query. Because the result of joining Ticket with TicketAdjustment will be like:
So, we can't just sum all value_with_tax related to some ticket with paid_with_tax and group that by location.
I couldn't find solution to perform this in one sql query. But I have found how to perform this in two queries:
tickets = Ticket.objects.values(
'location',
).annotate(
count=Count('id', distinct=True),
paid_amount=Sum('paid_with_tax')
)
# <QuerySet [
# {'paid_amount': 5, 'count': 1, 'location': 'A'},
# {'paid_amount': 13, 'count': 2, 'location': 'B'}
# ]>
adjustments = TicketAdjustment.objects.annotate(
location=F('ticket__location'))
.values(
'location',
).annotate(
paid_amount=Sum('value_with_tax')
)
# <QuerySet [
# {'paid_amount': 5, 'location': 'B'},
# {'paid_amount': 8, 'location': 'A'}
# ]>
def find_paid_amount_for_list_and_location(l, location):
for item in l:
if item['location'] == location:
return item['paid_amount'] or 0
for obj in tickets:
paid = find_paid_amount_for_list_and_location(adjustments, obj['location'])
obj['paid_amount'] += paid
tickets
# [
# {'location': 'A', 'paid_amount': 13, 'count': 1},
# {'location': 'B', 'paid_amount': 18, 'count': 2}
# ]
But this is not super efficient solution, and I think that you should create new table for locations and just have FK to that table? In this case you will able to perform these calculations in one query on db side.
SELECT `av`.`answer_id`, SUM(IF(`av`.`helpful`=1, 1, -1)) as `score`
FROM `questions_answervote` AS `av`
JOIN `questions_answer` AS `a`
ON `a`.`id`=`av`.`answer_id` AND `a`.`question_id`='775819'
GROUP BY `av`.`answer_id`
HAVING SUM(IF(`av`.`helpful`=1, 1, -1)) > 0
I have three models: Question, Answer and AnswerVote. Every Question has a set of Answers and every Answer has a set of AnswerVotes. AnswerVote has a field helpful which is a boolean.
What I am trying to do is get all the helpful Answers for a Question by calculating a score for each of the Answers (+1 for helpful=True, -1 for helpful=False). An Answer is helpful if it has a score > 0.
Any help would be appreciated!
If you have the following:
from django.db import models
class Question(models.Model):
data = models.CharField(max_length=30)
class Answer(models.Model):
question = models.ForeignKey(Question)
def __str__(self):
return str(self.__dict__)
class AnswerVotes(models.Model):
answer = models.ForeignKey(Answer)
helpful = models.SmallIntegerField(default=0)
def __str__(self):
return str(self.__dict__)
It may seem a bit like a work around but why simply not do an average of all votes helpfullness. Instead of -1 to 1 range, you will be somewhere between 0 and 1 with raw values in the DB. Simply treat 0.5 as the middle ground in your case and you should get the same behavior.
Answer.objects.annotate(score = Avg('answervotes__helpful'))
{'score': None, 'id': 1, 'question_id': 1}
{'score': 1.0, 'id': 2, 'question_id': 1}
{'score': 0.5, 'id': 3, 'question_id': 1}
{'score': 0.3333333333333333, 'id': 4, 'question_id': 2}
{'score': 0.5, 'id': 5, 'question_id': 3}
{'score': 0.4, 'id': 6, 'question_id': 3}
Answer.objects.annotate(score = Avg('answervotes__helpful')).filter(score__gte=0.5)
{'score': 1.0, 'id': 2, 'question_id': 1}
{'score': 0.5, 'id': 3, 'question_id': 1}
{'score': 0.5, 'id': 5, 'question_id': 3}
Django's ORM doesn't do HAVING, so you will have to drop to raw SQL for this one.
model:
class Product(models.Model):
name = models.CharField(max_length = 128)
(...)
def __unicode__(self):
return self.name
class Receipt(models.Model):
name = models.CharField(max_length=128)
(...)
components = models.ManyToManyField(Product, through='ReceiptComponent')
def __unicode__(self):
return self.name
class ReceiptComponent(models.Model):
product = models.ForeignKey(Product)
receipt = models.ForeignKey(Receipt)
quantity = models.FloatField(max_length=9)
unit = models.ForeignKey(Unit)
def __unicode__(self):
return unicode(self.quantity!=0 and self.quantity or '') + ' ' + unicode(self.unit) + ' ' + self.product.genitive
And now I'd like to get list of the most often useable products:
ReceiptComponent.objects.values('product').annotate(Count('product')).order_by('-product__count'
the example result:
[{'product': 3, 'product__count': 5}, {'product': 6, 'product__count': 4}, {'product': 5, 'product__count': 3}, {'product': 7, 'product__count': 2}, {'product': 1, 'product__count': 2}, {'product': 11, 'product__count': 1}, {'product': 8, 'product__count': 1}, {'product': 4, 'product__count': 1}, {'product': 9, 'product__count': 1}]
It's almost what I need. But I'd prefer having Product object not product value, because I'd like to use this in views.py for generating list.
If I'm not mistaken this has the same behaviour but with objects?
Product.objects.all().annotate(usecount=Count('receipt_set')).order_by('-usecount')