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

Veja neste artigo como criar relacionamentos 1-1, 1-N e N-N utilizando o ORM do Django.

Fagner Pinheiro 22 de abril de 2019

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.

Django - Fundamentos
Curso de Django - Fundamentos
CONHEÇA O CURSO

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.

Django - Fundamentos
Curso de Django - Fundamentos
CONHEÇA O CURSO

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

Conheça o autor desse artigo

  • Foto Autor Fagner Pinheiro
    Fagner Pinheiro

    Professor na TreinaWeb e graduado 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 desktop. Quando não está trabalhando, é IGL e Awper do time de CS:GO da Treinaweb. Até passou em uma peneira do Cruzeiro, mas preferiu estudar Python.

    Posts desse Autor

Artigos relacionados