在Django中,当每个帖子使用UUID而不是顺序ID时,如何有效地对随机帖子进行采样?

2024-06-25 23:20:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一些post模型,其中ID是UUID。 现在,我想显示一些随机张贴的建议,用户可能也喜欢在我的张贴详细模板看到

这是我处理用户可能也希望在views.py上看到的帖子建议的方式:

def post_proposals():
    post_elements = sorted(
        chain(
            Model1.objects.all(),
            Model2.objects.all(),
            Model3.objects.all()
        )
    )
    post_elements_list = list(post_elements) # Conversion to list is requierd by random
    post_proposals = random.sample(post_elements_list)
    return post_proposals


def post_detail(request, pk):
    ...
  args = {
    'post': post,
    'post_proposals': post_proposals(),
  ...

template.html:

 {% for post_proposal in post_proposals %}
    <h1>{{ post_proposal.title }}</h1>
 {% endfor %}

现在的问题是,从我的理解来看,这会破坏我的数据库性能。。。一旦我的数据库中存储了大量帖子,查询就会变得庞大。我首先要获取3个模型的所有元素,然后每次向用户显示帖子时,从列表中随机获取10个条目

我还发现以下内容似乎非常有用:

https://elpenia.wordpress.com/2010/05/11/getting-random-objects-from-a-queryset-in-django/

遗憾的是,我不能使用这个解决方案,因为我使用的UUID是非顺序字符串,而不是ID的int值


Tags: 用户模型idobjectsuuiddefrandomelements
2条回答

问题是你有不同的型号,这使得操作非常昂贵。 我建议您添加一个新模型,其中所有要查询的模型都注册为外键或id/类型对。这样,您就可以绕过设计缺陷

  1. 仅拉动ID: model.objects.all().values\u list('id',flat=True)。 random.sample的结果将是id,您可以直接使用id拉帖子

  2. 生成新表的1到count()之间的随机范围,然后通过处理具有相应索引的记录来提取实际的POST。这需要您添加一个索引字段,因为id可能不是连续的(删除和填充)

获得id后,您可以使用model.objects.filter(id\uuuu in=post\u建议书)提取集合并进一步处理它

-编辑示例实现-

环绕其他模型的模型将如下所示:

class Model1(models.Model):
   @staticmethod
   def get_ref_type(): return 0

   def create(self):
      super(Model1,self).create()
      Posts.register(self,Model1.get_ref_type())

   def delete(self):
      Posts.un_register(self,Model1.get_ref_type())
      super(Model1,self).delete()

class Posts(models.Model):
  class Meta: 
    ....

  #sequential index, this is what you will filter against
  index    = models.IntegerField(default=0)
  #type of the model you want to query
  ref_type = models.IntegerField(default =-1)
  #id of the record in the table defined in the ref_type field
  ref_id   = models.IntegerField(default =-1)

  @staticmethod
  def register(f_objRecord,f_intType):
      l_objWrp = Posts()
      #a separate table that will be used to hold the free indexes
      #it will ensure that even when you delete records, there
      #won't be any holes in the set
      l_objWrp.index = PostIndex.get_index()
      l_objWrp.ref_id = f_objRecord.id 
      l_objWrp.ref_type = f_intType

      l_objWrp.save()

  @staticmethod
  def un_register(f_objRecord,f_intType):
     l_objWrp = Posts.objects.get(ref_type=f_intType,ref_id=f_objRecord.id)
     PostIndex.free_index(l_objWrp.index)
     l_objWrp.delete()
  def get_data(self):
     l_intRefType = self.ref_type
     l_intId      = self.ref_id

     l_objRecord = None
     if l_intRefType == Model1.get_ref_type():
        l_objRecord = Model1.objects.get(id=l_intId)
     elif l_intRefType == Model2.get_ref_type():
       .....

     if l_objRecord: 
        #pull the data you want
     else: raise('unknown model type')

例如,您可以尝试让数据库随机排序,然后切片

Model1.objects.order_by('?')[:3]`.

^{}文档警告说,这可能代价高昂且速度缓慢,但可能值得进行测试,看看它在实践中是否给出了可接受的结果

相关问题 更多 >