开发者社区> 问答> 正文

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

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

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

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

展开
收起
一码平川MACHEL 2019-01-23 11:13:58 2109 0
1 条回答
写回答
取消 提交回答
  • 这与具有两个主键没有具体关系。如果需要在基于类的视图中获取对象而不是基本的pk或slug查找,则需要定义get_object方法。

    class VisualizaFundoSolutions(UpdateView):

    ...
    def get_object(self):
        return RmDadoscarteira.objects.get(pk=self.kwargs["pk"], cdcarteira=self.kwargs["cdcarteira"]
    2019-07-17 23:26:34
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载