mirror of
https://github.com/django/django.git
synced 2025-07-04 17:59:13 +00:00
schema-evolution: added documentation
git-svn-id: http://code.djangoproject.com/svn/django/branches/schema-evolution@5737 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
dac5af33de
commit
05fb387696
262
docs/schema-evolution.txt
Normal file
262
docs/schema-evolution.txt
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
=====================================
|
||||||
|
Django Schema Evolution Documentation
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
Schema evolution is the function of updating an existing Django generated
|
||||||
|
database schema to a newer/modified version based upon a newer/modified set of
|
||||||
|
Django models.
|
||||||
|
|
||||||
|
This documentation will take you through several common model changes and show
|
||||||
|
you how Django's schema evolution handles them. Each example provides the pre
|
||||||
|
and post model source code, as well as the SQL output.
|
||||||
|
|
||||||
|
Adding / Removing Fields
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
Model: version 1
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
class Poll(models.Model):
|
||||||
|
question = models.CharField(maxlength=200)
|
||||||
|
pub_date = models.DateTimeField('date published')
|
||||||
|
author = models.CharField(maxlength=200)
|
||||||
|
def __str__(self):
|
||||||
|
return self.question
|
||||||
|
|
||||||
|
class Choice(models.Model):
|
||||||
|
poll = models.ForeignKey(Poll)
|
||||||
|
choice = models.CharField(maxlength=200)
|
||||||
|
votes = models.IntegerField()
|
||||||
|
def __str__(self):
|
||||||
|
return self.choice
|
||||||
|
|
||||||
|
Model: version 2
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
class Poll(models.Model):
|
||||||
|
question = models.CharField(maxlength=200)
|
||||||
|
pub_date = models.DateTimeField('date published')
|
||||||
|
author = models.CharField(maxlength=200)
|
||||||
|
def __str__(self):
|
||||||
|
return self.question
|
||||||
|
|
||||||
|
# new fields
|
||||||
|
pub_date2 = models.DateTimeField('date published')
|
||||||
|
|
||||||
|
class Choice(models.Model):
|
||||||
|
poll = models.ForeignKey(Poll)
|
||||||
|
choice = models.CharField(maxlength=200)
|
||||||
|
votes = models.IntegerField()
|
||||||
|
def __str__(self):
|
||||||
|
return self.choice
|
||||||
|
|
||||||
|
# new fields
|
||||||
|
votes2 = models.IntegerField()
|
||||||
|
hasSomething = models.BooleanField()
|
||||||
|
creatorIp = models.IPAddressField()
|
||||||
|
|
||||||
|
Output: v1⇒v2
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
ALTER TABLE `case01_add_field_poll` ADD COLUMN `pub_date2` datetime NOT NULL;
|
||||||
|
ALTER TABLE `case01_add_field_choice` ADD COLUMN `votes2` integer NOT NULL;
|
||||||
|
ALTER TABLE `case01_add_field_choice` ADD COLUMN `hasSomething` bool NOT NULL;
|
||||||
|
ALTER TABLE `case01_add_field_choice` ADD COLUMN `creatorIp` char(15) NOT NULL;
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
Output: v2⇒v1
|
||||||
|
|
||||||
|
-- warning: as the following may cause data loss, it/they must be run manually
|
||||||
|
-- ALTER TABLE `case01_add_field_poll` DROP COLUMN `pub_date2`;
|
||||||
|
-- end warning
|
||||||
|
-- warning: as the following may cause data loss, it/they must be run manually
|
||||||
|
-- ALTER TABLE `case01_add_field_choice` DROP COLUMN `votes2`;
|
||||||
|
-- end warning
|
||||||
|
-- ALTER TABLE `case01_add_field_choice` DROP COLUMN `creatorIp`;
|
||||||
|
-- end warning
|
||||||
|
-- ALTER TABLE `case01_add_field_choice` DROP COLUMN `hasSomething`;
|
||||||
|
-- end warning
|
||||||
|
|
||||||
|
Renaming Fields
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Model: version 1
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
class Poll(models.Model):
|
||||||
|
"""this model originally had fields named pub_date and the_author. you can use
|
||||||
|
either a str or a tuple for the aka value. (tuples are used if you have changed
|
||||||
|
its name more than once)"""
|
||||||
|
question = models.CharField(maxlength=200)
|
||||||
|
pub_date = models.DateTimeField('date published', aka='publish_date')
|
||||||
|
the_author = models.CharField(maxlength=200, aka='the_author')
|
||||||
|
def __str__(self):
|
||||||
|
return self.question
|
||||||
|
|
||||||
|
class Choice(models.Model):
|
||||||
|
poll = models.ForeignKey(Poll)
|
||||||
|
choice = models.CharField(maxlength=200)
|
||||||
|
votes = models.IntegerField(aka='votes')
|
||||||
|
def __str__(self):
|
||||||
|
return self.choice
|
||||||
|
|
||||||
|
Model: version 2
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
class Poll(models.Model):
|
||||||
|
"""this model originally had fields named pub_date and the_author. you can use
|
||||||
|
either a str or a tuple for the aka value. (tuples are used if you have changed
|
||||||
|
its name more than once)"""
|
||||||
|
question = models.CharField(maxlength=200)
|
||||||
|
published_date = models.DateTimeField('date published', aka=('pub_date', 'publish_date'))
|
||||||
|
author = models.CharField(maxlength=200, aka='the_author')
|
||||||
|
def __str__(self):
|
||||||
|
return self.question
|
||||||
|
|
||||||
|
class Choice(models.Model):
|
||||||
|
poll = models.ForeignKey(Poll)
|
||||||
|
choice = models.CharField(maxlength=200)
|
||||||
|
number_of_votes = models.IntegerField(aka='votes')
|
||||||
|
def __str__(self):
|
||||||
|
return self.choice
|
||||||
|
|
||||||
|
Output: v1⇒v2
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
ALTER TABLE `case02_rename_field_poll` CHANGE COLUMN `pub_date` `published_date` datetime NOT NULL;
|
||||||
|
ALTER TABLE `case02_rename_field_poll` CHANGE COLUMN `the_author` `author` varchar(200) NOT NULL;
|
||||||
|
ALTER TABLE `case02_rename_field_choice` CHANGE COLUMN `votes` `number_of_votes` integer NOT NULL;
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
Renaming Models
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Model: version 1
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
class Poll(models.Model):
|
||||||
|
question = models.CharField(maxlength=200)
|
||||||
|
pub_date = models.DateTimeField('date published')
|
||||||
|
author = models.CharField(maxlength=200)
|
||||||
|
def __str__(self):
|
||||||
|
return self.question
|
||||||
|
|
||||||
|
class Choice(models.Model):
|
||||||
|
"the original name for this model was 'Choice'"
|
||||||
|
poll = models.ForeignKey(Poll)
|
||||||
|
choice = models.CharField(maxlength=200)
|
||||||
|
number_of_votes = models.IntegerField()
|
||||||
|
def __str__(self):
|
||||||
|
return self.choice
|
||||||
|
class Meta:
|
||||||
|
aka = ('Choice', 'OtherBadName')
|
||||||
|
|
||||||
|
Model: version 2
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
class Poll(models.Model):
|
||||||
|
question = models.CharField(maxlength=200)
|
||||||
|
pub_date = models.DateTimeField('date published')
|
||||||
|
author = models.CharField(maxlength=200)
|
||||||
|
def __str__(self):
|
||||||
|
return self.question
|
||||||
|
|
||||||
|
class Option(models.Model):
|
||||||
|
"the original name for this model was 'Choice'"
|
||||||
|
poll = models.ForeignKey(Poll)
|
||||||
|
choice = models.CharField(maxlength=200)
|
||||||
|
# show that field name changes work too
|
||||||
|
votes = models.IntegerField(aka='number_of_votes')
|
||||||
|
def __str__(self):
|
||||||
|
return self.choice
|
||||||
|
class Meta:
|
||||||
|
aka = ('Choice', 'BadName')
|
||||||
|
|
||||||
|
Output: v1⇒v2
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
ALTER TABLE `case03_rename_model_choice` RENAME TO `case03_rename_model_option`;
|
||||||
|
ALTER TABLE `case03_rename_model_option` CHANGE COLUMN `number_of_votes` `votes` integer NOT NULL;
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
Changing Flags
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Model: version 1
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
class Poll(models.Model):
|
||||||
|
question = models.CharField(maxlength=200)
|
||||||
|
pub_date = models.DateTimeField('date published')
|
||||||
|
author = models.CharField(maxlength=200)
|
||||||
|
def __str__(self):
|
||||||
|
return self.question
|
||||||
|
|
||||||
|
class Choice(models.Model):
|
||||||
|
"the original name for this model was 'Choice'"
|
||||||
|
poll = models.ForeignKey(Poll)
|
||||||
|
choice = models.CharField(maxlength=200)
|
||||||
|
votes = models.IntegerField()
|
||||||
|
def __str__(self):
|
||||||
|
return self.choice
|
||||||
|
|
||||||
|
class Foo(models.Model):
|
||||||
|
GENDER_CHOICES = (
|
||||||
|
('M', 'Male'),
|
||||||
|
('F', 'Female'),
|
||||||
|
)
|
||||||
|
gender = models.CharField(maxlength=1, choices=GENDER_CHOICES)
|
||||||
|
|
||||||
|
Model: version 2
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
class Poll(models.Model):
|
||||||
|
question = models.CharField(maxlength=100)
|
||||||
|
pub_date = models.DateTimeField('date published')
|
||||||
|
author = models.CharField(maxlength=200)
|
||||||
|
def __str__(self):
|
||||||
|
return self.question
|
||||||
|
|
||||||
|
class Choice(models.Model):
|
||||||
|
"the original name for this model was 'Choice'"
|
||||||
|
poll = models.ForeignKey(Poll)
|
||||||
|
# make sure aka still works with a flag change
|
||||||
|
option = models.CharField(maxlength=400, aka='choice')
|
||||||
|
votes = models.IntegerField()
|
||||||
|
votes2 = models.IntegerField() # make sure column adds still work
|
||||||
|
def __str__(self):
|
||||||
|
return self.choice
|
||||||
|
|
||||||
|
class Foo(models.Model):
|
||||||
|
GENDER_CHOICES = (
|
||||||
|
('M', 'Male'),
|
||||||
|
('F', 'Female'),
|
||||||
|
)
|
||||||
|
gender = models.CharField(maxlength=1, choices=GENDER_CHOICES, db_index=True)
|
||||||
|
gender2 = models.CharField(maxlength=1, null=True, unique=True)
|
||||||
|
|
||||||
|
|
||||||
|
Output: v1⇒v2
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
ALTER TABLE `case04_change_flag_poll` MODIFY COLUMN `question` varchar(100) NOT NULL;
|
||||||
|
ALTER TABLE `case04_change_flag_foo` ADD COLUMN `gender2` varchar(1) NULL UNIQUE;
|
||||||
|
ALTER TABLE `case04_change_flag_choice` MODIFY COLUMN `choice` varchar(400) NOT NULL;
|
||||||
|
ALTER TABLE `case04_change_flag_choice` CHANGE COLUMN `choice` `option` varchar(400) NOT NULL;
|
||||||
|
ALTER TABLE `case04_change_flag_choice` ADD COLUMN `votes2` integer NOT NULL;
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
Conclusion
|
||||||
|
----------
|
||||||
|
|
||||||
|
That's pretty much it. If you can suggest additional examples or test cases you
|
||||||
|
think would be of value, please email me at public@kered.org.
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user