ken*_*der 169 python django django-models
我有一个模特代表我在网站上出现的画作.在主要网页上,我想展示一些:最新的,大多数时间没有访问过的,最受欢迎的一个和随机的一个.
我正在使用Django 1.0.2.
虽然前三个使用django模型很容易拉,但最后一个(随机)给我带来了一些麻烦.我可以在我的视图中对它进行编码,如下所示:
number_of_records = models.Painting.objects.count()
random_index = int(random.random()*number_of_records)+1
random_paint = models.Painting.get(pk = random_index)
Run Code Online (Sandbox Code Playgroud)
在我看来,它看起来并不像我想要的东西 - 这完全是数据库抽象的一部分,应该在模型中.此外,在这里我需要处理删除的记录(然后所有记录的数量不会覆盖我所有可能的键值),可能还有很多其他的东西.
我可以做任何其他选择,最好以某种方式在模型抽象中?
muh*_*huk 245
只需使用:
MyModel.objects.order_by('?').first()
Run Code Online (Sandbox Code Playgroud)
Emi*_*nov 158
使用order_by('?')将在生产的第二天终止数据库服务器.更好的方法类似于从关系数据库获取随机行中描述的内容.
from django.db.models.aggregates import Count
from random import randint
class PaintingManager(models.Manager):
def random(self):
count = self.aggregate(count=Count('id'))['count']
random_index = randint(0, count - 1)
return self.all()[random_index]
Run Code Online (Sandbox Code Playgroud)
Mik*_*bov 26
如果使用MySQL(不了解其他数据库),即使对于中型表,order_by('?')[:N]的解决方案也非常慢.
order_by('?')[:N]将被翻译为SELECT ... FROM ... WHERE ... ORDER BY RAND() LIMIT N查询.
这意味着对于表中的每一行,将执行RAND()函数,然后将根据此函数的值对整个表进行排序,然后返回前N个记录.如果你的桌子很小,这很好.但在大多数情况下,这是一个非常慢的查询.
我写了一个简单的函数,即使id有漏洞(某些行被删除)也能正常工作:
def get_random_item(model, max_id=None):
if max_id is None:
max_id = model.objects.aggregate(Max('id')).values()[0]
min_id = math.ceil(max_id*random.random())
return model.objects.filter(id__gte=min_id)[0]
Run Code Online (Sandbox Code Playgroud)
几乎在所有情况下,它都比order_by('?')快.
小智 13
这是一个简单的解决方案:
from random import randint
count = Model.objects.count()
random_object = Model.objects.all()[randint(0, count - 1)] #single random object
Run Code Online (Sandbox Code Playgroud)
Sov*_*iut 10
您可以在模型上创建一个管理器来执行此类操作.首先要明白一个经理是什么,Painting.objects方法是包含一个管理者all(),filter(),get(),等创建自己的管理器允许您预先筛选结果,并拥有所有这些相同的方法,以及您自己的自定义方法,工作的结果.
编辑:我修改了我的代码以反映该order_by['?']方法.请注意,经理返回无限数量的随机模型.因此,我已经包含了一些使用代码来展示如何只获得一个模型.
from django.db import models
class RandomManager(models.Manager):
def get_query_set(self):
return super(RandomManager, self).get_query_set().order_by('?')
class Painting(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=50)
objects = models.Manager() # The default manager.
randoms = RandomManager() # The random-specific manager.
Run Code Online (Sandbox Code Playgroud)
用法
random_painting = Painting.randoms.all()[0]
Run Code Online (Sandbox Code Playgroud)
最后,您可以在模型上拥有许多经理,因此可以随意创建LeastViewsManager()或MostPopularManager().
其他答案可能很慢(使用order_by('?')),或者使用多个SQL查询。这是一个示例解决方案,没有排序,只有一个查询(假设Postgres):
Model.objects.raw('''
select * from {0} limit 1
offset floor(random() * (select count(*) from {0}))
'''.format(Model._meta.db_table))[0]
Run Code Online (Sandbox Code Playgroud)
请注意,如果表为空,这将引发索引错误。为自己编写一个与模型无关的辅助函数以进行检查。
| 归档时间: |
|
| 查看次数: |
74004 次 |
| 最近记录: |