为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

ABOUTYOU 2022-10-25 10:50:00
我有一些 ID 是 UUID 的帖子模型。现在我想在我的 post_detail 模板中显示一些用户可能还希望看到的随机帖子提案......这就是我处理用户可能还希望在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_proposalsdef post_detail(request, pk):    ...  args = {    'post': post,    'post_proposals': post_proposals(),  ...模板.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 值。
查看完整描述

2 回答

?
肥皂起泡泡

TA贡献1829条经验 获得超6个赞

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

  1. 仅提取 id:model.objects.all().values_list('id',flat=True)。random.sample 的结果将是 ids,您可以直接使用 id 拉出帖子

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

获得 ID 后,您可以使用 model.objects.filter(id__in=post_proposals) 拉取集合并进一步处理

--- 编辑示例实现 ---

环绕其他模型的模型看起来像这样:

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')


查看完整回答
反对 回复 2022-10-25
?
米琪卡哇伊

TA贡献1998条经验 获得超6个赞

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

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

文档警告说,这order_by可能既昂贵又缓慢,但可能值得测试,看看它在实践中是否给出了可接受的结果。


查看完整回答
反对 回复 2022-10-25
  • 2 回答
  • 0 关注
  • 107 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信