将基于类的视图UpdateView与2个主键模型一起使用

时间:2019-01-22 20:04:10

标签: python django

我正在用两个主键(这是一个旧数据库)构建一个求和。

基本上我想做的是单击表格元素,然后基于模型上的主键重定向到另一页。

我找不到有关如何使用Django基于类的视图执行此操作的任何信息

这是我的代码:

models.py

class RmDadoscarteira(models.Model):
    dtcalculo = models.DateField(db_column='dtCalculo', primary_key=True)  # Field name made lowercase.
    cdcarteira = models.CharField(db_column='cdCarteira', max_length=50)  # Field name made lowercase.
    nmcarteira = models.CharField(db_column='nmCarteira', max_length=255, blank=True, null=True)  # Field name made lowercase.
    pl = models.FloatField(db_column='PL', blank=True, null=True)  # Field name made lowercase.
    retornocota1d = models.FloatField(db_column='RetornoCota1d', blank=True, null=True)  # Field name made lowercase.
    var = models.FloatField(db_column='Var', blank=True, null=True)  # Field name made lowercase.
    var_lim = models.FloatField(db_column='VaR_Lim', blank=True, null=True)  # Field name made lowercase.
    var_variacao1d = models.FloatField(db_column='VaR_Variacao1d', blank=True, null=True)  # Field name made lowercase.
    var_variacao63d = models.FloatField(db_column='VaR_Variacao63d', blank=True, null=True)  # Field name made lowercase.
    var_consumolimite = models.FloatField(db_column='VaR_ConsumoLimite', blank=True, null=True)  # Field name made lowercase.
    stress = models.FloatField(db_column='Stress', blank=True, null=True)  # Field name made lowercase.
    stress_lim = models.FloatField(db_column='Stress_Lim', blank=True, null=True)  # Field name made lowercase.
    stress_variacao1d = models.FloatField(db_column='Stress_Variacao1d', blank=True, null=True)  # Field name made lowercase.
    stress_variacao63d = models.FloatField(db_column='Stress_Variacao63d', blank=True, null=True)  # Field name made lowercase.
    stress_consumolimite = models.FloatField(db_column='Stress_ConsumoLimite', blank=True, null=True)  # Field name made lowercase.
    grupo = models.CharField(db_column='Grupo', max_length=20, blank=True, null=True)  # Field name made lowercase.
    var_pl = models.FloatField(db_column='VaR_PL', blank=True, null=True)  # Field name made lowercase.
    stress_pl = models.FloatField(db_column='Stress_PL', blank=True, null=True)  # Field name made lowercase.


    objetos = models.Manager()

    class Meta:
        managed = False
        db_table = 'RM_DadosCarteira'
        unique_together = (('dtcalculo', 'cdcarteira'),)

views.py

from django.shortcuts import render, HttpResponse
from .models import *
import json
import pandas as pd
from django.views.generic.base import TemplateView
from django.urls import reverse_lazy
from django.views.generic.edit import UpdateView

# View do relatorio Flagship Solutions
#def FlagshipSolutions(request):
#    render(request, 'dash_solutions_completo.html')

class VisualizaFundoSolutions(UpdateView):
    template_name = "prototipo_fundo.html"
    model = RmDadoscarteira
    context_object_name = 'fundos_metricas'
    fields = 'all'
    success_url = reverse_lazy("portal_riscos:dash_solutions")





def FlagshipSolutions(request):

    # Queryset Tabela Diaria
    query_carteira = RmDadoscarteira.objetos.filter(grupo='Abertos')
    # Data Mais recente
    dt_recente = str(query_carteira.latest('dtcalculo').dtcalculo)
    # Filtrando queryset para data mais recente
    query_carteira = query_carteira.filter(dtcalculo=dt_recente)


    # Preparando os dados para o grafico de utilizacao de var e stress
    util_var = [round(obj['var_consumolimite'] * 100,2) for obj in query_carteira.values()]
    util_stress = [round(obj['stress_consumolimite'] * 100,2) for obj in query_carteira.values()]

    # Queryset Historico Graficos
    ### Definir um filtro de data
    query_hist = RmHistoricometricas.objetos.filter(grupo='Abertos').filter(dtcalculo__gte='2018-07-11')
    ### Queryset temporario ate dados de retorno e var estarem iguais
    query_data = RmHistoricometricas.objetos.filter(grupo='Abertos').filter(dtcalculo__gte='2018-07-11').filter(info='% VaR')

    ## Data Frames de Saida

    # Data Frame Historico
    df_hist = pd.DataFrame(list(query_hist.values()))
    # Criando uma chave de concateno
    df_hist['concat'] = df_hist['dtcalculo'].astype(str) + df_hist['cdcarteira']
    df_hist['valor'] = round(df_hist['valor'] * 100, 2)



    # Data Frame VaR PL Historico
    df_hist_var = df_hist[df_hist['info']=='% VaR']
    # Data Frame Stress PL Historico
    df_hist_stress = df_hist[df_hist['info']=='% Stress']
    # Data Frame Consumo VaR
    df_hist_var_cons = df_hist[df_hist['info']=='% Utilização Limite VaR']
    # Data Frame Consumo Stress
    df_hist_stress_cons = df_hist[df_hist['info']=='% Utilização Limite Stress']
    # Data Frame de Retorno
    df_hist_ret = df_hist[df_hist['info']=='Retorno']


    # Obtendo todas as datas (removendo duplicados)
    #datas = df_hist.dtcalculo.drop_duplicates(keep='first').reset_index(drop=True)
    datas = pd.DataFrame(list(query_data.values()))
    datas =  datas.dtcalculo.drop_duplicates(keep='first').reset_index(drop=True)

    # Obtendo o nome de todos os fundos (removendo duplicados)
    fundos = list(df_hist.cdcarteira.drop_duplicates(keep='first').reset_index(drop=True))

    # Criando um data frame unico com todas as informacoes a serem utilizadas
    df_hist_saida = pd.DataFrame(columns=['dtcalculo', 'cdcarteira'])

    # Criando um data frame com o numero de linhas igual a fundos * datas
    for fundo in fundos:
        # Data Frame temporario
        df_temp = pd.DataFrame(columns=['dtcalculo', 'cdcarteira'])
        # Copiando as datas
        df_temp['dtcalculo'] = datas
        # Inserindo o nome do fundo
        df_temp['cdcarteira'] = [fundo] * len(datas)

        # Inserindo dados do temp no data frame de saida
        df_hist_saida = df_hist_saida.append(df_temp)


    # Resetando index e criando uma chave de concateno para o dataframe de saida
    df_hist_saida = df_hist_saida.reset_index(drop=True)
    df_hist_saida['concat'] = df_hist_saida['dtcalculo'].astype(str) + df_hist_saida['cdcarteira']

    # Criando coluna de var pl
    df_hist_saida = df_hist_saida.merge(df_hist_var[['concat', 'valor']], on='concat', how='left')
    df_hist_saida = df_hist_saida.rename(columns={'valor': 'var_pl'})

    # Criando coluna de var pl
    df_hist_saida = df_hist_saida.merge(df_hist_stress[['concat', 'valor']], on='concat', how='left')
    df_hist_saida = df_hist_saida.rename(columns={'valor': 'stress_pl'})

    # Criando coluna de consumo var
    df_hist_saida = df_hist_saida.merge(df_hist_var_cons[['concat', 'valor']], on='concat', how='left')
    df_hist_saida = df_hist_saida.rename(columns={'valor': 'var_cons'})

    # Criando coluna de consumo stress
    df_hist_saida = df_hist_saida.merge(df_hist_stress_cons[['concat', 'valor']], on='concat', how='left')
    df_hist_saida = df_hist_saida.rename(columns={'valor': 'stress_cons'})

    # Criando coluna de retorno
    df_hist_saida = df_hist_saida.merge(df_hist_stress_cons[['concat', 'valor']], on='concat', how='left')
    df_hist_saida = df_hist_saida.rename(columns={'valor': 'retorno'})

    # Removendo a coluna concatenado
    df_hist_saida = df_hist_saida.drop('concat', axis=1)

    # Substituindo NaN por none
    df_hist_saida = df_hist_saida.fillna('None')

    # Criando dicionarios de saida
    dict_var_pl_hist = dict()
    dict_stress_pl_hist = dict()
    dict_var_cons_hist = dict()
    dict_stress_cons_hist = dict()

    for fundo in fundos:
        dict_var_pl_hist[fundo] = list(df_hist_saida[df_hist_saida['cdcarteira'] == fundo].var_pl)
        dict_stress_pl_hist[fundo] = list(df_hist_saida[df_hist_saida['cdcarteira'] == fundo].stress_pl)
        dict_var_cons_hist[fundo] = list(df_hist_saida[df_hist_saida['cdcarteira'] == fundo].var_cons)
        dict_stress_cons_hist[fundo] = list(df_hist_saida[df_hist_saida['cdcarteira'] == fundo].stress_cons)


    # Lista contendo todas as datas utilizadas
    lista_datas = list(datas.astype(str))

    # Alertas
    alerta_1 = [70] * len(datas)
    alerta_2 = [85] * len(datas)
    alerta_3 = [100] * len(datas)

    # Flagship
    context ={'query_carteira': query_carteira,
              'fundos': json.dumps(fundos),
              'util_var': json.dumps(util_var),
              'util_stress': json.dumps(util_stress,),
              'dict_var_pl_hist': json.dumps(dict_var_pl_hist, default=dict),
              'dict_stress_pl_hist': json.dumps(dict_stress_pl_hist, default=dict),
              'dict_var_cons_hist': json.dumps(dict_var_cons_hist, default=dict),
              'dict_stress_cons_hist': json.dumps(dict_stress_cons_hist, default=dict),
              'datas_hist': json.dumps(lista_datas, default=str),
              'alerta_1': json.dumps(alerta_1),
              'alerta_2': json.dumps(alerta_2),
              'alerta_3': json.dumps(alerta_3),
    }



    return render(request, 'dash_solutions_completo.html', context)

urls.py

# Importamos a função index() definida no arquivo views.py

from portal_riscos.views import *
from django.urls import path
from django.contrib.auth.views import LoginView


app_name = 'portal_riscos'

# urlpatterns contém a lista de roteamento URLs


urlpatterns = [
    # Dashboard Solutions
    path('', FlagshipSolutions, name='dash_solutions'),
    path('solutions_fundos/<pk>/<cdcarteira>', VisualizaFundoSolutions.as_view(), name='solutions_fundos')


    ]

我要单击并重定向的表的一部分

<a href="{% url 'portal_riscos:solutions_fundos' fundo.dtcalculo fundo.cdcarteira %}"
                                                        class="btn btn-light btn-sm">Atualizar</a>

那是我得到的错误:

Environment:


Request Method: GET
Request URL: http://127.0.0.1:8000/solutions_fundos/2019-01-14/FICFI52865

Django Version: 2.1.2
Python Version: 3.6.1
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'portal_riscos',
 'widget_tweaks',
 'django.contrib.humanize']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback:

File "C:\Users\TBMEPYG\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\core\handlers\exception.py" in inner
  34.             response = get_response(request)

File "C:\Users\TBMEPYG\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\core\handlers\base.py" in _get_response
  126.                 response = self.process_exception_by_middleware(e, request)

File "C:\Users\TBMEPYG\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\core\handlers\base.py" in _get_response
  124.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "C:\Users\TBMEPYG\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\views\generic\base.py" in view
  68.             return self.dispatch(request, *args, **kwargs)

File "C:\Users\TBMEPYG\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\views\generic\base.py" in dispatch
  88.         return handler(request, *args, **kwargs)

File "C:\Users\TBMEPYG\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\views\generic\edit.py" in get
  189.         self.object = self.get_object()

File "C:\Users\TBMEPYG\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\views\generic\detail.py" in get_object
  52.             obj = queryset.get()

File "C:\Users\TBMEPYG\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\db\models\query.py" in get
  403.             (self.model._meta.object_name, num)

Exception Type: MultipleObjectsReturned at /solutions_fundos/2019-01-14/FICFI52865
Exception Value: get() returned more than one RmDadoscarteira -- it returned 21!

任何人对我该怎么办?

谢谢

1 个答案:

答案 0 :(得分:2)

这与拥有两个主键没有特别关系。如果您需要使用基本的pk或slug查找之外的其他方法,而在基于类的视图中获取对象,则需要定义get_object方法。

class VisualizaFundoSolutions(UpdateView):
    ...
    def get_object(self):
        return RmDadoscarteira.objects.get(pk=self.kwargs["pk"], cdcarteira=self.kwargs["cdcarteira"])