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 ?
-
\$\begingroup\$ Those poor people born in Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch. Place names can be longer than 30 characters! \$\endgroup\$Graipher– Graipher2016年11月22日 17:54:57 +00:00Commented 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\$Essex– Essex2016年11月22日 18:40:23 +00:00Commented 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\$Graipher– Graipher2016年11月22日 19:01:47 +00:00Commented Nov 22, 2016 at 19:01
-
1\$\begingroup\$ I have rolled back the last edit. Please see What to do when someone answers . \$\endgroup\$Mast– Mast ♦2016年11月22日 19:07:54 +00:00Commented 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\$Mast– Mast ♦2016年11月22日 19:09:10 +00:00Commented Nov 22, 2016 at 19:09
1 Answer 1
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)
-
\$\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\$Essex– Essex2016年11月22日 18:46:14 +00:00Commented 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\$Mathieu Guindon– Mathieu Guindon2016年11月22日 19:06:28 +00:00Commented 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\$Essex– Essex2016年11月23日 08:18:21 +00:00Commented Nov 23, 2016 at 8:18
Explore related questions
See similar questions with these tags.