views:

221

answers:

5

I have a simple django app that is using only the admin. This is the model as is now in the server:

from django.db import models

class School(models.Model):    
    school = models.CharField(max_length=200)
    def __unicode__(self):
        return self.school

class Lawyer(models.Model):
    first = models.CharField(max_length=20)
    initial = models.CharField(blank=True, max_length=2)
    last = models.CharField(max_length=20)
    year_graduated = models.IntegerField('Year graduated')
    school = models.CharField(max_length=200)
    school = models.ForeignKey(School)
    class Meta:
        ordering = ('last',)
    def __unicode__(self):
        return self.first

I want to add two new fields, so that the new models.py looks like this:

from django.db import models

class School(models.Model):    
    school = models.CharField(max_length=300)
    def __unicode__(self):
        return self.school
class Lawyer(models.Model):
    firm_url = models.URLField('Bio', max_length=200)
    firm_name = models.CharField('Firm', max_length=100)
    first = models.CharField('First Name', max_length=50)
    last = models.CharField('Last Name', max_length=50)
    year_graduated = models.IntegerField('Year graduated')
    school = models.CharField(max_length=300)
    school = models.ForeignKey(School)
    class Meta:
        ordering = ('?',)
    def __unicode__(self):
        return self.first

Otherwise everything else is the same. Can I just upload this new models.py to the server and expect the application to work the same as before? I also need to clear what is in the database. I am using sqlite3.

I tried to deploy a new app but unfortunately the hosting co is refusing to help. Since I don't need two apps I thought about replacing models.py. This new app works in the django dev server as expected. I would appreciate advice since I will take care of the other outstanding questions after I make this app running. Thanks!

Edit

Thanks for all the answers. Since I want the database clear I will try jcd's solution. So, I will replace the old fields in the models.py

    first = models.CharField(max_length=20)
    initial = models.CharField(blank=True, max_length=2)
    last = models.CharField(max_length=20)
    year_graduated = models.IntegerField('Year graduated')
    school = models.CharField(max_length=200)
    school = models.ForeignKey(School)

with the new fields:

    firm_url = models.URLField('Bio', max_length=200)
    firm_name = models.CharField('Firm', max_length=100)
    first = models.CharField('First Name', max_length=50)
    last = models.CharField('Last Name', max_length=50)
    year_graduated = models.IntegerField('Year graduated')
    school = models.CharField(max_length=300)
    school = models.ForeignKey(School)

to have

from django.db import models

class School(models.Model):    
    school = models.CharField(max_length=200)
    def __unicode__(self):
        return self.school

class Lawyer(models.Model):
    firm_url = models.URLField('Bio', max_length=200)
    firm_name = models.CharField('Firm', max_length=100)
    first = models.CharField('First Name', max_length=50)
    last = models.CharField('Last Name', max_length=50)
    year_graduated = models.IntegerField('Year graduated')
    school = models.CharField(max_length=300)
    school = models.ForeignKey(School)
    class Meta:
        ordering = ('last',)
    def __unicode__(self):
        return self.first

and upload this to the server. Then I will run manage.py syncdb.

And when I open the page I will see the admin as it was before except with new fields.

I assume it is no problem to update the admin.py later to add the new fields:

class LawyerAdmin(admin.ModelAdmin):
    fieldsets = [
        ('Name',   {'fields': ['first', 'last', 'firm_name', 'firm_url']}),
        ('School', {'fields': ['school', 'year_graduated']}),
    ]
    list_display = ('first', 'last', 'school', 'year_graduated', 'firm_name', 'firm_url')
    list_filter = ['year_graduated']
    #search_fields = ['last', 'first']
    search_fields = ['school__school']
    search_fields = ['school__lawyer__last']

Thanks again!

A: 

No, you cannot just replace models.py. You need some kind of schema migration. If you don't use a tool like django south, you'll have to do it manually.

Look at http://www.sqlite.org/lang%5Faltertable.html You can use manage.py sqlall to see which SQL statements you need.

Chris
A: 

Since you're using a sqlite database, and you want to clear the data anyway, this is dead easy. Add your two fields, move your database to a backup location, and re-run manage.py syncdb. It will set up the new database for you. If you need to keep your old data, you are using a more complex database, or you want to manage your change over time, you should look into a schema migration tool like South.

jcdyer
jcd: is it enough to run manage.py syncdb to set the new db? According to this thread http://groups.google.com/group/django-users/browse_frm/thread/c96f717b1fc1dbf4 syncdb does not create new tables?
Zeynel
Syncdb creates new tables, but not new fields within already existing tables.
jcdyer
I am confused. I uploaded my new models.py and ran syncdb and reset the server and I am getting TemplateSyntaxError: no such column: wkw1_lawyer.firm_url So database was not reset. It appears that I will have to start a new project.
Zeynel
So, can you update the answer for future reference? It seems that this does not work in this case; or I did not do what the answer says.
Zeynel
You didn't 'move your database to a backup' - ie replace your existing sqlite file - before running syncdb.
Daniel Roseman
Zeynel
A: 

Run a manage.py sqlall on your project

This will dump the SQL create command

From there, look at the dump for your new columns, and use this to help create your Alter Table statements

Side note, is it kinda weird you have two "school" definitions?

phillc
A: 

Modifying a model on a live Django environment can be a bit of a hassle, depending on your approach.

If you don't mind losing data, a simple manage.py command will do the trick:

python manage.py reset [app name]

If, however, you want to retain the data that's already in the database, you'll have to execute some SQL manually to modify the schema. This can get messy to keep track of if you're not careful.

What I've done previously is to write a SQL statement for every change to any model, and record that somewhere along with the date. I also record the last time the schema was modified for any database (in my case, development, staging, and production). To update any one database to the correct schema, I just ran all the schema change SQL from dates after that particular database was last updated.

ShZ
According to this: http://osdir.com/ml/python.django.user/2006-01/msg00027.html "if you change a model (drop some tables and add some others) sqlreset will not work." Maybe I am misunderstanding how this works?
Zeynel
This only applies when you're dropped or added tables in the database manually. As long as you haven't done so (and I really see no reason why anyone would), you can use `manage.py reset` just fine.
ShZ
A: 

You can use python manage.py sqlall <appname> | grep <column name> to get the SQL definition of a particular column.

Then, you can do something like: ALTER TABLE my_table ADD COLUMN 'column_name' varchar(30);

(In this case, the manage.py line above returned 'column_name varchar(30);')

kcbanner