5
\$\begingroup\$

I'm beginning with Django and I have a Civil Status project. I created my first models.py in order to get a Form, but I had some advices in order to normalize my database.

I made this process and I would like to know what do you think about this new restructuration.

My old models.py :

from django.db import models
from django.forms import ModelForm
from .countries import CHOIX_PAYS # Importation de la liste des pays
from .sexe import CHOIX_SEXE # Importation de la liste des sexes 
# Create my Form model BirthCertificate
class BirthCertificate(models.Model) :
 nom = models.CharField('Nom', max_length=30, null=False) # Lastname
 prenom = models.CharField('Prénom', max_length=30, null = False) # Firstname
 sexe = models.CharField('Sexe', max_length=1, choices = CHOIX_SEXE) # Choice between 'M' or 'F'
 birthday = models.DateField('Date de naissance', null=False)
 birthhour = models.TimeField('heure de naissance', null=False)
 birthcity = models.CharField('Ville de naissance', max_length = 30, null=False)
 birthcountry = models.ForeignKey(Country)
 nom_pere = models.CharField('Nom père', max_length=30, null=False)
 prenom_pere = models.CharField('Prénom père', max_length=30, null=False)
 birthday_pere = models.DateField('Date de naissance du père', null=False)
 birthcity_pere = models.CharField('Ville de naissance du père', max_length=30, null=False)
 birthcountry_pere = models.CharField('Pays de naissance du père', max_length=2, choices= CHOIX_PAYS)
 job_pere = models.CharField('Profession du père', max_length=30, null=False)
 adress_pere = models.CharField('Adresse du père', max_length=40, null=False)
 ville_pere = models.CharField('Ville du père', max_length=30, null=False)
 zip_pere = models.IntegerField('Code Postal du père', null=False)
 pays_pere = models.CharField('Pays du père', max_length=2, choices= CHOIX_PAYS)
 nom_mere = models.CharField('Nom mère', max_length=30, null=False)
 prenom_mere = models.CharField('Prénom mère', max_length=30, null=False)
 birthday_mere = models.DateField('Date de naissance de la mère', null=False)
 birthcity_mere = models.CharField('Ville de naissance de la mère', max_length=30, null=False)
 birthcountry_mere = models.CharField('Pays de naissance de la mère', max_length=2, choices= CHOIX_PAYS)
 job_mere = models.CharField('Profession de la mère', max_length=30, null=False)
 adress_mere = models.CharField('Adresse de la mère', max_length=40, null=False)
 ville_mere = models.CharField('Ville de la mère', max_length=30, null=False)
 zip_mere = models.IntegerField('Code Postal de la mère', null=False)
 pays_mere = models.CharField('Pays de la mère', max_length=2, choices= CHOIX_PAYS)
 nom_temoin1 = models.CharField('Nom témoin n°1', max_length=30, null=False)
 prenom_temoin1 = models.CharField('Prénom témoin n°1', max_length=30, null=False)
 birthday_temoin1 = models.DateField('Date de naissance du témoin n°1', null=False)
 birthcity_temoin1 = models.CharField('Ville de naissance du témoin n°1', max_length=30, null=False)
 nom_temoin2 = models.CharField('Nom témoin n°2', max_length=30, null=False)
 prenom_temoin2 = models.CharField('Prénom témoin n°2', max_length=30, null=False)
 birthday_temoin2 = models.DateField('Date de naissance du témoin n°2', null=False)
 birthcity_temoin2 = models.CharField('Ville de naissance du témoin n°2', max_length=30, null=False)
 def __str__(self):
 return self.nom

And my new models.py :

from django.db import models
from django.forms import ModelForm
class Country(models.Model):
 code = models.CharField(max_length=3, null=False) # Example : 'FR' - 'US' 
 pays = models.CharField(max_length=50, null=False) # Example : 'France' - 'Etats-Unis'
 def __str__(self):
 return self.code
class Sexe(models.Model):
 code = models.CharField(max_length=1, null=False) # Example : 'M' or 'F'
 name = models.CharField(max_length=7, null=False) # Example : 'Mâle' or 'Femelle'
 def __str__(self):
 return self.code
class Civility(models.Model):
 code = models.CharField(max_length=4, null=False) # 'Mr' - 'Mlle' - 'Mme' - ..
 name = models.CharField(max_length=20, null=False) # 'Monsieur' - 'Mademoiselle' - ..
 def __str__(self):
 return self.code
class Parent1(models.Model):
 civility = models.ForeignKey(Civility)
 lastname = models.CharField(max_length=30, null=False)
 firstname = models.CharField(max_length=30, null=False)
 sexe = models.ForeignKey(Sexe)
 birthday = models.DateField(null=False)
 birthcity = models.CharField(max_length=30, null=False)
 birthcountry = models.ForeignKey(Country)
 job = models.CharField(max_length=30, null=False)
 adress = models.CharField(max_length=30, null=False)
 city = models.CharField(max_length=30, null=False)
 zip = models.IntegerField(max_length=10, null=False)
 country = models.ForeignKey(Country)
 def __str__(self):
 return self.lastname
class Parent2(models.Model):
 civility = models.ForeignKey(Civility)
 lastname = models.CharField(max_length=30, null=False)
 firstname = models.CharField(max_length=30, null=False)
 sexe = models.ForeignKey(Sexe)
 birthday = models.DateField(null=False)
 birthcity = models.CharField(max_length=30, null=False)
 birthcountry = models.ForeignKey(Country)
 job = models.CharField(max_length=30, null=False)
 adress = models.CharField(max_length=30, null=False)
 city = models.CharField(max_length=30, null=False)
 zip = models.IntegerField(max_length=10, null=False)
 country = models.ForeignKey(Country)
 def __str__(self):
 return self.lastname
class BirthCertificate(models.Model):
 lastname = models.CharField(max_length=30, null=False) 
 firstname = models.CharField(max_length=30, null=False)
 sexe = models.ForeignKey(Sexe)
 birthday = models.DateField(null=False)
 birthhour = models.TimeField(null=False)
 birthcity = models.CharField(max_length=30, null=False)
 birthcountry = models.ForeignKey(Country)
 parent1 = models.ForeignKey(Parent1)
 parent2 = models.ForeignKey(Parent2)
 def __str__(self):
 return self.lastname

As you can see, I tried to make a database normalization. I think it's better than the first models.py try.

Do you think that 'JOINs' are smartly written or I need to modify one more time this file ?

200_success
145k22 gold badges190 silver badges478 bronze badges
asked Nov 22, 2016 at 11:37
\$\endgroup\$
6
  • \$\begingroup\$ Those poor people born in Llanfair­pwllgwyngyll­gogery­chwyrn­drobwll­llan­tysilio­gogo­goch. Place names can be longer than 30 characters! \$\endgroup\$ Commented Nov 22, 2016 at 17:54
  • \$\begingroup\$ @Graipher Yeah, but this city can be called : Llanfair Pwllgwyngyll (less than 30 characters ;) ). More than 30 characters for names ? \$\endgroup\$ Commented Nov 22, 2016 at 18:40
  • \$\begingroup\$ Well, there is this guy with a last name with probably about 666 characters... But I think raising them to 100 chars should be more than enough for most people, even with long double last names. \$\endgroup\$ Commented Nov 22, 2016 at 19:01
  • 1
    \$\begingroup\$ I have rolled back the last edit. Please see What to do when someone answers . \$\endgroup\$ Commented Nov 22, 2016 at 19:07
  • \$\begingroup\$ Basically, when an answer has been posted, please don't touch the code in your question. It makes it hard to understand what's going on for any future visitors. Feel free to post a follow-up question if you've incorporated the answers into your code, it should all be explained in the link provided in the previous comment. \$\endgroup\$ Commented Nov 22, 2016 at 19:09

1 Answer 1

6
\$\begingroup\$

Few things here:

1. Parent1 and Parent2 It's not really clear why would you need to have parents in the separate tables while they both represent a person. There is no difference between parent1 and parent2 so they can be stored in the same table.

2. Parent1/Parent2/BirthCertificate

They all share lots of common fields, so you can create an abstract class that will describe them all.

3. Separate table for sex and title

I would not go for this, I don't see much of reasons to create a table with only 2 rows in it.

So, in the end, your code should look like this:

from django.db import models
SEX_CHOICES = (
 ('M', 'Male'),
 ('F', 'Female')
)
TITLE_CHOICES = (
 ('Mr', 'Mister'),
 ('Mrs', 'Missus')
)
class Country(models.Model):
 code = models.CharField(max_length=3, null=False) # Example : 'FR' - 'US'
 pays = models.CharField(max_length=50, null=False) # Example : 'France' - 'Etats-Unis'
 def __str__(self):
 return self.code
class Person(models.Model):
 class Meta:
 abstract = True
 lastname = models.CharField(max_length=30, null=False)
 firstname = models.CharField(max_length=30, null=False)
 sex = models.CharField(max_length=1, choices=SEX_CHOICES)
 birthday = models.DateField(null=False)
 birthhour = models.TimeField(null=False)
 birthcity = models.CharField(max_length=30, null=False)
 birthcountry = models.ForeignKey(Country)
 def __str__(self):
 return self.lastname
class Parent(Person):
 title = models.CharField(choices=TITLE_CHOICES)
 job = models.CharField(max_length=30, null=False)
 adress = models.CharField(max_length=30, null=False)
 city = models.CharField(max_length=30, null=False)
 zip = models.IntegerField(max_length=10, null=False)
 country = models.ForeignKey(Country)
class BirthCertificate(Person):
 parent1 = models.ForeignKey(Parent)
 parent2 = models.ForeignKey(Parent)
answered Nov 22, 2016 at 15:36
\$\endgroup\$
3
  • \$\begingroup\$ Thank you to your post : Some elements in order to answer you. 1) If parents don't live at the same place ? Don't forget that the goal of this project is to get a civil status extract, with lots of specifications about parents/child. 2) I don't really understand why birthhour for example makes part of abstract instead of BirthCertificate (I forgot to modify the name, it's Child). 3) I agree with you \$\endgroup\$ Commented Nov 22, 2016 at 18:46
  • \$\begingroup\$ @Andromedae93 the point is that the parents can be two separate records in the same table, each with their own distinct field values. In general when you have two tables with identical columns, it's a sign something is wrong. The common fields in BirthCertificate can also be stored as a different record in the same table. \$\endgroup\$ Commented Nov 22, 2016 at 19:06
  • \$\begingroup\$ @Mat'sMug Oh ok thank you for precisions ! I will see exactly How I can adapt the Alex's answer to my case. Perhaps some little modifications but the Alex's script is very interesting. \$\endgroup\$ Commented Nov 23, 2016 at 8:18

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.