Mauricio Kalfelz
Mauricio Kalfelz

Reputation: 79

Foreign key in the database

This is a database for use in Brazil, so the language is Portuguese. Translation:

I use this database to keep track of vehicles in a parking lot with monthly vehicle records.

My problem is one of permutations: Each person could have many vehicles, but each vehicle belongs to only one person.

How do I make sure that, when making an entry, vehicles are only registered in the name of the Person (Pessoa), not the Vehicle (Veiculo)?

I'm using the SqlLite 3 from Django

Foreign key in the database

Models.py

class Pessoa(models.Model):
    nome = models.CharField(max_length=50, blank=False)
    email = models.EmailField(blank=False)
    cpf = models.CharField(max_length=11, unique=True, blank=False)
    endereco = models.CharField(max_length=50)
    numero = models.CharField(max_length=10)
    bairro = models.CharField(max_length=30)
    telefone = models.CharField(max_length=20, blank=False)
    cidade = models.CharField(max_length=20)
    estado = models.CharField(max_length=2, choices=STATE_CHOICES)

class Veiculo(models.Model):
    marca = models.ForeignKey(Marca, on_delete=models.CASCADE, blank=False)
    modelo = models.CharField(max_length=20, blank=False)
    ano = models.CharField(max_length=7)
    placa = models.CharField(max_length=7)
    proprietario = models.ForeignKey(
        Pessoa, on_delete=models.CASCADE, blank=False, )
    cor = models.CharField(max_length=15, blank=False)
    observacoes = models.TextField(blank=False)

class Mensalista(models.Model):
    veiculo = models.ForeignKey(Veiculo, on_delete=models.CASCADE, 
         blank=False)
    inicio = models.DateField(blank=False)
    validade = models.DateField(blank=False)
    proprietario = models.ForeignKey(
        Pessoa, blank=False, on_delete=models.CASCADE)
    valor_mes = models.DecimalField(
        max_digits=6, decimal_places=2, blank=False)
    pago = models.CharField(max_length=15, choices=PAGO_CHOICES)

Upvotes: 0

Views: 87

Answers (2)

ivissani
ivissani

Reputation: 2664

You don't need to store the Person (Pessoa) in the Monthly (Mensalista) model as it is already defined by the vehicle. Having an instance of Mensalista (let's say m) you can access the Vehicles's owner simply by doing m.veiculo.proprietario

If, for some reason (clarity, cleanness or whatever) you want to have a proprietario property on your Mensalista model you could simply add the following:

@property
def proprietario(self):
    return self.veiculo.proprietario

To sum up you could change your Mensalista model to the following:

class Mensalista(models.Model):
    veiculo = models.ForeignKey(Veiculo, on_delete=models.CASCADE, blank=False)
    inicio = models.DateField(blank=False)
    validade = models.DateField(blank=False)
    # The next is not necessary
    # proprietario = models.ForeignKey(Pessoa, blank=False, on_delete=models.CASCADE)
    valor_mes = models.DecimalField(max_digits=6, decimal_places=2, blank=False)
    pago = models.CharField(max_length=15, choices=PAGO_CHOICES)

    @property
    def proprietario(self):
        return self.veiculo.proprietario

To clarify a bit more, the models as you have them are what is called denormalized (you can read more about normalization and denormalization here. Essentially your models are redundant since you have a ForeignKey to Person on both Vehicle and Monthly but you want that the person in Monthly is the same as the person in Vehicle. You can save yourself some trouble by erasing the reference to Person in your Monthly model. In this way you don't need to enforce that both reference to Person coincide as there is only one reference to Person.

Upvotes: 0

cerossi
cerossi

Reputation: 11

I'd suggest you to model this scenario a bit different. As your model Vehicle is already related to your model Person, your attribute proprietario in the model Mensalista is not necessary and this sounds enough to solve your problem.
Notice that once you can get a Person's attributes due the relationship it has with you model Vehicle, it doens't make sense (in my humble opinion and inside this context) to explicitly relate a Person to Mensalita, if you already have an implictly relatioship between them through your model Vehicle:

mensalita = Mensalita.objects.get(pk=this_object_id);
veiculo = mensalita.veiculo;
pessoa = veiculo.proprietario; //You've got your Person without problems.

However, in a context where two people share the same vehicle and this car is eventually parked by some of this drivers, this attribute would be helpful but yet not the best solution for your problem.

I hope I understood correctcly your problem. Please let me know if it's everything clear enough for you. I'll be glad to help you out if I missed something.

Upvotes: 1

Related Questions