Relacionamento Um-para-Muitos (One-to-Many) no Django
O relacionamento Um-para-Muitos ocorre quando uma entidade principal pode estar associada a várias entidades dependentes. No Django, esse tipo de relacionamento é definido com um campo ForeignKey
from django.db import models
class Company(models.Model):
name = models.CharField(max_length=30)
class Product(models.Model):
company = models.ForeignKey(Company, on_delete=models.CASCADE)
name = models.CharField(max_length=30)
price = models.IntegerField()
Nesse caso, o modelo Company
Product
O campo company
Product
ForeignKey
Company
on_delete
on_delete
: exclui automaticamente os registros dependentes quando a entidade principal é removida.models.CASCADE
: impede a exclusão de um registro da entidade principal se houver registros dependentes vinculados a ele.models.PROTECT
: define o campo como NULL quando o registro associado na entidade principal é removido. Para isso, o campomodels.SET_NULL
deve permitir valores NULL.ForeignKey
: atribui um valor padrão ao campomodels.SET_DEFAULT
quando a entidade principal é excluída. O campo deve ter um valor padrão definido.ForeignKey
: não executa nenhuma ação ao excluir a entidade principal, o que pode levar a violações de integridade referencial no banco de dados.models.DO_NOTHING
Após realizar a migração em um banco de dados SQLite, as seguintes tabelas serão criadas:
CREATE TABLE "hello_company" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"name" varchar(30) NOT NULL
);
CREATE TABLE "hello_product" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"name" varchar(30) NOT NULL,
"price" integer NOT NULL,
"company_id" bigint NOT NULL REFERENCES "hello_company" ("id") DEFERRABLE INITIALLY DEFERRED
);
Operações com Modelos
A model Product
Company
company_id
Product
# Obtendo o ID da empresa associada ao produto
Product.objects.get(id=1).company.id
# Obtendo o nome da empresa associada ao produto
Product.objects.get(id=1).company.name
# Obtendo todos os produtos pertencentes a uma empresa específica
Product.objects.filter(company__name="Apple")
A sintaxe modelo__campo
Do ponto de vista da model Company
Product
empresa.produto_set
Por padrão, o Django adiciona _set
Exemplo de uso:
from .models import Company, Product
apple = Company.objects.get(name="Apple")
# Obtendo todos os produtos da empresa
apple.product_set.all()
# Obtendo a quantidade de produtos da empresa
apple.product_set.count()
# Obtendo produtos cujo nome começa com "iPhone"
apple.product_set.filter(name__startswith="iPhone")
O related manager_set
# Criando uma empresa
apple = Company.objects.create(name="Apple")
# Criando um produto associado a essa empresa
apple.product_set.create(name="iPhone 16", price=6789)
# Criando um produto separadamente e depois associando-o à empresa
ipad = Product(name="iPad", price=3456)
# Para adicionar um produto já existente, bulk=False deve ser especificado
apple.product_set.add(ipad, bulk=False)
# Remove todos os produtos da empresa, mas mantém os produtos no banco
# Isso só funciona se o campo ForeignKey permitir valores NULL
# apple.product_set.clear()
# Remove apenas um produto específico da empresa
# ipad = Product.objects.get(name="iPad")
# apple.product_set.remove(ipad)
Três métodos importantes no related manager_set
: cria um vínculo entre um objeto dependente e um objeto principal. Na prática, isso corresponde a uma operaçãoadd()
no banco para definir a chave estrangeira. Se o objeto dependente ainda não existir no banco,UPDATE
pode ser passado para garantir que ele seja salvo corretamente antes da vinculação.bulk=False
: remove a relação entre todos os objetos dependentes e a entidade principal. Os objetos continuam existindo no banco, mas a chave estrangeira é definida comoclear()
. Isso só funciona seNULL
for permitido na model dependente.ForeignKey(null=True)
: remove a relação entre um único objeto dependente e a entidade principal, sem excluir os registros do banco. Assim comoremove()
, funciona apenas se o campoclear()
permitirForeignKey
.NULL