Atualizado: 18/01/2024

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 na model dependente, apontando para a model principal. Um exemplo clássico é uma empresa que pode fabricar vários produtos:

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 representa um fabricante e é a entidade principal, enquanto o modelo Product representa um produto e é a entidade dependente.

O campo company em Product é um ForeignKey, que estabelece a relação com Company. O primeiro argumento define a model associada, e o parâmetro on_delete determina o comportamento quando um registro da entidade principal é excluído. Algumas opções disponíveis para on_delete são:

  • models.CASCADE: exclui automaticamente os registros dependentes quando a entidade principal é removida.

  • models.PROTECT: impede a exclusão de um registro da entidade principal se houver registros dependentes vinculados a ele.

  • models.SET_NULL: define o campo como NULL quando o registro associado na entidade principal é removido. Para isso, o campo ForeignKey deve permitir valores NULL.

  • models.SET_DEFAULT: atribui um valor padrão ao campo ForeignKey quando a entidade principal é excluída. O campo deve ter um valor padrão definido.

  • models.DO_NOTHING: 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.

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 está associada a Company por meio do campo company_id, que é criado automaticamente no banco de dados. No entanto, no Django, a relação pode ser acessada diretamente pelo campo company da model 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 (com dois sublinhados) permite filtrar registros da entidade dependente com base em atributos da entidade principal.

Do ponto de vista da model Company, não há um campo explícito que a relacione a Product. No entanto, o Django cria automaticamente um related manager, que permite acessar os produtos associados por meio da sintaxe:

empresa.produto_set

Por padrão, o Django adiciona _set ao nome da model dependente para criar esse acesso.

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 também permite adicionar, modificar e remover objetos da entidade dependente diretamente a partir da entidade principal.

# 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:

  • add(): cria um vínculo entre um objeto dependente e um objeto principal. Na prática, isso corresponde a uma operação UPDATE no banco para definir a chave estrangeira. Se o objeto dependente ainda não existir no banco, bulk=False pode ser passado para garantir que ele seja salvo corretamente antes da vinculação.

  • clear(): remove a relação entre todos os objetos dependentes e a entidade principal. Os objetos continuam existindo no banco, mas a chave estrangeira é definida como NULL. Isso só funciona se ForeignKey(null=True) for permitido na model dependente.

  • remove(): remove a relação entre um único objeto dependente e a entidade principal, sem excluir os registros do banco. Assim como clear(), funciona apenas se o campo ForeignKey permitir NULL.

Política de Privacidade

Copyright © www.programicio.com Todos os direitos reservados

É proibida a reprodução do conteúdo desta página sem autorização prévia do autor.

Contato: programicio@gmail.com