Contexto e Objetivos do Projeto
A rápida urbanização e o aquecimento do mercado imobiliário transformaram a compra e venda de imóveis usados em um tema de grande interesse. Na cidade de Yuncheng, os dados desse mercado encontram-se fragmentados, dificultando a análise de tendências por parte de compradores e investidores. Métodos tradicionais de gestão, baseados em planilhas estáticas, não oferecem atualizações em tempo real nem interatividade. Para solucionar esse problema, foi desenvolvido um sistema web de visualização de dados que consolida informações do mercado e fornece ferramentas analíticas intuitivas, permitindo o acompanhamento de variações de preços, diferenças regionais e a relação entre oferta e demanda.
Arquitetura e Tecnologias Utilizadas
A aplicação adota uma arquitetura de separação de responsabilidades entre frontend e backend:
- Frontend: Construído com Vue 3, utilizando sua API de Composição para gerenciar o estado reativo e renderizar interfaces dinâmicas. A biblioteca ECharts é integrada para a geração de gráficos interativos, como mapas de calor e séries temporais.
- Backend: Desenvolvido em Python utilizando o framework Django. Através do Django REST Framework (DRF), o sistema expõe endpoints RESTful seguros e eficientes para o consumo de dados.
- Banco de Dados: MySQL é utilizado para o armazenamento relacional, garantindo a integridade, consistência e escalabilidade dos registros imobiliários e de usuários.
Modelagem do Banco de Dados
A estrutura relacional foi projetada para suportar o cadastro de imóveis, controle de acesso e métricas de mercado. Abaixo estão as principais tabelas do sistema:
Tabela de Imóveis (Imoveis)
Armazena as características físicas e comerciais das propriedades disponíveis em Yuncheng.
| Campo | Tipo | Descrição |
|---|---|---|
| id_imovel | VARCHAR(20) | Identificador único (Chave Primária) |
| titulo | VARCHAR(100) | Título do anúncio |
| distrito | VARCHAR(50) | Região ou bairro (ex: Yanhu) |
| endereco | VARCHAR(200) | Localização detalhada |
| preco | DECIMAL(10,2) | Valor de venda (em dezenas de milhares) |
| area | INT | Metragem quadrada |
| tipo_comodo | VARCHAR(20) | Layout (ex: 3 quartos, 2 salas) |
| data_publicacao | DATETIME | Data de inserção no sistema |
| is_vendido | BOOLEAN | Status de negociação |
Tabela de Usuários (Usuarios)
Gerencia as credenciais e permissões de acesso à plataforma.
| Campo | Tipo | Descrição |
|---|---|---|
| id_usuario | VARCHAR(20) | Identificador único (Chave Primária) |
| nome_usuario | VARCHAR(50) | Login de acesso |
| hash_senha | VARCHAR(100) | Crdeencial criptografada |
| papel | VARCHAR(20) | Nível de permissão (ex: Administrador) |
| ultimo_acesso | DATETIME | Registro de login mais recente |
| VARCHAR(100) | Endereço de e-mail vinculado |
Tabela de Análise de Mercado (Analises_Mercado)
Consolida métricas estatísticas derivadas dos dados brutos para alimentar os dashboards.
| Campo | Tipo | Descrição |
|---|---|---|
| id_analise | VARCHAR(20) | Identificador do registro (Chave Primária) |
| distrito | VARCHAR(50) | Área geográfica analisada |
| preco_medio | DECIMAL(10,2) | Média de preços na região |
| crescimento_mensal | DECIMAL(5,2) | Variação percentual no mês |
| data_atualizacao | DATE | Data do processamento estatístico |
| historico_tendencia | JSON | Série temporal de preços (formato JSON) |
Implementação do Backend com Django
Para ilustrar a estrutura do backend, abaixo estão os modelos de dados e as views responsáveis pela autenticação e listagem de imóveis, utilizando o Django REST Framework.
Definição dos Modelos (models.py)
from django.db import models
import uuid
class Imovel(models.Model):
id_imovel = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
titulo = models.CharField(max_length=100)
distrito = models.CharField(max_length=50)
endereco = models.CharField(max_length=200)
preco = models.DecimalField(max_digits=10, decimal_places=2)
area = models.IntegerField()
tipo_comodo = models.CharField(max_length=20)
data_publicacao = models.DateTimeField(auto_now_add=True)
is_vendido = models.BooleanField(default=False)
class Meta:
db_table = 'imoveis'
class Usuario(models.Model):
id_usuario = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
nome_usuario = models.CharField(max_length=50, unique=True)
hash_senha = models.CharField(max_length=100)
papel = models.CharField(max_length=20, default='usuario')
ultimo_acesso = models.DateTimeField(null=True, blank=True)
email = models.EmailField(max_length=100)
class Meta:
db_table = 'usuarios'
Views e Autenticação (views.py)
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response
from rest_framework import status
from django.contrib.auth.hashers import make_password, check_password
from .models import Imovel, Usuario
from .serializers import ImovelSerializer
from datetime import datetime
@api_view(['POST'])
@permission_classes([AllowAny])
def autenticar_usuario(request):
dados = request.data
nome_usuario = dados.get('nome_usuario')
senha = dados.get('senha')
try:
usuario = Usuario.objects.get(nome_usuario=nome_usuario)
if check_password(senha, usuario.hash_senha):
usuario.ultimo_acesso = datetime.now()
usuario.save()
return Response({
'mensagem': 'Login bem-sucedido',
'usuario_id': str(usuario.id_usuario)
}, status=status.HTTP_200_OK)
return Response({'erro': 'Credenciais inválidas'}, status=status.HTTP_401_UNAUTHORIZED)
except Usuario.DoesNotExist:
return Response({'erro': 'Usuário não encontrado'}, status=status.HTTP_404_NOT_FOUND)
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def listar_imoveis_regiao(request, regiao):
imoveis = Imovel.objects.filter(
distrito=regiao,
is_vendido=False
).order_by('-data_publicacao')
serializer = ImovelSerializer(imoveis, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)