无法检索外键ID

时间:2016-09-22 17:53:36

标签: django

我正在构建一个应用程序,允许用户创建场景,然后创建关联的电子邮件,t,调用和交易场景。

与场景和通信有1:很多关系。我遇到的问题是我希望用户能够单击该方案,然后显示已过滤的通信列表,每个通信源都是一个选项卡。我过滤通信的方式是基于对象上的外键的id。但是,如果数据源没有条目,我会收到"没有反向匹配"因为我正在使用来自第一个对象的方案ID,并且如果该方案没有通信则不存在。

除了删除我喜欢的标签之外,我对最好的方法感到难过。

如果我遗失任何内容,请告诉我,我对编程相对较新,对Django来说也很新。

models.py

from __future__ import unicode_literals
from django.db import models
from django.core.urlresolvers import reverse


class Scenario(models.Model):
    name = models.CharField(max_length=256, blank=False, null=False, unique=True)
    description = models.TextField(max_length=1000)

    def get_absolute_url(self):
        return reverse('scenarios:detail', kwargs={'pk': self.pk})

    def __unicode__(self):
        return self.name


class Email(models.Model):
    scenario = models.ForeignKey(Scenario, on_delete=models.CASCADE )
    recipient_email = models.EmailField()
    sender_email = models.EmailField()
    subject = models.CharField(blank=True, null=False, max_length=256)
    body = models.TextField(blank=True, null=False,  max_length=2048)
    # timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
    # updated = models.DateTimeField(auto_now_add=False, auto_now=True)

    def get_absolute_url(self):
        return reverse('scenarios:email-index')

    def __unicode__(self):
        return self.sender_email + ' ' + self.recipient_email + ' ' + self.subject


class InstantMessage(models.Model):
    NETWORKS = (
        ('Yahoo', 'Yahoo'),
        ('MSN', 'MSN'),
        ('Skype', 'Skype')
    )
    scenario = models.ForeignKey(Scenario, on_delete=models.CASCADE)
    description = models.CharField(max_length=256, null=False, blank=False)
    network = models.CharField(max_length=50, null=False, blank=False, choices=NETWORKS)
    room = models.CharField(max_length=100, null=False, blank=False)
    starttime = models.TimeField(blank=False, null=False)
    endtime = models.TimeField(blank=False, null=False)
    participant1 = models.CharField(max_length=256, null=False, blank=False)
    participant2 = models.CharField(max_length=256, null=False, blank=False)
    chatcsv = models.FileField(upload_to='chatfiles')

    def get_absolute_url(self):
        return reverse('scenarios:im-index')

    def __unicode__(self):
        return "Network=" + self.network + " Description:" + self.description



class VoiceCall(models.Model):
    DIRECTION = (
        ('outbound', 'Outbound'),
        ('inbound', 'Inbound')
    )

    scenario = models.ForeignKey(Scenario, on_delete=models.CASCADE)
    description = models.CharField(max_length=256, null=False, blank=False)
    direction = models.CharField(choices=DIRECTION, null=False, blank=False, default="Outbound", max_length=15)
    starttime = models.TimeField(blank=False, null=False)
    endtime = models.TimeField(blank=False, null=False)
    traderid = models.CharField(max_length=50,blank=False, null=False)
    diallednumber = models.BigIntegerField(blank=True, null=True)
    cli = models.BigIntegerField(blank=True, null=True)
    nameofcaller = models.CharField(max_length=100, blank=True, null=True)
    nameofline = models.CharField(max_length=100, blank=True, null=True)
    wavfile = models.FileField(upload_to='voice')
    transcript = models.FileField(blank=True, null=True, upload_to='voice')
    bagofwords = models.FileField(blank=True, null=True, upload_to='voice')

    def get_absolute_url(self):
        return reverse('scenarios:call-index')

    def __unicode__(self):
        return self.description


class Trade(models.Model):
    scenario = models.ForeignKey(Scenario, on_delete=models.CASCADE)
    tradeprefix = models.CharField(max_length=6, null=False, blank=False)
    trader = models.CharField(max_length=256, null=False, blank=False)
    sales = models.CharField(max_length=256, null=False, blank=False)
    counterpartyid = models.CharField(max_length=256, null=False, blank=False)
    counterpartyname = models.CharField(max_length=256, null=False, blank=False)
    brokerid = models.CharField(max_length=256, null=False, blank=False)
    brokername = models.CharField(max_length=256, null=False, blank=False)
    isevent = models.BooleanField(default=False)

    def get_absolute_url(self):
        return reverse('scenarios:trade-index')

    # def __unicode__(self):
    #     return self.description


class Mobile(models.Model):
    scenario = models.ForeignKey(Scenario, on_delete=models.CASCADE)
    displayname = models.CharField(max_length=100, null=False, blank=False)
    email = models.EmailField()
    tonumber = models.BigIntegerField(blank=True, null=True)
    fromnumber = models.BigIntegerField(blank=True, null=True)
    message = models.CharField(blank=True, null=False, max_length=1024)

    def get_absolute_url(self):
        return reverse('scenarios:mobile-index')

views.py

  class IMScenarioList(generic.ListView):
    model = InstantMessage
    template_name = 'scenarios/im_filtered.html'
    context_object_name = 'scenario_ims'

    def get_queryset(self):
        return InstantMessage.objects.filter(scenario=self.kwargs['pk'])


class CallScenario(generic.ListView):
    model = VoiceCall
    template_name = 'scenarios/call_filtered.html'
    context_object_name = 'scenario_calls'

    def get_queryset(self):
        return VoiceCall.objects.filter(scenario=self.kwargs['pk'])


class MobileScenario(generic.ListView):
    model = Mobile
    template_name = 'scenarios/mobile_filtered.html'
    context_object_name = 'scenario_mobiles'

    def get_queryset(self):
        return Mobile.objects.filter(scenario=self.kwargs['pk'])


class TradeScenario(generic.ListView):
    model = Trade
    template_name = 'scenarios/trades_filtered.html'
    context_object_name = 'trades'

    def get_queryset(self):
        return Trade.objects.filter(scenario=self.kwargs['pk'])

urls.py

url(r'^(?P<pk>[0-9]+)/email/$', views.EmailScenarioList.as_view(), name='email-scenario'),

    # Instant Messages
    url(r'^im/$', views.IMList.as_view(), name='im-index'),
    url(r'^im/add/$', views.IMCreate.as_view(), name='im-create'),
    url(r'^im/(?P<pk>[0-9]+)/update/$', views.IMUpdate.as_view(), name='im-update'),
    url(r'^im/(?P<pk>[0-9]+)/delete/$', views.IMDelete.as_view(), name='im-delete'),
    url(r'^(?P<pk>[0-9]+)/im/$', views.IMScenarioList.as_view(), name='im-scenario'),

    # Voice Calls
    url(r'^calls/$', views.CallList.as_view(), name='call-index'),
    url(r'calls/add/$', views.CallCreate.as_view(), name='call-create'),
    url(r'^calls/(?P<pk>[0-9]+)/update/$', views.CallUpdate.as_view(), name='call-update'),
    url(r'^calls/(?P<pk>[0-9]+)/delete/$', views.CallDelete.as_view(), name='call-delete'),
    url(r'^(?P<pk>[0-9]+)/voice/$', views.CallScenario.as_view(), name='call-scenario'),

    # trades
    url(r'^trades/$', views.TradeList.as_view(), name='trade-index'),
    url(r'^trades/add/$', views.TradeCreate.as_view(), name='trade-create'),
    url(r'^trades/(?P<pk>[0-9]+)/update/$', views.TradeUpdate.as_view(), name='trade-update'),
    url(r'^trades/(?P<pk>[0-9]+)/delete/$', views.TradeDelete.as_view(), name='trade-delete'),
    url(r'^(?P<pk>[0-9]+)/trade/$', views.TradeScenario.as_view(), name='trade-scenario'),

    # mobile
    url(r'^mobile/$', views.MobileList.as_view(), name='mobile-index'),
    url(r'^mobile/add/$', views.MobileCreate.as_view(), name='mobile-create'),
    url(r'^mobile/(?P<pk>[0-9]+)/update/$', views.MobileUpdate.as_view(), name='mobile-update'),
    url(r'^mobile/(?P<pk>[0-9]+)/delete/$', views.MobileDelete.as_view(), name='mobile-delete'),
    url(r'^(?P<pk>[0-9]+)/mobile/$', views.MobileScenario.as_view(), name='mobile-scenario'),

模板

trade_index.html

{% extends 'base.html' %}
{% block content %}

    <div class="container">
        <table id="myTable" class="tablesorter tablesorter-bootstrap">
            <thead>
                <tr>
                    <th class="first-name filter-select" data-placeholder="Select a Scenario">Scenario</th>
                    <th></th>
                    <th>Trade Prefix</th>
                    <th>Trader</th>
                    <th>Sales</th>
                    <th>Counterparty ID</th>
                    <th class="first-name filter-select" data-placeholder="Select Counterparty">Counterparty Name</th>
                    <th>Broker ID</th>
                    <th></th>
                    <th class="first-name filter-select" data-placeholder="Select Broker">Broker Name</th>
                    <th class="first-name filter-select" data-placeholder="IsEvent">IsEvent</th>
                    <th>Edit</th>
                    <th>Delete</th>
                </tr>
            </thead>
                <tbody>
                {% for  trade in trades %}
                  <tr>
                <td data-toggle="tooltip" title="Description: {{trade.scenario.description}}">{{trade.scenario}}</td>
                    <td></td>
                    <td>{{trade.tradeprefix}}</td>
                    <td>{{trade.trader}}</td>
                    <td>{{trade.sales}}</td>
                    <td>{{trade.counterpartyid}}</td>
                    <td>{{trade.counterpartyname}}</td>
                    <td>{{trade.brokerid}}</td>
                    <td></td>
                    <td>{{trade.brokername}}</td>
                    <td>{{trade.isevent}}</td>
                    <td>
                        <a href="{% url 'scenarios:trade-update' trade.id %}">
                            <button type="submit" class="btn btn-default btn-sm">
                                <span class="glyphicon glyphicon-pencil" />
                            </button>
                        </a>
                    </td>

                    <td><form action="{% url 'scenarios:trade-delete' pk=trade.id %}" method="post">
                            {% csrf_token %}
                            <input type="hidden" name="call_id" value="{{ trade.id}}"/>
                            <button type="submit" class="btn btn-default btn-sm" onclick="return confirm('Are you sure you want to delete {{trade.description}}?')">
                                <span class="glyphicon glyphicon-trash" />
                            </button>
                        </form>
                    </td>
                  </tr>
                {% endfor %}
            </tbody>
            </table>
            <a href="{% url 'scenarios:trade-create' %}">
                <button type="submit" class="btn btn-default btn-sm">
                    <span class="glyphicon glyphicon-plus" />

                </button>
            </a> Add Trade
            <br>
            <button type="button" class="btn btn-default btn-sm"  value="Back" onClick="javascript:history.go(-1);">
                    <span class="glyphicon glyphicon-backward" />
            </button>

</div>

{% endblock %}

trades_filtered.html

{% extends 'scenarios/trade_index.html' %}
{% block content %}
{% with trades|first as first_trade %}
      <ul class="nav nav-pills">
            <li class="active"><a href="{% url 'scenarios:trade-scenario' pk=first_trade.scenario.id %}">trades</a></li>
            <li><a href="{% url 'scenarios:email-scenario' pk=first_trade.scenario.id %}">emails</a></li>
            <li><a href="{% url 'scenarios:im-scenario' pk=first_trade.scenario.id %}">instant messages</a></li>
            <li><a href="{% url 'scenarios:call-scenario' pk=first_trade.scenario.id %}">voice</a></li>
            <li><a href="{% url 'scenarios:mobile-scenario' pk=first_trade.scenario.id %}">mobile</a></li>
      </ul>
{% endwith %}
        {{ block.super }}
{% endblock %}

1 个答案:

答案 0 :(得分:1)

现在在trades_filtered.html中,您获取给定scenario的ID并使用该ID手动构建您的五个网址。如果是我,我会使用自定义模型方法来确定是否需要首先生成URL。

class Scenario(models.Model):
    name = models.CharField(max_length=256, blank=False, null=False, unique=True)
    description = models.TextField(max_length=1000)

    def generate_trade_url(self):
        if self.trade_set.exists():
            return reverse('scenarios:trade-scenario', kwargs={'pk':self.pk})
        return None

    def generate_email_url(self):
        ...

对于要生成的每个网址,您需要一个这样的方法。您可以在视图(首选)或模板(更简单但更慢)中使用此逻辑,以便仅在URL有效时动态生成URL。

编辑:我刚刚第二次看了这个答案。我在null=False字段定义中包含name,因为它位于原始字段中,但要注意它实际上并没有对CharField执行任何有用的操作。 Django不对这些字段使用空值,而是将它们存储为''(空字符串)。