Relacionamento 1-1, 1-N e N-N com Django

No modelo relacional, existem três tipos de associação entre entidades (tabelas) distintas. Estas relações são utilizadas para mapear como as tabelas interagem entre si e podem ser classificadas de três formas: 1-1 (um para um), 1-N (um para muitos) e N-N (muitos para muitos).

Sendo assim, veremos neste artigo como funciona e como implementar os três tipos de relacionamento no Django.

Relacionamento 1-1

Assim como o próprio nome supõe, o relacionamento 1-1 define que um item de uma entidade só poderá se relacionar com um item de outra entidade. Por exemplo, supondo que temos as entidades Cliente e Endereço que se relacionam de forma 1-1, um cliente só poderá possuir um endereço, que também só pode estar relacionado a um cliente.

Para criar este tipo de relacionamento no Django, no arquivo models.py, precisamos criar um campo que armazene o ID do endereço na entidade cliente do tipo OneToOneField:

class Endereco(models.Model):
        # Definimos seus atributos

class Cliente(models.Model):
        # Definimos seus atributos
      endereco = models.OneToOneField(Endereco, on_delete=models.SET_NULL, null=True)

Desta forma, a classe Cliente irá armazenar o ID do Endereço que cada cliente possuirá. O código completo das classes Endereço e Cliente podem ser vistas abaixo:

class Endereco(models.Model):
    rua = models.CharField(max_length=200, null=False, blank=False)
    numero = models.IntegerField(null=False, blank=False)
    complemento = models.CharField(max_length=200, null=False, blank=False)
    bairro = models.CharField(max_length=50, null=False, blank=False)
    cidade = models.CharField(max_length=100, null=False, blank=False)
    pais = models.CharField(max_length=50, null=False, blank=False)

    def __str__(self):
        return self.rua

class Cliente(models.Model):
    SEXO_CHOICES = (
        ("F", "Feminino"),
        ("M", "Masculino"),
        ("N", "Nenhuma das opções")
    )

    nome = models.CharField(max_length=100, null=False, blank=False)
    data_nascimento = models.DateField(null=False, blank=False)
    email = models.EmailField(null=False, blank=False)
    profissao = models.CharField(max_length=50, null=False, blank=False)
    sexo = models.CharField(max_length=1, choices=SEXO_CHOICES, blank=False, null=False)
    endereco = models.OneToOneField(Endereco, on_delete=models.SET_NULL, null=True)

Após definir as classes acima, precisamos criar a migração para efetivar as alterações no banco de dados e, assim, criar as tabelas no banco de dados. Para isso, utilizamos os comandos abaixo:

python manage.py makemigrations

python manage.py migrate

Isso fará com que as tabelas sejam criadas no banco de dados com a seguinte estrutura:

Relacionamento 1N

O relacionamento 1N determina que um item de uma tabela pode se relacionar com vários itens de uma outra tabela. Continuando o exemplo acima, podemos determinar que um cliente pode realizar diversos pedidos em um restaurante, porém cada pedido só pode possuir um cliente atrelado a ele.

Para criar este relacionamento no Django, utilizamos um campo do tipo ForeignKey, como podemos ver abaixo:

class Pedido(models.Model):
    cliente = models.ForeignKey("Cliente", on_delete=models.CASCADE, related_name='pedidos')

Isso fará com que a tabela Pedidoarmazene o ID do cliente de cada relação. O código completo das classes Pedido e Cliente pode ser visto abaixo:

class Pedido(models.Model):
    STATUS_CHOICES = (
        ("P", "Pedido realizado"),
        ("F", "Fazendo"),
        ("E", "Saiu para entrega"),
    )
    cliente = models.ForeignKey("Cliente", on_delete=models.CASCADE, related_name='pedidos')
    observacoes = models.CharField(max_length=300, null=False, blank=False)
    data_pedido = models.DateTimeField(default=timezone.now)
    valor = models.FloatField(blank=False, null=False)
    status = models.CharField(max_length=1, choices=STATUS_CHOICES, blank=False, null=False)

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

class Cliente(models.Model):
    SEXO_CHOICES = (
        ("F", "Feminino"),
        ("M", "Masculino"),
        ("N", "Nenhuma das opções")
    )

    nome = models.CharField(max_length=100, null=False, blank=False)
    data_nascimento = models.DateField(null=False, blank=False)
    email = models.EmailField(null=False, blank=False)
    profissao = models.CharField(max_length=50, null=False, blank=False)
    sexo = models.CharField(max_length=1, choices=SEXO_CHOICES, blank=False, null=False)
    endereco = models.OneToOneField(Endereco, on_delete=models.SET_NULL, null=True)

Após definir as classes acima, precisamos criar a migração para efetivar as alterações no banco de dados e, assim, criar as tabelas no banco de dados. Para isso, utilizamos os comandos abaixo:

python manage.py makemigrations

python manage.py migrate

Isso fará com que as tabelas sejam criadas no banco de dados com a seguinte estrutura:

Agora, a tabela Pedido armazenará, além de todos os seus atributos, o ID do cliente. Assim, um cliente poderá estar relacionado a vários pedidos, porém um pedido só pode se relacionar com um único cliente.

Relacionamento NN

O relacionamento NN define que um item de uma tabela pode se relacionar com vários itens de uma outra tabela e vice-versa. Por exemplo, podemos determinar que um pedido pode possuir diversos produtos relacionados a ele, assim como um mesmo produto pode estar relacionado a diversos pedidos diferentes.

Para criar este tipo de relacionamento, utilizamos um campo do tipo ManyToManyField, como podemos ver abaixo:

class Produto(models.Model):
    nome = models.CharField(max_length=50, null=False, blank=False)
    descricao = models.CharField(max_length=200, null=False, blank=False)
    valor = models.FloatField(null=False, blank=False)

    def __str__(self):
        return self.nome

class Pedido(models.Model):
    STATUS_CHOICES = (
        ("P", "Pedido realizado"),
        ("F", "Fazendo"),
        ("E", "Saiu para entrega"),
    )
    cliente = models.ForeignKey("Cliente", on_delete=models.CASCADE, related_name='pedidos')
    observacoes = models.CharField(max_length=300, null=False, blank=False)
    data_pedido = models.DateTimeField(default=timezone.now)
    valor = models.FloatField(blank=False, null=False)
    status = models.CharField(max_length=1, choices=STATUS_CHOICES, blank=False, null=False)
    produtos = models.ManyToManyField(Produto)

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

Após definir as classes acima, precisamos criar a migração para efetivar as alterações no banco de dados e, assim, criar as tabelas no banco de dados. Para isso, utilizamos os comandos abaixo:

python manage.py makemigrations

python manage.py migrate

Isso fará com que as tabelas sejam criadas no banco de dados com a seguinte estrutura:

Para este tipo de relacionamento, uma tabela “auxiliar” será criada para armazenar os IDs do pedido e do produto que se relaciona.

A tabela clientes_pedido_produtosirá armazenar o id do pedido e o id do produto que fazem relação. Desta forma, um pedido pode se relacionar com diferentes produtos e um produto pode estar relacionado a diferentes pedidos.

Conclusão

Vimos neste artigo o quão simples é criar os três tipos de relacionamento em bancos de dados relacionais utilizando o ORM do Django. Com isso, agora podemos criar nossas aplicações e estruturar nosso banco de dados da melhor forma possível.

Deixe seu comentário

Professor na TreinaWeb e graduando em Sistemas de Informação pelo Instituto Federal da Bahia. Apaixonado por desenvolvimento web, desktop e mobile desde os 12 anos de idade. Já utilizou todos os sistemas operacionais possíveis, mas hoje se contenta com o OSX instalado em seu notebook Samsung. Até passou em uma peneira do Cruzeiro, mas preferiu estudar Python.

JUNTE-SE A MAIS DE 150.000 PROGRAMADORES