开发者社区> 问答> 正文

使用带有2个主键模型基于view UpdateView的类

一码平川MACHEL 2019-01-23 11:13:58 354

我正在构建一个带有两个主键的应用程序(它是一个遗留数据库)。

基本上我想要做的是单击表元素并根据模型上的主键重定向到另一个页面。

我没有找到任何关于如何使用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')
]

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

                                                    class="btn btn-light btn-sm">Atualizar</a>

那是我得到的错误:

Environment:

Request Method: GET
Request URL:

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:UsersTBMEPYGAppDataLocalContinuumAnaconda3libsite-packagesdjangocorehandlersexception.py" in inner

response = get_response(request)

File "C:UsersTBMEPYGAppDataLocalContinuumAnaconda3libsite-packagesdjangocorehandlersbase.py" in _get_response

response = self.process_exception_by_middleware(e, request)

File "C:UsersTBMEPYGAppDataLocalContinuumAnaconda3libsite-packagesdjangocorehandlersbase.py" in _get_response

response = wrapped_callback(request, callback_args, *callback_kwargs)

File "C:UsersTBMEPYGAppDataLocalContinuumAnaconda3libsite-packagesdjangoviewsgenericbase.py" in view

return self.dispatch(request, args, *kwargs)

File "C:UsersTBMEPYGAppDataLocalContinuumAnaconda3libsite-packagesdjangoviewsgenericbase.py" in dispatch

return handler(request, args, *kwargs)

File "C:UsersTBMEPYGAppDataLocalContinuumAnaconda3libsite-packagesdjangoviewsgenericedit.py" in get

self.object = self.get_object()

File "C:UsersTBMEPYGAppDataLocalContinuumAnaconda3libsite-packagesdjangoviewsgenericdetail.py" in get_object

obj = queryset.get()

File "C:UsersTBMEPYGAppDataLocalContinuumAnaconda3libsite-packagesdjangodbmodelsquery.py" in get

(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!

JSON 中间件 数据库 数据格式 Python Perl
分享到
取消 提交回答
全部回答(1)
  • 一码平川MACHEL
    2019-07-17 23:26:34

    这与具有两个主键没有具体关系。如果需要在基于类的视图中获取对象而不是基本的pk或slug查找,则需要定义get_object方法。

    class VisualizaFundoSolutions(UpdateView):

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

集结各类场景实战经验,助你开发运维畅行无忧

推荐文章
相似问题