5

I want to add a column to a model in django. The database I am using is mysql. The earlier database file was;

class Student(models.Model):
    name = models.CharField(max_length=20, validators=[validate_name])
    password = models.CharField(max_length=100)
    email = models.EmailField(max_length=50)


class StudentForm(forms.ModelForm):
    class Meta:
        model = Student
        fields = '__all__'

Now, I added following line too, after password:

repeat_password = models.CharField(max_length=100)

Now I am running following commands:

python manage.py makemigrations
python manage.py migrate

The first line results in 0001_initial.py whose contents are:

class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='Student',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(max_length=20, validators=[ajax.models.validate_name])),
                ('password', models.CharField(max_length=100)),
                ('repeat_password', models.CharField(max_length=100)),
                ('email', models.EmailField(max_length=50)),
            ],
        ),
    ]

But, the second line doesn't add anything to the database:

mysql> desc ajax_student;
+----------+--------------+------+-----+---------+----------------+
| Field    | Type         | Null | Key | Default | Extra          |
+----------+--------------+------+-----+---------+----------------+
| id       | int(11)      | NO   | PRI | NULL    | auto_increment |
| name     | varchar(20)  | NO   |     | NULL    |                |
| password | varchar(100) | NO   |     | NULL    |                |
| email    | varchar(10)  | NO   |     | NULL    |                |
+----------+--------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

I don't know what am I doing wrong? I looked for answer on SO, but none of them worked: Altering database tables in Django

Adding fields to an already existing database

Please help me to solve this.

Edit

Thank you for help every one. When I was adding the field repeat_password, it was asking for a default value:

You are trying to add a non-nullable field 'repeat_password' to student without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
 1) Provide a one-off default now (will be set on all existing rows)
 2) Quit, and let me add a default in models.py
Select an option: 1
Please enter the default value now, as valid Python
The datetime and django.utils.timezone modules are available, so you can do e.g. timezone.now()

So, what I did wrong was chose 1 option and deleted previous migrations. And, then run makemigrations and migrations, just to avoid rewriting default values. That's why I got the error.

But, when I choose second option and then giving a default value, I run above commands, it worked. The thing is I just wanted to save myself from providing a default value. I don't know why while adding extra field it is required, but while creating a field, it's not required.

Community
  • 1
  • 1
learner
  • 4,614
  • 7
  • 54
  • 98
  • Hmm. Try to run django shell on production server and create some test data in production server with extra filed you just added (if you can do this). And after that try to retrive all objects from Student. If there will be any errors? – valex May 16 '16 at 10:01
  • which django version? – thebjorn May 16 '16 at 10:01
  • django version 1.9 – learner May 16 '16 at 10:02
  • 3
    Why do you want to store `repeat_password`?. That's mostly used to avoid users typos so front-end only would be enough – chachan May 16 '16 at 10:06
  • @valex I am getting errors: `"errors": {"repeat_password": ["This field is required."]}` – learner May 16 '16 at 10:07
  • @chachan A valid observation. But, what if jquery is disabled and user enters two different passwords? Also, problem remains the same, what if I want to add other fields to the table? – learner May 16 '16 at 10:09
  • @learner this mean that 'repeat_password' columnt is created successfully and you can just use it. Try to make new student and fill all fields (include 'repeat_password') and then watch django output (easiest way - in admin). – valex May 16 '16 at 10:11
  • You should read https://docs.djangoproject.com/en/1.9/topics/migrations/ until you get to at least `--fake-initial`... (hint: the first migration should be before you add a new field, and be ran with the mentioned flag). – thebjorn May 16 '16 at 10:14
  • 1
    @learner if jQuery is disabled, then you can do the validation without saving on database (on backend side). About your db problem, add `default` parameter: `models.CharField(max_length=100, default='')` – chachan May 16 '16 at 10:25
  • 2
    as @chachan you shouldn't add repeat password to the model but you should add it to the form. And besides you really should be using one of the tried and testing django authentication mechanism. You don't want to save plain text passwords as your model appears to be doing – e4c5 May 16 '16 at 10:55

1 Answers1

2

This is what I do whenever Django does not seem to allow me alter tables. Rename the model, say to Student_1. Then add the new field:

class Student_1(models.Model):
    name = models.CharField(max_length=20, validators=[validate_name])
    password = models.CharField(max_length=100)
    email = models.EmailField(max_length=50)
    repeat_password = models.CharField(max_length=100)

Run python manage.py makemigrations, which will recognise the new table, student_1. Then run python manage.py migrate.

Gathide
  • 899
  • 9
  • 19