QuerySet with Avg - django

I'm having problems making a queryset for a report :/
The ChangeLog model (please see model picture below) stores every change in MedicalRequest model. I'm trying to get the time average from first record to last record in ChangeLog for a single MedicalRequest. I'm querying from customer because I'need make some reports.
I already test this:
customer = Customer.objects.get(pk=10)
customer.medicalrequest_set.aggregate(avg=Avg(Max(changelog__timestamp),
Min(changelog__timestamp)))
but I'm getting 'changelog__timestamp' is not defined :(
any idea?

Your problem is with your syntax. changelog__timestamp is treated as a variable, which you haven't defined. You have to pass the name as a string to these functions. Like, Max('changelog__timestamp').

Related

Determine how many times a Django model instance has been updated

I'm trying to find a generic way to get a count of how many times an instance of a model has had any of its fields updated. In other words, in Django, how do I get a count of how many times a specific row in a table has been updated? I'm aiming to show a count of how many updates have been made.
Let's say I have:
class MyModel(models.Model):
field = models.CharField()
another_field = models.IntegerField()
...
and I have an instance of the model:
my_model = MyModel.objects.get(id=1)
Is there a way to find out how many times my_model has had any of its fields updated? Or would I need to create a field like update_count and increment it each time a field is updated? Hopefully there is some kind of mechanism available in Django so I don't have to go that route.
Hopefully this isn't too basic of a question, I'm still learning Django and have been struggling with how to figure this out on my own.
There is no generic way to get this. As mentioned by wim you can use some "versioning package" to track whole history of changes. I've personally used the same suggestion: django-reversion, but there are other alternatives.
If you need to track only some fields then you may program some simpler mechanism yourself:
create a model/field to track your information
use something like FieldTracker to track changes to specific fields
Create handler post-save signal (or just modify model's save method) to save the data
You may also use something like "table audit". I haven't tried anything like that myself but there are some packages for that too:
https://github.com/StefanKjartansson/django-postgres-audit
https://github.com/torstenrudolf/django-audit-trigger
https://github.com/kvesteri/postgresql-audit

Django: Handling discount codes

I am currently building a Django application where visitors can buy an online course. I now want to implement the possibility to provide discount codes. As these discount codes should be limited by quantity I now have the following implementation idea:
Guest visits www.page.com?discount=TEST
The model discount contains the fields discount_codes & max qty. I will check here, if the code exists. Also, I have to count all entries in my order model that used the discount code TEST. My order model contains the foreign_key field 'redeemed_discounts').
As soon the user clicks on Pay (via Stripe) I'll once again count all the orders in my order model which contain 'TEST' to make sure, the 'max_qty' is not reached meanwhile.
Now I can charge the visitor.
Would you consider this as good implemented or do you see any problems with the way I am planning to do it?
instead of using max_qty why don't you use something like use_left and max_use
so whenever someone uses that code you can reduce the count accordingly and when count hits zero you can stop using that with this approach you don't have to scan order table every time to see if the coupon code is still available.

django database functions cumulative count?

is their a way to create cumulative count using/customizing django database functions. this built-in query gets the number of items for each year. what if we need the number of items before that year ?
items.values('year').annotate(nb=Count('id'))
This functionality is built-in in django. You can combine order_by, values and annotate to get what you want:
Item.objects.order_by('year').values('year').annotate(nb=Count('id'))
For the official docs, see: aggregation. If the sample doesn't work I'll need more information about the model to give you the correct call. Please provide the full model and, if required, some sample data.

How to fetch and display data from 2 models in a single queryset ordered by time, Django

I want to have facebook kind of news feed, in which i need to fetch data from 2 different models ordered by time.
Models are something like :
class User_image(models.Model):
user = models.ForeignKey(User_info)
profile_pic = models.ImageField(upload_to='user_images')
created = models.DateTimeField(auto_now_add=True)
class User_status(models.Model):
user = models.ForeignKey(User_info)
status = models.CharField(max_length=1)
created = models.DateTimeField(auto_now_add=True)
As per my requirement, i can not make a single model out of these two models.
Now i need to know the simple code in views and template so as to display profile pic and status in the news feed according to time.
Thanks.
The most simple way of archiving this is to have a base model, call it Base_event,
class Base_event(models.Model):
user = models.ForeignKey(User_info)
created = models.DateTimeField(auto_now_add=True)
and derive both your models from this Base. This way you write less code, and you archive your objective. Notice that you have to make an implementation choice: how will they will inherit from base. I advice to read Django documentation to help you choose wisely according to what you want to do.
EDIT:
I would notice that the accepted answer has a caveat. It sorts the data on the python and not on the mysql, which means it will have an impact on the performance: the whole idea of mysql having SORT is to avoid having to hit the database and them perform the sorting. For instance, if you want to retrieve just the first 10 elements sorted, with the accepted solution you have to extract all the entries, and only then decide which ones are the first 10.
Something like Base_event.objects.filter().sort_by(...)[10] would only extract 10 elements of the database, instead of the whole filtered table.
The easy solution now becomes the problem later.
Try something like creating list chain.
feed = list(chain(User_image,User_status))
feed = sorted(feed, key=operator.attrgetter('date_added'))
for those who refer it as not correct.
https://stackoverflow.com/a/434755/2301434

Django: Query with F() into an object not behaving as expected

I am trying to navigate into the Price model to compare prices, but met with an unexpected result.
My model:
class ProfitableBooks(models.Model):
price = models.ForeignKey('Price',primary_key=True)
In my view:
foo = ProfitableBooks.objects.filter(price__buy__gte=F('price__sell'))
Producing this error:
'ProfitableBooks' object has no attribute 'sell'
Is this your actual model or a simplification? I think the problem may lie in having a model whose only field is its primary key is a foreign key. If I try to parse that out, it seems to imply that it's essentially a field acting as a proxy for a queryset-- you could never have more profitable books than prices because of the nature of primary keys. It also would seem to mean that your elided books field must have no overlap in prices due to the implied uniqueness constraints.
If I understand correctly, you're trying to compare two values in another model: price.buy vs. price.sell, and you want to know if this unpictured Book model is profitable or not. While I'm not sure exactly how the F() object breaks down here, my intuition is that F() is intended to facilitate a kind of efficient querying and updating where you're comparing or adjusting a model value based on another value in the database. It may not be equipped to deal with a 'shell' model like this which has no fields except a joint primary/foreign key and a comparison of two values both external to the model from which the query is conducted (and also distinct from the Book model which has the identifying info about books, I presume).
The documentation says you can use a join in an F() object as long as you are filtering and not updating, and I assume your price model has a buy and sell field, so it seems to qualify. So I'm not 100% sure where this breaks down behind the scenes. But from a practical perspective, if you want to accomplish exactly the result implied here, you could just do a simple query on your price model, b/c again, there's no distinct data in the ProfitableBooks model (it only returns prices), and you're also implying that each price.buy and price.sell have exactly one corresponding book. So Price.objects.filter(buy__gte=F('sell')) gives the result you've requested in your snipped.
If you want to get results which are book objects, you should do a query like the one you've got here, but start from your Book model instead. You could put that query in a queryset manager called "profitable_books" or something, if you wanted to substantiate it in some way.