Django:将来自两个查询(两个不同模型)的项目组合在一起

时间:2014-03-29 22:18:18

标签: mysql sql django postgresql

我正在使用Django构建一个事件平台,其中包含一些事件 public 和一些 invite -only。以下是它的基本工作原理:

  • 每个活动都基于活动模型。

  • 私人活动只有受邀嘉宾才能看到:这是实现的 通过邀请模型引用事件和访客。

  • 用户可以告知他们是否参加活动 通过存储相关事件的答案模型,用户 和答案。

  • 答案邀请模型完全相互独立,这样我就可以使用答案模型公共和私人活动。


我想要实现的目标:

对于我受邀的每个活动,请显示邀请(event.creator邀请您加入event.name),如果存在,则显示我的相关答案,否则显示要回答的表单。

所以我认为我想要做的就是让所有事件都被我邀请(我没有问题)并加入我的答案(用户=我)。问题是答案可能还不存在 - 如果我没有回答。

理想情况下,我会在一个查询中拥有所有这些,以便我可以在模板中执行类似的操作:invite_event.answer并显示答案(如果存在)。

编辑:

所以我认为我最终需要的是混合两个查询:一个获取我被邀请的所有事件(1),另一个获取这些事件的所有答案(2)。

(1)

latest_events_invited = Event.objects.filter(invite__user_invited=request.user)

(2)

answers_events_invited = Answer.objects.filter(user_answering=request.user, event__in=latest_events_invited)

类似于:对于latest_events_invited中的每个事件,附加来自answers_events_invited的相应答案。

有什么想法吗?


代码:

我的模板(index.html):

<h3>Invites</h3>
{% if latest_invites_list %}
    <ul>
    {% for event in latest_events_invited %}
        <li>
            {{ event.creator }} invited you to {{ event }}<br/ >

            <!--IDEALLY:-->
            {% if event.answer %}
                    You answered: {{ answer.answer }}
            {% else %}
                <form action="{% url 'events:answer_event' invite.event.id %}" method="post">
                    {% csrf_token %}
                    Answer:
                    <select name="answer">
                        <option value="1" >Attending</option>
                        <option value="2" >Not attending</option>
                    </select>
                    <input type="submit" name="submit" value="Answer">
                </form>
            {% endif %}
        </li>
    </ul>
{% else %}
    <p>No invites.</p>
{% endif %}

视图(views.py)

def index(request):

    if request.user.is_authenticated():
        latest_events_invited = Event.objects.filter(invite__user_invited=request.user)
        latest_answers_list = Answer.objects.filter(user_answering=request.user, event__in=latest_events_invited)

        #do something with those to get: "latest_events_invited_with_answers"

        context = {'latest_events_invited':latest_events_invited, 'latest_answers_list':latest_answers_list}

    else:
        [...]

return render(request, 'events/index.html', context)

和模特。

事件

class Event(models.Model):
    PRIVACY_CHOICES = (
        (0, 'Public'),
        (1, 'Invite only'),
    )

    name = models.CharField(max_length=200)
    [...]
    privacy = models.PositiveSmallIntegerField(max_length=1, choices=PRIVACY_CHOICES, default=0)
    invited = models.ManyToManyField(settings.AUTH_USER_MODEL, through='Invite', related_name='events_invited', blank=True)
    answers = models.ManyToManyField(settings.AUTH_USER_MODEL, through='Answer', related_name='events_answered', blank=True)

邀请

class Invite(models.Model):

    user_invited = models.ForeignKey(settings.AUTH_USER_MODEL)
    event = models.ForeignKey(Event)
    created = models.DateTimeField(default=timezone.now, editable=False)

    class Meta:
        unique_together = (("user_invited", "event"),)

答案

class Answer(models.Model):

    ANSWER_CHOICES = (
        (1, 'Attending'),
        (2, 'Not attending'),
    )

    user_answering = models.ForeignKey(settings.AUTH_USER_MODEL)
    event = models.ForeignKey(Event)
    answer = models.PositiveSmallIntegerField(max_length=1, choices=ANSWER_CHOICES)

    class Meta:
        unique_together = (("user_answering", "event"),)

希望有人可以帮助我 感谢。

2 个答案:

答案 0 :(得分:0)

一个选项是在邀请某人时自动添加答案,默认为“否”。使用邀请的post_save信号或覆盖保存方法,这样您就不必每次都创建相关的答案。 / p>

另一种选择,可能更好,是在视图中而不是在模板中执行逻辑。检查答案是否存在;如果是,则传递模板的答案列表;如果没有,请传递一个空列表。

编辑:或者,更好的是:

在视图中:

try:
  user_answer = Answer.objects.filter(user_answering = request.user).filter(event=event)
except ObjectDoesNotExist:
  answer = None

EDIT2:或者怎么样:

Answer.objects.filter(user_answering = request.user).filter(event__in=Event.objects.filter(user__in = event.invited))

答案 1 :(得分:0)

好的,所以我明白了。我不知道这是否是最佳解决方案,但它现在有效 最后,它只有2个查询,我与for循环结合。

这是代码:(views.py)

def index(request):
    if request.user.is_authenticated():
        latest_events_invited = Event.objects.filter(invite__user_invited=request.user)
        latest_answers_for_events = Answer.objects.filter(user_answering=request.user, event__in=latest_events_invited)

        for event in latest_events_invited:
            for answer in latest_answers_for_events:
                if answer.event.id == event.id:
                    event.answer = answer.answer
                else:
                    event.answer = ''

    context = {'latest_events_invited': latest_events_invited,}

    return render(request, 'events/index.html', context)

然后我可以直接在模板(index.html)中访问答案,如下所示:

{{ event.answer }}