Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/86.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Django:确定用户是否已投票_Python_Sql_Django_Orm - Fatal编程技术网

Python Django:确定用户是否已投票

Python Django:确定用户是否已投票,python,sql,django,orm,Python,Sql,Django,Orm,我有一个很长的链接列表,我使用下面的代码,总投票数,提交人,通常的东西,但我不是100%的关于如何确定当前登录的用户是否对链接投票。我知道如何从我的视图中执行此操作,但我是否需要更改我的以下视图代码,或者我是否可以利用模板的工作方式来确定它 我读过,但我不太明白发生了什么,不需要任何JavaScriptery 模型代码段: class Link(models.Model): category = models.ForeignKey(Category, blank=False, defau

我有一个很长的链接列表,我使用下面的代码,总投票数,提交人,通常的东西,但我不是100%的关于如何确定当前登录的用户是否对链接投票。我知道如何从我的视图中执行此操作,但我是否需要更改我的以下视图代码,或者我是否可以利用模板的工作方式来确定它

我读过,但我不太明白发生了什么,不需要任何JavaScriptery

模型代码段:

class Link(models.Model):
    category = models.ForeignKey(Category, blank=False, default=1)
    user = models.ForeignKey(User)
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)
    url = models.URLField(max_length=1024, unique=True, verify_exists=True)
    name = models.CharField(max_length=512)

    def __unicode__(self):
        return u'%s (%s)' % (self.name, self.url)

class Vote(models.Model):
    link = models.ForeignKey(Link)
    user = models.ForeignKey(User)
    created = models.DateTimeField(auto_now_add=True)

    def __unicode__(self):
        return u'%s vote for %s' % (self.user, self.link)
def hot(request):
    links = Link.objects.select_related().annotate(votes=Count('vote')).order_by('-created')
    for link in links:
        delta_in_hours = (int(datetime.now().strftime("%s")) - int(link.created.strftime("%s"))) / 3600
        link.popularity = ((link.votes - 1) / (delta_in_hours + 2)**1.5)
        if request.user.is_authenticated():
            try:
                link.voted = Vote.objects.get(link=link, user=request.user)
            except Vote.DoesNotExist:
                link.voted = None

    links = sorted(links, key=lambda x: x.popularity, reverse=True)

    links = paginate(request, links, 15)

    return direct_to_template(
        request,
        template = 'links/link_list.html',
        extra_context = {
            'links': links,
        })
视图片段:

class Link(models.Model):
    category = models.ForeignKey(Category, blank=False, default=1)
    user = models.ForeignKey(User)
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)
    url = models.URLField(max_length=1024, unique=True, verify_exists=True)
    name = models.CharField(max_length=512)

    def __unicode__(self):
        return u'%s (%s)' % (self.name, self.url)

class Vote(models.Model):
    link = models.ForeignKey(Link)
    user = models.ForeignKey(User)
    created = models.DateTimeField(auto_now_add=True)

    def __unicode__(self):
        return u'%s vote for %s' % (self.user, self.link)
def hot(request):
    links = Link.objects.select_related().annotate(votes=Count('vote')).order_by('-created')
    for link in links:
        delta_in_hours = (int(datetime.now().strftime("%s")) - int(link.created.strftime("%s"))) / 3600
        link.popularity = ((link.votes - 1) / (delta_in_hours + 2)**1.5)
        if request.user.is_authenticated():
            try:
                link.voted = Vote.objects.get(link=link, user=request.user)
            except Vote.DoesNotExist:
                link.voted = None

    links = sorted(links, key=lambda x: x.popularity, reverse=True)

    links = paginate(request, links, 15)

    return direct_to_template(
        request,
        template = 'links/link_list.html',
        extra_context = {
            'links': links,
        })
上述观点实际上满足了我的需要,但我认为这是一种非常低效的方式。这就导致了可怕的n+1查询,目前的情况是,一个只包含29个链接的页面有33个查询,而最初我只处理了4个查询。我真的更愿意使用Django的ORM或者至少是.extra来实现这一点

有什么建议吗

编辑

@加布里埃尔·赫利

我正在尝试重新创建你的答案,我很高兴有混合的结果,让我告诉你我得到了什么

views.py

links = Link.objects.select_related().extra(
    select={
        'votes': 'COUNT(links_vote.id)',
        'voted': 'SELECT COUNT(links_vote.id) FROM links_vote WHERE links_vote.user_id = 1 AND links_vote.link_id = links_link.id',
    },
    tables = ['links_vote']
)
models.py

class Vote(models.Model):
    link = models.ForeignKey(Link)
    user = models.ForeignKey(User)
    created = models.DateTimeField(auto_now_add=True)

    class Meta:
        unique_together = ('link', 'user')

    def __unicode__(self):
        return u'%s vote for %s' % (self.user, self.link)
但它返回了一个错误:

subquery uses ungrouped column "links_link.id" from outer query
第1行:…E links\u vote.user\u id=1和links\u vote.link\u id=links\u link

生成的查询看起来与以下内容完全相同:

SELECT (SELECT COUNT(links_vote.id) FROM links_vote WHERE links_vote.user_id = 1 AND links_vote.link_id = links_link.id) AS "voted", "links_link"."id", "links_link"."category_id", "links_link"."user_id", "links_link"."created", "links_link"."modified", "links_link"."url", "links_link"."name", "links_category"."id", "links_category"."name", "auth_user"."id", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."password", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."is_superuser", "auth_user"."last_login", "auth_user"."date_joined" FROM "links_link" INNER JOIN "links_category" ON ("links_link"."category_id" = "links_category"."id") INNER JOIN "auth_user" ON ("links_link"."user_id" = "auth_user"."id") , "links_vote"
我使用的是PostgreSQL,我知道它很喜欢GROUP BY,但我对如何纠正这一点不是百分之百的了解

编辑2个主要进展

links=Link.objects.select\u related.annotatedVoces=Count'vote'。额外 挑选={ “已投票”:“从链接投票中选择计数,其中链接投票。用户投票id=%s和链接投票。链接投票id=链接投票。id”%request.user.id, “已投票”:%request.user.id, “已投票”:“当链接\u vote.user\u id=%s然后1 ELSE 0结束“%request.user.id”时选择大小写, “已投票”:“从链接投票中选择计数,其中links\u vote.link\u id=links\u link.id和links\u vote.user\u id=%s”%request.user.id, }, 其中=['links\u link.id=links\u vote.link\u id'], .order_by'-已创建'

*这只有在从这里为bug应用补丁后才有效


我很快就要找到我需要确定用户是否投票的最后一块了…

我以前处理过这个问题,并或多或少地用额外的方法解决了它,就像这样:

# annotate whether you've already voted on this item
table = Vote._meta.db_table
select = 'SELECT COUNT(id) FROM %s' %table
where1 = 'WHERE ' + table + '.user_id = %s'
where2 = 'AND ' + table + '.item_id = appname_item.id'
items = items.extra(
        select={'votes':" ".join((select, where1, where2,))},
        select_params=(request.user.id,)
    )

实际上,这需要一组查询项,并用0或某些票数对每个项进行注释。在我的系统中,我在投票时使用unique_together='link','user',以确保每个用户只能投票一次,因此带注释的数据可以是0或1。它工作得很好,避免了n+1问题。

我有几个问题不适合这里,请参见上面的编辑。谢谢你!我觉得这让我走上了正轨。