Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.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
如何在不使用原始sql的情况下使用Django连接两个表?_Django_Sorting_Join_Django Models_Django Voting - Fatal编程技术网

如何在不使用原始sql的情况下使用Django连接两个表?

如何在不使用原始sql的情况下使用Django连接两个表?,django,sorting,join,django-models,django-voting,Django,Sorting,Join,Django Models,Django Voting,是否可以使用Django的ORM以编程方式连接两个表?我有两个模型:主题和投票。在我的模板上,我有一个主题列表,用户可以像Reddit一样向上/向下投票。除了对结果进行排序外,一切都正常工作。我不知道如何根据分数对对象列表进行排序,分数是每个对象的投票计数之和。我可以从postgres检索到所需的数据,没有任何问题: select i.id, i.title, i.date_created, s.object_id, s.vote, Sum(vote) from topic_topic i,

是否可以使用Django的ORM以编程方式连接两个表?我有两个模型:主题和投票。在我的模板上,我有一个主题列表,用户可以像Reddit一样向上/向下投票。除了对结果进行排序外,一切都正常工作。我不知道如何根据分数对对象列表进行排序,分数是每个对象的投票计数之和。我可以从postgres检索到所需的数据,没有任何问题:

select i.id, i.title, i.date_created, s.object_id, s.vote, Sum(vote) 
from topic_topic i, votes s 
where i.id = s.object_id 
group by 1, 2, 3, 4, 5 
order by sum DESC;
它返回所需的结果:

id | title  |         date_created          | object_id | vote | sum 

11 | sdfg   | 2012-06-04 23:30:17.805671-07 |        11 |    1 |   2

 1 | test   | 2012-05-13 17:03:24.206092-07 |         1 |    1 |   2

 3 | asdf   | 2012-05-13 19:23:15.059135-07 |         3 |    1 |   2

 2 | adsf   | 2012-05-13 19:21:34.180905-07 |         2 |    1 |   2

12 | 11     | 2012-06-04 23:30:54.759158-07 |        12 |    1 |   2

 9 | asfd   | 2012-05-24 00:26:26.705843-07 |         9 |   -1 |  -1

 4 | asdf   | 2012-05-14 19:59:52.450693-07 |         4 |   -1 |  -2
问题是,我不确定如何将其作为查询集检索。目前,我正在使用以下内容显示对象:

topic_list = Topic.objects.all()
除排序顺序外,所有内容都按我的要求显示。我想先显示最高分

我已经看过的资源:

还有更多,但作为一个新用户,反垃圾邮件阻止我添加它们

我试过的东西:

链:

listed_links = list(chain(topic, score))
不幸的是,如果我试图添加一个排序的值,这将导致崩溃

组合对象列表:

topic = Topic.objects.all().values_list('user','id', 'title','slug', 'date_created', 'date_updated',)

score = Vote.objects.values('object_id').annotate(total=Sum('vote')).order_by('-total')

results = []

for topic in topic:
results.append(topic)

for score in score:
results.append(topic)
这导致所有我想要的对象都出现在一个列表中,但我不知道如何将
topic.id
链接到
score.object\u id

我也尝试过插入原始SQL,但我觉得我做得不对,可能会导致第三方进行SQL注入

我很乐意将这一结果分享给django投票项目。就像我说的,一切都按它应该的方式运行,除了我不知道如何按分数desc排序

=============投票========================

from django.contrib.contenttypes import generic

from django.contrib.contenttypes.models import ContentType

from django.contrib.auth.models import User

from django.db import models

from voting.managers import VoteManager

from voting.VotedObjectsManager import VotedObjectsManager

    SCORES = (
    (+1, u'+1'),
    (-1, u'-1'),
)

class Vote(models.Model):

    """
    A vote on an object by a User.
    """

    user         = models.ForeignKey(User)

    content_type = models.ForeignKey(ContentType)

    object_id    = models.PositiveIntegerField()

    object       = generic.GenericForeignKey('content_type', 'object_id')

    vote         = models.SmallIntegerField(choices=SCORES)

    objects      = VoteManager()


    class Meta:
        db_table = 'votes'
        # One vote per user per object
        unique_together = (('user', 'content_type', 'object_id'),)

    def __unicode__(self):
        return u'%s: %s on %s' % (self.user, self.vote, self.object)

    def is_upvote(self):
        return self.vote == 1

    def is_downvote(self):
        return self.vote == -1
from django.db import models

from datetime import datetime

from tinymce import models as tinymce_models

from django.forms import ModelForm

from django.template.defaultfilters import slugify

from tagging.fields import TagField

from tagging.models import Tag

from django.contrib.auth.models import User

from django.utils.translation import ugettext_lazy as _

from django.contrib.contenttypes.models import ContentType

from django.contrib.contenttypes import generic

from django.core import urlresolvers

    class Topic(models.Model):

    title           = models.CharField(max_length=50)

    slug            = models.SlugField(max_length=50, editable=False)

    topic         = tinymce_models.HTMLField()

    date_created    = models.DateTimeField(editable=False)

    date_updated    = models.DateTimeField(editable=False)

    tags            = TagField()


    def set_tags(self, tags):
        Tag.objects.update_tags(self, tags)    

    def __unicode__(self):
        return self.tags

    def __unicode__(self):
        return self.id

    def __unicode__(self):
        return self.title
=============主题模型========================

from django.contrib.contenttypes import generic

from django.contrib.contenttypes.models import ContentType

from django.contrib.auth.models import User

from django.db import models

from voting.managers import VoteManager

from voting.VotedObjectsManager import VotedObjectsManager

    SCORES = (
    (+1, u'+1'),
    (-1, u'-1'),
)

class Vote(models.Model):

    """
    A vote on an object by a User.
    """

    user         = models.ForeignKey(User)

    content_type = models.ForeignKey(ContentType)

    object_id    = models.PositiveIntegerField()

    object       = generic.GenericForeignKey('content_type', 'object_id')

    vote         = models.SmallIntegerField(choices=SCORES)

    objects      = VoteManager()


    class Meta:
        db_table = 'votes'
        # One vote per user per object
        unique_together = (('user', 'content_type', 'object_id'),)

    def __unicode__(self):
        return u'%s: %s on %s' % (self.user, self.vote, self.object)

    def is_upvote(self):
        return self.vote == 1

    def is_downvote(self):
        return self.vote == -1
from django.db import models

from datetime import datetime

from tinymce import models as tinymce_models

from django.forms import ModelForm

from django.template.defaultfilters import slugify

from tagging.fields import TagField

from tagging.models import Tag

from django.contrib.auth.models import User

from django.utils.translation import ugettext_lazy as _

from django.contrib.contenttypes.models import ContentType

from django.contrib.contenttypes import generic

from django.core import urlresolvers

    class Topic(models.Model):

    title           = models.CharField(max_length=50)

    slug            = models.SlugField(max_length=50, editable=False)

    topic         = tinymce_models.HTMLField()

    date_created    = models.DateTimeField(editable=False)

    date_updated    = models.DateTimeField(editable=False)

    tags            = TagField()


    def set_tags(self, tags):
        Tag.objects.update_tags(self, tags)    

    def __unicode__(self):
        return self.tags

    def __unicode__(self):
        return self.id

    def __unicode__(self):
        return self.title

您可以尝试注释主题查询集以包含投票总数:

topic_list = Topic.objects.all().annotate(total=Sum('vote__vote')).order_by('-total')

注意:在没有看到您的模型的情况下,我不确定在
Sum()
函数中放什么。它应该是子模型名(我假设是vote),后跟模型上的字段名。

我能够使用如下所述的补丁来找出解决方案:

不同之处在于我提取了以下几行:

    def select_score(self):
    """ Add vote scores for objects in resoultset """
    from django.contrib.contenttypes.models import ContentType
    model_type = ContentType.objects.get_for_model(self.model)
    table_name = self.model._meta.db_table
    print type(model_type)
    print model_type.id
    return self.extra(select={'score': 'SELECT SUM(vote) FROM votes WHERE content_type_id=%i AND object_id=%s.id' % (int(model_type.id), table_name)})
并将它们添加到投票/managers.py文件中,如下所示:

class VoteManager(models.Manager):
def get_score(self, obj):
    """
    Get a dictionary containing the total score for ``obj`` and
    the number of votes it's received.
    """
    ctype = ContentType.objects.get_for_model(obj)
    result = self.filter(object_id=obj._get_pk_val(),
                         content_type=ctype).extra(
        select={
            'score': 'COALESCE(SUM(vote), 0)',
            'num_votes': 'COALESCE(COUNT(vote), 0)',
    }).values_list('score', 'num_votes')[0]

    return {
        'score': int(result[0]),
        'num_votes': int(result[1]),
    }
然后在我的主题.views.py中添加了以下内容:

from voting.managers import VoteManager
def index(request):
queryset = Topic.objects.select_score().order_by('-score')
paginator = Paginator(queryset, 3) # Show 25 contacts per page

page = request.GET.get('page')
try:
    topic_list = paginator.page(page)
except PageNotAnInteger:
    # If page is not an integer, deliver first page.
    topic_list = paginator.page(1)
except EmptyPage:
    #If page is out of range (e.g. 9999), deliver last page of results.
    topic_list = paginator.page(paginator.num_pages)

c = Context({
'topic_list': topic_list,
'request': request
})
return render_to_response('idea/index.html', c, context_instance=RequestContext(request))
最后,在我的index.html中,我添加了以下几行,这与为用户提供的原始示例略有不同:

{% load voting_tags %}
{% votes_by_user user on topic_list as vote_dict %}
{% scores_for_objects topic_list as score_dict %}

<table id="voting_table" class="list">
<tbody>
  {% for link in topic_list %}
<td class="vote">

{% dict_entry_for_item link from vote_dict as vote %}
{% dict_entry_for_item link from score_dict as score %}

<div>    
 <form class="linkvote" id="linkup{{ link.id }}"{% if vote and vote.is_upvote %} action="{% url link_vote object_id=link.id, direction="clear" %}"{% else %} action="{% url link_vote object_id=link.id, direction="up" %}"{% endif %} method="POST">
    <input type="image" id="linkuparrow{{ link.id }}" src="{{ STATIC_URL }}images/aup{% if vote and vote.is_upvote %}mod{% else %}grey{% endif %}.png">
    {% csrf_token %}
    <input type="hidden" name="next" value="{{ request.get_full_path }}"/>
    {% else %}

  </form>

       <div id="link_score">{{ score.score|default:0 }}</div>

  <form class="linkvote" id="linkdown{{ link.id }}" {% if vote and vote.is_downvote %} action="{% url link_vote object_id=link.id, direction="clear" %}"{% else %} action="{% url link_vote object_id=link.id, direction="down" %}"{% endif %} method="POST">
  {% csrf_token %}
    <input type="image" id="linkdownarrow{{ link.id }}" src="{{ STATIC_URL }}images/adown{% if vote and vote.is_downvote %}mod{% else %}grey{% endif %}.png">
     <input type="hidden" name="next" value="{{ request.get_full_path }}"/>

</td>
<td class="item">
  <a id="link_title" href="{{ link.id }}">{{ link.title|escape }}</a></h2>
  <p class="details">
    <span class="score" id="linkscore{{ link.id }}"
          title="after {{ score.num_votes|default:0 }} vote{{ score.num_votes|default:0|pluralize }}">
    </span>
    posted {{ link.date_created|timesince }} ago by
    <span class="user"><a href="../users/{{ link.user.id }}/">{{ link.owner|escape }}</a></span>
{% get_comment_count for link as comment_count %}
    <span id="comment_score" class="comment_details"> {{ comment_count }} comment{{ comment_count|pluralize }}</span>
  </p>
</td>
</tr>{% endfor %}
</tbody>
  <td>
    <div id="paginator" class="pagination">
    <span class="step-links">
        {% if topic_list.has_previous %}
            <a href="?page={{ topic_list.previous_page_number }}">previous</a>
    {% endif %}
    {% if topic_list.has_next %}
        <a href="?page={{ topic_list.next_page_number }}">next</a>
    {% endif %}
    </span>
    </div>
  </td>
</table>
})


我真的希望这能帮助别人。很抱歉,没有尽快发布解决方案。希望有人能通过从VoteManager中删除SQL来改进这一点,但我需要继续前进。

我添加了模型。谢谢你的快速反馈。嗨,内森!谢谢你的反馈。我希望我能为这个主题添加的链接数量不受限制。不幸的是,我已经试过了,结果是:FieldError:无法将关键字“投票”解析到字段中。选项包括:创建日期、更新日期、id、所有者、slug、标记、标题我怀疑这与使用GenericForeignKey有关。我没有看到一个关于主题的问题-你需要添加它以便你可以访问该主题的投票吗?我相信是的。django投票应用程序使用通用视图来管理投票。再次感谢内森的努力。