Django Models - Foreignkey how to call method within the class by Admin

Asked

Viewed 791 times

0

Good afternoon Galera,

My situation is as follows. I have a nested class structure for a solution and I’m stuck in the following situation: I have these class structure:

class Atividade_estruturas_complementares(models.Model):
    atividades_complementares = models.OneToOneField(Atividade, on_delete=models.PROTECT,
                                                     related_name='atividades_complementares')

    class Meta:
        verbose_name_plural = 'Estruturas Complementares'
        verbose_name = 'Estruturas Complementares'

    def __str__(self):
        return self.atividades_complementares.nome

class Estruturas_complementares(models.Model):
    passivo_id = models.ForeignKey(Passivo,
                                   related_name='complementares',
                                   on_delete=models.CASCADE)
    atividade_complementar = models.ForeignKey(Atividade_estruturas_complementares, on_delete=models.PROTECT,
                                               related_name='atividade_estruturas_complementares')
    comprimento = models.DecimalField(
        'Comprimento', max_digits=10, decimal_places=2, blank=True, null=True, default=None)
    largura_altura = models.DecimalField(
        'Largura / Altura', max_digits=6, decimal_places=2, blank=True, null=True)
    profundidade = models.DecimalField(
        'Profundidade', max_digits=10, decimal_places=2, blank=True, null=True, default=None)
    valor = models.FloatField(default=0.0)  

The Structures_complementary class is registered in admin as inline and assigned to another model called Passive. When saving the liability I would like to update the value field of the Structures_complementary class with a function that makes a specific calculation, I already have the function but do not know how to relate so that the moment I save the passive object I call the function that includes the value in the structures_complementary object. I thought about the possibility of calling a function in default, but did not succeed.

I would like some help to improve this implementation as I am still new to Django and python. In case you need more information I am available.

py.models All classes are in the same models.py, it’s a huge file, but I think the most important one in this case would be the passive class, which is the core of the system, and is represented below. Edit* "ALL CLASSES BELOW"

from django.contrib.gis.db import models
from djgeojson.fields import PointField
from django.contrib.gis.geos import Point
from django.contrib.gis.geos import GEOSGeometry
from django.contrib.gis.gdal import SpatialReference, CoordTransform
from bdg import models as bdg_models
from django.contrib.gis.measure import D
import django_tables2 as tables
from sorl.thumbnail import ImageField
from rest_framework import serializers
from smart_selects.db_fields import ChainedManyToManyField
from django.contrib import messages
from django.shortcuts import render
from .thumbs import ImageWithThumbsField
from sorl_thumbnail_serializer.fields import HyperlinkedSorlImageField
from drf_dynamic_fields import DynamicFieldsMixin
from django.core.validators import FileExtensionValidator
import zipfile
from sicro.models import Sicro


class Unidade(models.Model):
    nome = models.CharField('Nome', max_length=20)
    sigla = models.CharField('Sigla', max_length=5)

    def __str__(self):
        return str(self.sigla)


class Atividade(models.Model):
    codigoSICRO = models.OneToOneField(Sicro, on_delete=models.CASCADE, unique=True, primary_key=True)
    nome = models.CharField('Nome', max_length=200, unique=True)
    descricao = models.TextField('Descrição', max_length=300, blank=True)
    unidadeMedida = models.ForeignKey(Unidade, on_delete=models.DO_NOTHING)

    def __str__(self):
        return self.nome

class Reparo(models.Model):
    nome = models.CharField('Nome', max_length=100, blank=True)
    descricao = models.TextField('Descrição', max_length=300, blank=True)
    atividades = models.ManyToManyField(Atividade)

    def __str__(self):
        return self.nome


class Causa(models.Model):
    # feicao = models.ManyToManyField(Feicao)
    nome = models.CharField(max_length=250, null=True, blank=True)

    def __str__(self):
        return self.nome

    class Meta:
        verbose_name_plural = "Causas"


class Consequencia(models.Model):
    nome = models.CharField(max_length=250, null=True, blank=True)
    valoracao = models.FloatField('Valoração', default=0.0)

    def __str__(self):
        return self.nome

    class Meta:
        verbose_name_plural = "Consequências"
        verbose_name = "Consequência"


class Feicao(models.Model):
    # Opcoes Tipo
    erosao_uniforme = 'Erosão Uniforme'
    erosao_concentrada = 'Erosão Concentrada'
    escorregamento_rotacional = 'Escorregamento Rotacional'
    escorregamento_planar = 'Escorregamento Planar'
    queda_blocos_tombamento = 'Queda de blocos/tombamento'
    corrida = 'Corrida'
    rastejo = 'Rastejo'
    adensamento = 'Adensamento'

    tipos_opcoes = (
        (erosao_uniforme, "Erosão Uniforme"),
        (erosao_concentrada, "Erosão Concentrada"),
        (escorregamento_rotacional, "Escorregamento Rotacional"),
        (escorregamento_planar, "Escorregamento Planar"),
        (queda_blocos_tombamento, "Queda de blocos / tombamento"),
        (corrida, "Corrida"),
        (rastejo, "Rastejo"),
        (adensamento, "Adensamento")
    )
    nome = models.CharField(
        max_length=50, choices=tipos_opcoes, blank=True, null=True)
    causas = models.ManyToManyField(Causa)
    consequencias = models.ManyToManyField(Consequencia)

    def __str__(self):
        return self.nome

    class Meta:
        verbose_name_plural = "Feições"


def calculoReparo(dimensao_comprimento, largura_faixa_dominio_total, dimensao_profundidade, metodos_reparo,
                  siglaEstado):
    comprimento = dimensao_comprimento
    altura_largura = largura_faixa_dominio_total
    profundidade = dimensao_profundidade
    estado = siglaEstado.lower()
    soma = 0.0
    for atividade in metodos_reparo.atividades.all():
        if atividade.unidadeMedida.sigla == 'm':
            valores = Sicro.objects.all().filter(codigo=str(atividade.codigoSICRO)).values(estado)
            valor = list(valores[0].values())
            soma += valor[0] * float(comprimento)
        elif atividade.unidadeMedida.sigla == 'tkm':
            valores = Sicro.objects.all().filter(codigo=str(atividade.codigoSICRO)).values(estado)
            valor = list(valores[0].values())
            pass
        elif atividade.unidadeMedida.sigla == 'un':
            valores = Sicro.objects.all().filter(codigo=str(atividade.codigoSICRO)).values(estado)
            valor = list(valores[0].values())
            soma += valor[0]
        elif atividade.unidadeMedida.sigla == 'm²':
            valores = Sicro.objects.all().filter(codigo=str(atividade.codigoSICRO)).values(estado)
            valor = list(valores[0].values())
            soma += valor[0] * float((comprimento * altura_largura))
        elif atividade.unidadeMedida.sigla == 'm³':
            valores = Sicro.objects.all().filter(codigo=str(atividade.codigoSICRO)).values(estado)
            valor = list(valores[0].values())
            soma += valor[0] * float((comprimento * altura_largura * profundidade))
    return soma


valor_protecao_superficial = 0.0
valor_estruturas_complementares = 0.0


def calculoComplementares(atividade, comprimento, largura_altura, profundidade, passivo):
    estado = passivo.siglaEstado.lower()
    soma = 0.0
    if atividade.unidadeMedida.sigla == 'm':
        valores = Sicro.objects.all().filter(codigo=str(atividade.codigoSICRO)).values(estado)
        valor = list(valores[0].values())
        soma += valor[0] * float(comprimento)
    elif atividade.unidadeMedida.sigla == 'tkm':
        valores = Sicro.objects.all().filter(codigo=str(atividade.codigoSICRO)).values(estado)
        valor = list(valores[0].values())
        pass
    elif atividade.unidadeMedida.sigla == 'un':
        valores = Sicro.objects.all().filter(codigo=str(atividade.codigoSICRO)).values(estado)
        valor = list(valores[0].values())
        soma += valor[0]
    elif atividade.unidadeMedida.sigla == 'm²':
        valores = Sicro.objects.all().filter(codigo=str(atividade.codigoSICRO)).values(estado)
        valor = list(valores[0].values())
        soma += valor[0] * float((comprimento * largura_altura))
    elif atividade.unidadeMedida.sigla == 'm³':
        valores = Sicro.objects.all().filter(codigo=str(atividade.codigoSICRO)).values(estado)
        valor = list(valores[0].values())
        soma += valor[0] * float((comprimento * largura_altura * profundidade))
    elif atividade.unidadeMedida.sigla == 't':
        valores = Sicro.objects.all().filter(codigo=str(atividade.codigoSICRO)).values(estado)
        valor = list(valores[0].values())
        soma += valor[0] * float((comprimento))
    return soma


def calculoSuperficial(atividade, comprimento, largura_altura, profundidade, passivo):
    estado = passivo.siglaEstado.lower()
    soma = 0.0
    if atividade.unidadeMedida.sigla == 'm':
        valores = Sicro.objects.all().filter(codigo=str(atividade.codigoSICRO)).values(estado)
        valor = list(valores[0].values())
        soma += valor[0] * float(comprimento)
    elif atividade.unidadeMedida.sigla == 'un':
        valores = Sicro.objects.all().filter(codigo=str(atividade.codigoSICRO)).values(estado)
        valor = list(valores[0].values())
        soma += valor[0]
    elif atividade.unidadeMedida.sigla == 'm²':
        valores = Sicro.objects.all().filter(codigo=str(atividade.codigoSICRO)).values(estado)
        valor = list(valores[0].values())
        soma += valor[0] * float((comprimento * largura_altura))
    elif atividade.unidadeMedida.sigla == 'm³':
        valores = Sicro.objects.all().filter(codigo=str(atividade.codigoSICRO)).values(estado)
        valor = list(valores[0].values())
        soma += valor[0] * float((comprimento * largura_altura * profundidade))
    return soma


class Abrangencia(models.Model):
    atributo = models.CharField('Atributo', blank=True,
                                null=True, max_length=20)
    valoracao = models.FloatField('Valoração', default=1.0)

    descricao = models.TextField()

    class Meta:
        verbose_name_plural = 'Abrangências'
        verbose_name = 'Abrangência'

    def __str__(self):
        return self.atributo


class Magnitude(models.Model):
    atributo = models.CharField('Atributo', blank=True,
                                null=True, max_length=20)
    valoracao = models.FloatField('Valoração', default=1.0)

    erosao = models.TextField('Erosão', )
    movimento_massa = models.TextField('Movimentos de massa', )
    adensamento = models.TextField('Adensamento', )

    class Meta:
        verbose_name_plural = 'Magnitudes'
        verbose_name = 'Magnitude'

    def __str__(self):
        return self.atributo


class Interferencia(models.Model):
    descricao = models.CharField('Descrição', blank=True,
                                 null=True, max_length=100)
    valoracao = models.FloatField('Valoração', default=1.0)

    class Meta:
        verbose_name_plural = 'Interferências'
        verbose_name = 'Interferência'

    def __str__(self):
        return self.descricao


def calculaGrandeza(abrangencia, magnitude):
    grandeza = (abrangencia.valoracao + magnitude.valoracao) / 2
    return grandeza


def calculaRisco(risco_ao_usuario, provaveis_consequencias):
    risco = 0.0
    consequencias = provaveis_consequencias.all()
    for consequencia in consequencias:
        risco += consequencia.valoracao
    risco = risco * risco_ao_usuario
    return risco

def calculaIndicePrioridade(self):
    g = calculaGrandeza(self.abrangencia, self.magnitude)
    # teste = self.provaveis_consequencias.all()
    r = calculaRisco(self.risco_ao_usuario, self.provaveis_consequencias)
    it = self.interferencia.valoracao
    ip = (0.55 * r) + (0.1 * g) + (0.1 * it)
    return ip
class Passivo(models.Model):
    # Opcoes relevo
    plano = 'PL'
    ondulado = 'ON'
    montanhoso = 'MO'

    relevo_opcoes = (
        (plano, 'Plano'),
        (ondulado, 'Ondulado'),
        (montanhoso, 'Montanhoso')
    )

    # Opcoes terceira_faixa_localizacao
    lado_direito = 'LD'
    lado_esquerdo = 'LE'
    inexistente = 'IN'
    ambos = 'AM'

    terceira_faixa_localizacao_opcoes = (
        (lado_direito, 'Lado Direito'),
        (lado_esquerdo, 'Lado Esquerdo'),
        (inexistente, 'Inexistente')
    )

    # opcoes pavimento
    pavimento_asfautico = 'PA'
    pavimento_concreto = 'PC'
    nao_pavimentado = 'NP'
    outro_pavimento = 'OP'
    pista_rolamento_pavimento_opcoes = (
        (pavimento_asfautico, 'Pavimento Asfaltico'),
        (pavimento_concreto, 'Pavimento Concreto'),
        (nao_pavimentado, 'Nao Pavimentado'),
        (outro_pavimento, 'Outro Pavimento')
    )

    # opcoes lado
    direito = 'D'
    esquerdo = 'E'
    indefinido = 'I'
    ambos = 'A'

    lado_opcoes = (
        (direito, 'Direito'),
        (esquerdo, 'Esquerdo'),
        (indefinido, 'Indefinido'),
        (ambos, 'Lado Direito e Esquerdo')
    )

    # Opcoes Perigo e sua valoração
    sem_perigo = 0.0
    perigo_potencial = 0.5
    perigo_iminente = 1.0
    perigo_instalado = 1.5

    nivel_gravidade_escolhas = (
        (sem_perigo, 'Sem Perigo'),
        (perigo_potencial, 'Perigo Potencial'),
        (perigo_iminente, 'Perigo Iminente'),
        (perigo_instalado, 'Perigo Instalado')
    )

    # MODELO
    data_inspecao = models.DateField('Data de inspeção', auto_now=False)

    # LOCALIZAÇÃO
    latitude = models.DecimalField(
        'Latitude', max_digits=14, decimal_places=10, blank=False, null=True)
    longitude = models.DecimalField(
        'Longitude', max_digits=14, decimal_places=10, blank=False, null=True)
    km_ponto = models.DecimalField(
        'Km', blank=True, null=True, max_digits=7, decimal_places=2)
    lado = models.CharField('Lado de Ocorrência', blank=True,
                            null=True, max_length=1, choices=lado_opcoes)
    distancia_ao_eixo = models.CharField(
        'Distância do Passivo ao Eixo', max_length=50, blank=True, null=True)
    area_ocorrencia_faixa_dominio = models.NullBooleanField(
        blank=True, null=True, default=False)
    area_ocorrencia_area_adjacente = models.NullBooleanField(
        blank=True, null=True, default=False)

    # CARACTERIZAÇÃO DO SEGMENTO RODOVIÁRIO
    largura_faixa_dominio_esquerda = models.DecimalField(
        max_digits=6, decimal_places=2, blank=True, null=True)
    largura_faixa_dominio_direita = models.DecimalField(
        max_digits=6, decimal_places=2, blank=True, null=True)
    pista_rolamento_numero = models.IntegerField(
        'nº de pistas de rolamento', blank=True, null=True)
    pista_rolamento_pavimento = models.CharField(max_length=50,
                                                 choices=pista_rolamento_pavimento_opcoes,
                                                 default=pavimento_asfautico)
    acostamento_presenca = models.NullBooleanField(
        'Acostamento', default=False)
    terceira_faixa_localizacao = models.CharField('Terceira Faixa / Localização', max_length=50,
                                                  choices=terceira_faixa_localizacao_opcoes,
                                                  default=inexistente)
    relevo = models.CharField(max_length=50,
                              choices=relevo_opcoes,
                              default=plano)

    # CARACTERIZAÇÃO DO PASSIVO
    feicao = models.ForeignKey(Feicao, on_delete=models.DO_NOTHING)
    risco_ao_usuario = models.FloatField(choices=nivel_gravidade_escolhas, default=None, blank=True, null=True)
    risco_ao_patrimonio = models.FloatField(choices=nivel_gravidade_escolhas, default=None, blank=True, null=True)
    risco_ao_ambiente = models.FloatField(choices=nivel_gravidade_escolhas, default=None, blank=True, null=True)
    possiveis_causas = ChainedManyToManyField(
        Causa,
        horizontal=True,
        verbose_name='Possiveis Causas',
        chained_field="feicao",
        chained_model_field="feicao",
    )
    provaveis_consequencias = ChainedManyToManyField(
        Consequencia,
        horizontal=True,
        verbose_name='Provaveis Consequências',
        chained_field="feicao",
        chained_model_field="feicao",
    )
    abrangencia = models.ForeignKey(Abrangencia, on_delete=models.CASCADE, null=True)
    magnitude = models.ForeignKey(Magnitude, on_delete=models.CASCADE, null=True)
    interferencia = models.ForeignKey(Interferencia, on_delete=models.CASCADE, null=True)
    localizacao = models.PointField(blank=True, null=True)
    modelo_3d = models.FileField(upload_to='models/', blank=True, null=True,
                                 validators=[FileExtensionValidator(allowed_extensions=['zip'])])
    modelo_3d_path = models.CharField(
        'Endereço do arquivo 3d (cloud.js)', max_length=128, blank=True, null=True)
    croqui = models.ImageField('Croqui', blank=True, null=True)
    observacoes = models.TextField('Observações', blank=True, null=True)
    segmento_rodoviario = models.ForeignKey(
        bdg_models.Rodovia, on_delete=models.CASCADE, blank=True, null=True, unique=False,
        verbose_name='Segmento Rodoviário')
    estado = models.CharField('Estado', blank=True, null=True, max_length=50)
    siglaEstado = models.CharField('Sigla', blank=True, null=True, max_length=2)
    municipio = models.CharField(
        'Município', blank=True, null=True, max_length=50)

    # MÉTODOS DE REPARO
    metodos_reparo = models.ForeignKey(Reparo, on_delete=models.CASCADE, null=True)
    dimensao_comprimento = models.DecimalField(
        'Comprimento', max_digits=10, decimal_places=2, blank=True, null=True, default=None)
    largura_faixa_dominio_total = models.DecimalField(
        'Largura / Altura', max_digits=6, decimal_places=2, blank=True, null=True)
    dimensao_profundidade = models.DecimalField(
        'Profundidade', max_digits=10, decimal_places=2, blank=True, null=True, default=None)
    valor_total_reparo = models.FloatField('valor reparo', default=0.0)
    indice_prioridade = models.FloatField('Indice de Prioridade', default=0.0)

    def save(self, *args, **kwargs):
        if ((self.latitude != None) & (self.longitude != None)):
            coordinate = 'POINT(' + str(self.longitude) + \
                         ' ' + str(self.latitude) + ')'
            try:
                RODOVIA_FROM_LOCALIZACAO_ID = bdg_models.Rodovia.objects.filter(
                    geom__distance_lt=(GEOSGeometry(coordinate), D(m=5000)))[0]
                self.segmento_rodoviario = RODOVIA_FROM_LOCALIZACAO_ID
            except RuntimeError:
                print('Something wrong with input points')

                raise
            try:
                ESTADO_FROM_LOCALIZACAO_ID = bdg_models.Estado.objects.filter(
                    geom__intersects=(GEOSGeometry(coordinate)))
                self.estado = ESTADO_FROM_LOCALIZACAO_ID[0].nome
                self.siglaEstado = ESTADO_FROM_LOCALIZACAO_ID[0].sigla
                self.valor_total_reparo = calculoReparo(self.dimensao_comprimento, self.largura_faixa_dominio_total,
                                                        self.dimensao_profundidade, self.metodos_reparo,
                                                        self.siglaEstado)
                self.indice_prioridade = calculaIndicePrioridade(self)
                protecao_superficial = Protecao_superficial.objects.all()
                protecao_superficial
                for atividade in protecao_superficial:
                    print(atividade)


            except RuntimeError:
                print('Something wrong with input points')

                raise
            try:
                MUNICIPIO_FROM_LOCALIZACAO_ID = bdg_models.Municipio.objects.filter(
                    geom__intersects=(GEOSGeometry(coordinate)))
                self.municipio = MUNICIPIO_FROM_LOCALIZACAO_ID[0].nome
            except RuntimeError:
                print('Something wrong with input points')
                raise
            self.localizacao = GEOSGeometry(coordinate)
            if self.modelo_3d:
                try:
                    targetdir = 'static/models'
                    targetname = '/' + str(self.id)
                    self.modelo_3d_path = '/models' + targetname + '/cloud.js'
                    with zipfile.ZipFile(self.modelo_3d, "r") as zip_ref:
                        zip_ref.extractall(targetdir + targetname)
                except RuntimeError:
                    print('Something wrong with the unziping')
                    raise
            else:
                pass
        else:
            print('Preencher coordenadas')

        super(Passivo, self).save(*args, **kwargs)

    class Meta:
        verbose_name_plural = "Passivos"

    # def all_images(self):
    #     # code to determine which image to show. The First in this case.
    #     return self.fotos

    def __str__(self):
        return str(self.id)


# PROTEÇÃO SUPERFICIAL
class Atividade_protecao_superficial(models.Model):
    atividade_superficial = models.ForeignKey(Atividade, on_delete=models.PROTECT,
                                                related_name='atividade_superficial', primary_key=True)

    class Meta:
        verbose_name_plural = 'Atividades Superficiais'
        verbose_name = 'Atividade Superficial'

    def __str__(self):
        return self.atividade_superficial.nome


class Protecao_superficial(models.Model):
    passivo_id = models.ForeignKey(Passivo,
                                   related_name='superficial',
                                   on_delete=models.CASCADE)
    atividade_superficial = models.ForeignKey(Atividade_protecao_superficial, on_delete=models.PROTECT,
                                              related_name='atividade_protecao_superficial')
    comprimento = models.DecimalField(
        'Comprimento', max_digits=10, decimal_places=2, blank=True, null=True, default=None)
    largura_altura = models.DecimalField(
        'Largura / Altura', max_digits=6, decimal_places=2, blank=True, null=True)
    profundidade = models.DecimalField(
        'Profundidade', max_digits=10, decimal_places=2, blank=True, null=True, default=None)
    valor = models.FloatField(default=0.0)

    class Meta:
        verbose_name_plural = 'Proteções Superficiais'
        verbose_name = 'Proteção Superficial'
        unique_together = (('passivo_id', 'atividade_superficial'),)

    def __str__(self):
        return ''


# ESTRUTURAS COMPLEMENTARES

class Atividade_estruturas_complementares(models.Model):
    atividade_complementar = models.ForeignKey(Atividade, on_delete=models.PROTECT,
                                                     related_name='atividade_complementar', primary_key=True)

    class Meta:
        verbose_name_plural = 'Atividades Complementares'
        verbose_name = 'Atividade Complementar'

    def __str__(self):
        return self.atividade_complementar.nome


class Estruturas_complementares(models.Model):
    passivo_id = models.ForeignKey(Passivo,
                                   related_name='complementares',
                                   on_delete=models.CASCADE)
    atividade_complementar = models.ForeignKey(Atividade_estruturas_complementares, on_delete=models.PROTECT,
                                               related_name='atividade_estruturas_complementares')
    comprimento = models.DecimalField(
        'Comprimento', max_digits=10, decimal_places=2, blank=True, null=True, default=None)
    largura_altura = models.DecimalField(
        'Largura / Altura', max_digits=6, decimal_places=2, blank=True, null=True)
    profundidade = models.DecimalField(
        'Profundidade', max_digits=10, decimal_places=2, blank=True, null=True, default=None)
    valor = models.FloatField(default=0.0)

    class Meta:
        verbose_name = 'Estrutura Complementar'
        verbose_name_plural = 'Estruturas Complementares'
        unique_together = (('passivo_id', 'atividade_complementar'),)

    def __str__(self):
        return ''


class Foto(models.Model):
    property = models.ForeignKey(Passivo,
                                 related_name='fotos',
                                 on_delete=models.CASCADE, null=True)  # , default='no-img.png')
    image = ImageWithThumbsField(sizes=((100, 130), (200, 260)))
    descricao = models.CharField(
        'Descrição', max_length=300, blank=True, null=True, default=None)

    class Meta:
        verbose_name_plural = "Fotos"

        def __str__(self):
            return ("Fotos do passivo"

admin py.

from django.contrib import admin
from django.apps import apps
from .models import Feicao, Passivo, Causa, Consequencia, Foto, Local, Unidade, Atividade, Reparo, \
    Estruturas_complementares, Protecao_superficial, Atividade_estruturas_complementares, \
    Atividade_protecao_superficial, Abrangencia, Magnitude, Interferencia
from sorl.thumbnail.admin import AdminImageMixin
import nested_admin
from leaflet.admin import LeafletGeoAdmin
from jet.admin import CompactInline


class ReparoInline(nested_admin.NestedTabularInline):
    model = Reparo
    extra = 0


class FotoInline(AdminImageMixin, nested_admin.NestedTabularInline):
    model = Foto
    extra = 0


class LocalInline(nested_admin.NestedTabularInline):
    model = Local
    extra = 0


class Estruturas_complementares_inline(nested_admin.NestedTabularInline):
    model = Estruturas_complementares
    readonly_fields = ('valor',)
    extra = 0

class Protecao_superficial_inline(nested_admin.NestedTabularInline):
    model = Protecao_superficial
    readonly_fields =('valor',)
    extra = 0

class PassivoAdmin(nested_admin.NestedModelAdmin, LeafletGeoAdmin):
    model = Passivo
    list_filter = ['data_inspecao']
    autocomplete_fields = ['metodos_reparo', 'possiveis_causas', 'provaveis_consequencias',]
    list_display = ('id', 'segmento_rodoviario', 'km_ponto',
                    'lado', 'latitude', 'longitude', 'estado')
    readonly_fields = ('segmento_rodoviario', 'indice_prioridade', 'estado',
                       'municipio', 'modelo_3d_path','valor_total_reparo')
    fieldsets = (
        (None, {
            'fields': ('data_inspecao',)
        }),
        ('Localização', {
            'fields': ('latitude', 'longitude', 'km_ponto', 'lado', 'distancia_ao_eixo', 'area_ocorrencia_faixa_dominio', 'area_ocorrencia_area_adjacente')
        }),
        ('Mapa', {
            'fields': ('localizacao',)
        }),
        ('Segmento Rodoviário', {
            'classes': ('collapse',),
            'fields': ('largura_faixa_dominio_esquerda', 'largura_faixa_dominio_direita', 'pista_rolamento_numero', 'pista_rolamento_pavimento', 'acostamento_presenca', 'terceira_faixa_localizacao', 'relevo')
        }),
        ('Caracterização', {
            'classes': ('collapse',),
            'fields': ('feicao', 'risco_ao_usuario', 'risco_ao_patrimonio', 'risco_ao_ambiente', 'possiveis_causas', 'provaveis_consequencias', 'abrangencia', 'magnitude', 'interferencia','indice_prioridade', 'modelo_3d', 'modelo_3d_path', 'croqui', 'observacoes', 'segmento_rodoviario', 'estado', 'municipio')
        }),
        ('Métodos de Reparo', {
            'classes': ('collapse',),
            'fields': ('metodos_reparo', 'dimensao_comprimento', 'largura_faixa_dominio_total', 'dimensao_profundidade', 'valor_total_reparo')
        }),
    )
    inlines = [Estruturas_complementares_inline, Protecao_superficial_inline, FotoInline, LocalInline]

Edit:

I started testing yesterday the following way:

def calcula_valor(sender, **kwargs):
    if kwargs['created']:
        atividade = Passivo.objects.update(id=kwargs['instance'])
        atividade.valor = calculoSuperficial(atividade.atividade_superficial,atividade.comprimento,atividade.largura_altura,atividade.profundidade, atividade.passivo_id)
    elif kwargs['update_fields']:
        atividade = Protecao_superficial.objects.create(passivo_id=kwargs['instance'])
        atividade.valor = calculoSuperficial(atividade.atividade_superficial,atividade.comprimento,atividade.largura_altura,atividade.profundidade, atividade.passivo_id)
    else:
        for atividade in Protecao_superficial.objects.all().filter(passivo_id_id=kwargs['instance']):
            valor = calculoSuperficial(atividade.atividade_superficial,atividade.comprimento,atividade.largura_altura,atividade.profundidade, atividade.passivo_id)
            atividade.valor = valor
            atividade.save() # Edit2: como descrito era apenas o .save() e a solução funcionou
post_save.connect(calcula_valor, sender=Passivo)

It almost worked, I can access all the objects I need, I do the calculations, but when saving the changes are not being saved, as far as I could see, I am not able to attach the information to the context.

  • Hello alive take a look here For example, if it becomes too complex, share more details about your models.py and admin.py with what you’ve done so far. Another suggestion, or plan B would be to create a Trigger, not recommend the use of triggers in some cases cause performance problems, if it is a table with little data in this particular case may be a solution, i.e. when recording into Liability Trigger is triggered and performs the operation you want.

  • Hi, improved. But you can put pf the objects of the models that are in admin, so it’s just copy and Paste and I have your scenario

  • I’ll do it now

2 answers

1


To get what I needed, I don’t know if it was the best solution, but I managed to achieve it in the following way.

def calcula_valor(sender, **kwargs):
    if kwargs['created']:
        atividade = Passivo.objects.update(id=kwargs['instance'])
        atividade.valor = calculoSuperficial(atividade.atividade_superficial,atividade.comprimento,atividade.largura_altura,atividade.profundidade, atividade.passivo_id)
    elif kwargs['update_fields']:
        atividade = Protecao_superficial.objects.create(passivo_id=kwargs['instance'])
        atividade.valor = calculoSuperficial(atividade.atividade_superficial,atividade.comprimento,atividade.largura_altura,atividade.profundidade, atividade.passivo_id)
    else:
        for atividade in Protecao_superficial.objects.all().filter(passivo_id_id=kwargs['instance']):
            valor = calculoSuperficial(atividade.atividade_superficial,atividade.comprimento,atividade.largura_altura,atividade.profundidade, atividade.passivo_id)
            atividade.valor = valor
            atividade.save()
post_save.connect(calcula_valor, sender=Passivo)

0

Hi viva I realized after your sharing that your app is really big and there is a lot to install to help you with a fully functional example. As for what you want, part of what you need has already been implemented, namely the save in the Passive model. What you need is just to add a line of code, but as you defined Unique as 2 FK, and with lots of lines of code, I wonder if you have access to the attribute activity in the Scope of the passive object?

In my view this will be a possible solution, (since it was not impossible to test your code), in which the passivo_id served as id of the object itself, all right and remove the second, otherwise you will need to get the ID of the FK activity_complementary to filter through this too.

Only with passive_id

Estruturas_complementares.objects.filter(passivo_id=self.id).update(largura_altura=12273)

With passive_id and complementary activity_complement

Estruturas_complementares.objects.filter(passivo_id=self.id).filter(atividade_complementar=self.???).update(largura_altura=12273)
  • Ernesto, when you say remove the second one, I was confused about which piece of code you’re referring to, would that be the one? passivo_id = models.Foreignkey(Passive, related_name='superficial', on_delete=models.CASCADE) superficial activity = models.Foreignkey(Activity_proteco_superficial, on_delete=models.PROTECT, related_name='activity_proteco_superficial') Thanks Ernesto, I will do the tests here and give feedback again.

  • 1

    Do not touch your model, do not use the second "filter", or my first example, to put in your SAVE.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.