A very simple question say i have the following models:
class Tweet(models.Model):
entry = Models.CharField()
time_of_entry = Models.DateTimeField()
in my view i do the following:
def get_tweets(request):
tw = Tweet.objects.all().order_by(-time_of_entry)
this will return me the tweets ordered in descending order by time.
when i filter it this way, say there are 150 tweets arranged in variable tw.
Is there any way i can get tweets in range 20 to 30 of the above queryset?
I want to show 10 tweets at a time, from the above list, and then in my template i want to have a simple button, which reads load_10_next_tweets and does the same. I do not want to use pagination.
How can this be done?
Two ways. The first is to get an iterator and then islice it multiple times. The second is to slice the query set itself, e.g. tw[20:30].
Related
I'm using Django with Postgres.
On a page I can show a list of featured items, let's say 10.
If in the database I have more featured items than 10, I want to get them random/(better rotate).
If the number of featured item is lower than 10, get all featured item and add to the list until 10 non-featured items.
Because the random takes more time on database, I do the sampling in python:
count = Item.objects.filter(is_featured=True).count()
if count >= 10:
item = random.sample(list(Item.objects.filter(is_featured=True))[:10])
else:
item = list(Item.objects.all()[:10])
The code above miss the case where there less than 10 featured(for example 8, to add 2 non-featured).
I can try to add a new query, but I don't know if this is an efficient retrive, using 4-5 queries for this.
The best solution I could find is this:
from itertools import chain
items = list(chain(Item.objects.filter(is_featured=True).order_by('?'), Item.objects.filter(is_featured=False).order_by('?')))[:10]
In this way, the order of the querysets are retained, but downside is that items becomes a list not a Queryset. You can see more details in this SO Answer. FYI: there are some fantastic solutions like using Q or pipe but they don't retain order of queryset.
SQL method: You can achieve that with an SQL statement like this:
SELECT uuid_generate_v4(), *
FROM table_name
ORDER BY NOT is_featured, uuid_generate_v4()
LIMIT 10;
Explain: The generated UUID should simulate randomness (for the purpose of e-commerce, this should suffice). While sorting the rows by NOT is_featured will put the is_featured rows on top; and automatically flow the rows down to 10 limits if it run out of featured items.
I am writing a web based music application and I want implement some feature that user can see most favor album in last week-month-year.
so this is my model :
class album(models.Model):
def get_weely_count():
...
def get_monthly_count():
...
def get_yearly_count():
...
class like(models.Model):
created_at = models.DateField()
albumID = models.ForeignKey(Album)
Now I want to receive albums that most liked in last week or last month or last year,I want done some thing like this(but I can not):
Album.objects.all().order_by('get_weekly_count')
can any one help me to fix it or give another approach to achieve that goal??
The order_by method translates into an SQL ORDER BY, therefore it works only with model fields, which correspond to table columns. It won't work if you intend to sort your elements by a model's method.
So, if you want to accomplish something like
Album.objects.all().order_by('get_weekly_count')
You'll have to do it the python way
sorted(Album.objects.all(), key=lambda x: x.get_weekly_count())
Performance-wise, this means you'll get your elements with a query and then you'll sort them with python (that's different from getting a sorted queryset in one shot).
Otherwise, if it's possible for you to turn get_weekly_count into raw SQL, you could use it with a Count() or an extra modifier, that would make order_by usable, i.e.:
Album.objects.all().extra(
select={'weekly_count': "<some SQL>"},
select_params=(<you params>,),
).order_by('weekly_count')
Have a look at https://docs.djangoproject.com/en/1.8/ref/models/querysets/#extra
According to the documentation, you should use:
from django.db.models import Count
like.objects.filter(created_at__gt=START_OF_MONTH, created_at__lt=Datetime.now()).values('albumID').annotate(count=Count('albumID')).order_by('count')
This will get results for you in single db query. For more details visit https://docs.djangoproject.com/en/dev/topics/db/aggregation/.
I want to update budget of Category model in Django.
class Category(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=128)
budget = models.DecimalField(default=0.0, decimal_places=2, max_digits=12, help_text="Amount in dollars ($)")
I would have a list of new budget like this which is equal to number of data in Category:
>>> new_category_budget
[Decimal('2700.000'), Decimal('750.000'), Decimal('1500.000')]
I am updating like this:
>>> for budget in new_category_budget:
... Category.objects.filter(user=2).update(budget=budget)
...
3L
3L
3L
But all of these return the same data. What's wrong with my update statement?
What you're doing is iterating over your budget values, and updating all records with user=2 to each one, overriding the previous value.
The return value of QuerySet.update is the number of updated records. Each time you call update(), you get the result that 3 records were updated.
I don't quite understand what you are actually trying to do, but it might be something like this (untested!):
for (budget, category) in zip(new_category_budget, list(Category.objects.filter(user=2)):
category.budget=budget
category.save()
Of course, this assumes that the number of filtered categories will exactly match the number of budgets in new_category_budget, and also the order of iteration over categories is not obvious. All in all, this seems weird :)
When you call update on a QuerySet, it will set all items in the QuerySet to that value. See the example here.
So through your for loop, you are updating all the Category objects with user=2 to each budget. At the end of the for loop, all the Category objects should be have budget == new_category_budget[-1] or the last budget item.
If you want different values for each Category object, you'll need to call save on them individually.
For example if I have models.py like this:
Handler(models.Model):
model1 = ForeignKey(Model1)
model2 = ForeigKey(Model2)
user = models.ForeignKey(User)
For example there are 100 instances of Handler with Model1 id = 1, but Model 2 id for this 100 instances is in range 1 to 5. And when I do something like this:
Handles.objects.filter(model1=1).values_list('model2_id', flat=True)
It returns list of 5 id values or list of 100 id values, which are be repeated?
And if it return 100 values is there possibility to remain only one value for every repeated value?
It will return a list of 100 id values.
If you want to get the unique 5 ones, then you can do that in python.
model2_id_uniq_values = list(set(Handles.objects.filter(model1=1).values_list('model2_id', flat=True)))
It may not be the most finely tuned algorithm, and by using a set, you would lose the order. But for your purposes it appears to work.
I have Django models that are lists of items and I want the items on each list to have a separate sort order. Maybe list 1 will sort line items by name, list 2 by date, and list 3 by priority.
The models looks more or less like this:
class ListItem(models.Model):
priority = models.IntegerField(choices=PRIORITY_CHOICES)
name = models.CharField(max_length=240)
due_date = models.DateTimeField(null=True, blank=True)
list = models.ForeignKey(List)
Right now I'm using this query in my view:
lists = List.objects.filter(user=request.user)
return render_to_response('showlists.html', {'lists': lists })
I've read examples that imply that I could do something like this:
lists = List.objects.filter(user=request.user).select_related().order_by("items.name")
Assuming that worked, it would give me the collection of lists with an identical sort order for each batch of items. How would I go about sorting each individual list's related items differently?
The syntax for ordering across related models is the same double-underscore format as for filter, so you can do:
List.objects.filter(user=request.user).select_related().order_by("listitems__name")
You should just able to use the different fields in the same way in the order_by call.
If the lists are small, then you could do it in python, using sort and tagging
list = <...code to get sublist here ...>
list.sort(key=lambda x: x.due_date) #sort by due date, say
Otherwise kick off a query for each sub-list