Database Error on Dotcloud, Postgres Django - django

I'm deploying my django app with Dotcloud.
I use Postgres as DB.
I had a new model to my app, and I wanted to flush and syncdb the db. Everything works find when I do it. My new model, named 'Competition' appears in my admin.
The problem is that an other model, Match, has a ForeignKey with the model Competition. And when I go to 'Matchs' in my admin, I get this error:
DatabaseError at /admin/myproject/match/
column myproject_match.competition_id does not exist
LINE 1: ...team_challenger_id", "sportdub_match"."sport_id", "sportdub_...
Any idea on why the syncdb didn't make it work find?
Thank you for your help.
EDIT: My two models
class Competition(models.Model):
name = models.CharField(max_length=256)
comp_pic = models.ImageField(upload_to="comp_pics/")
def __unicode__(self):
return self.name
class Match(models.Model):
team_host = models.ForeignKey(Team, related_name='host_matches')
team_challenger = models.ForeignKey(Team, related_name= 'challenger_matches')
sport = models.ForeignKey(Sport)
competition = models.ForeignKey(Competition)

manage.py syncdb will only create missing tables. If a table already exists, but with an invalid definition, it will not be updated. This is very probably the problem that you are experiencing.
There are at least three ways to solve the problem.
The easy way: use manage.py reset to effectively drop+recreate all the tables. Easy, but of course you will lose the data.
The lazy way: install django_extensions and use manage.py sqldiff. It will show you the difference between the current structure of the database, and the expected structure. sqldiff will nicely show you SQL statements which can update the existing database to conform with your models. You can then execute those statements in a SQL shell.
The clean way: use a migrations framework like south to handle database schema updates. Of course, if you are early in the development, this is overkill (you do not want to write database migrations each time you add/change/remove a field while you're doing local development!) but if your project will have a longer life span, I definitely recommend checking out south.

Related

Django max_length where there should not be a max_length

I do not have a deep understanding of Django, anyway not deep enough to overcome a problem that turns up in my application.
In models.py I have a.o. the following definitions:
class Relatiedata(models.Model):
...
getuigen = models.TextField(blank=True, null=True)
...
class Meta:
db_table = 'relatiedata'
Relatiedata.objects = Relatiedata.objects.using('genealogie')
So in the database genealogie, which is not the default database, I have a table relatiedata with a column getuigen that has to contain a text string without a limitation on the length.
Further, I have a user form for mutating records of this table. As usual, the form is populated from a Relatiedata.object and the returned form results in another Relatiedata.object which is saved, thereby updating the database. This works (almost) perfect.
The problem is that in my form it turns out to be impossible to enter a string of length above 600 in the textarea for getuigen. Longer strings are simply cut off. There seems to be sort of a form validation for the length of that field, despite the fact that there is no such limit in the models, nor in the database, nor in the migration files.
This value of 600 comes from earlier, abandoned, implementations of the model, where originally I had a CharField with max_length 600 instead of a TextField.
All remarks are highly welcome.
EDIT
Some additional information. As it is now, the models were created from the already existing database, which is a simple sqlite database with some tables, no relations between the tables. The table relatiedata is a simple table with some textual columns, a little bit too large to show here. Makemigrations and migrate were of course used after the models were constructed, and at the moment makemigrations does not find anything to migrate.
Even worse: when I change the definition:
getuigen = models.CharField(max_length=2000, blank=True, null=True),
makemigrations shows this change and migrate solves it, but it is still impossible to use a string of more than 600 characters in the form. With less, it is OK.
Finally, I can change the value of the field getuigen to strings with more than 600 characters by using SQL. Having done that, in my application the long string turns up correctly in all output where it should be, even in my mutation form. But in the mutation form it cannot be edited because it is too long.
Make migrations and migrate again
python manage.py makemigrations specify_app_name
then
python manage.py migrate specify_app_name

Calling loaddata in Django 1.7 migrations is throwing "Unknown column '[field]' in 'field list'"

I'm running into an issue in Django 1.7 when attempting to write multiple migrations in a row. Here's the basic setup of the migrations:
Initial schema migration to create the models for an app
Data migration that calls loaddata on a specific fixture that contains one-time default data
A new optional field was added to one of the models, so it's a schemamigration to add the field
If I generate the first migration, run it, generate the second, run it, and then add the new field, generate the third migration, and run it, everything is fine. However, if my database were on migration #1 and then I pulled down from a source repository, migration 2 would fail because it uses the models from models.py when calling loaddata rather than the models as of the time of that migration. It then produces the following error:
"Unknown column '[field]' in 'field list'"
In this case, [field] is the new field that I added for migration #3. The error makes sense, because my database doesn't have the new field yet but loaddata expects it to be there (even though the fixture doesn't reference the new field), but is there any way to make loaddata use the database at the time of the migration rather than the current state in models.py? Or are there any other ways to get around this issue?
Thanks.
I ended up writing a hack to get around this for now, but I feel like there has to be a better way. Instead of calling loaddata in the migration, I now call this function:
def load_fixture_in_data_migration(apps, schema_editor, fixture_filename, migration_file):
"""
Load fixture data in data migrations without breaking everything
when the models change later on
"""
fixture_dir = os.path.abspath(os.path.join(os.path.dirname(migration_file), '../fixtures'))
fixture_file = os.path.join(fixture_dir, fixture_filename)
fixture = open(fixture_file, 'rb')
objects = serializers.deserialize('json', fixture, ignorenonexistent=True)
for obj in objects:
ObjApp = apps.get_model(obj.object._meta.app_label, obj.object._meta.object_name)
new_obj = ObjApp(pk=obj.object.pk)
for field in ObjApp._meta.fields:
setattr(new_obj, field.name, getattr(obj.object, field.name))
new_obj.save()
fixture.close()
And I call it like this from the data migration:
load_fixture_in_data_migration(apps, schema_editor, 'initial_add_ons.json', __file__)
Does anyone know a better way to do this? It feels really like a hack since I have to access object meta data to accomplish this.

Slugfield in tango with django

I'm reading this tutorial to lear the basics of django and I'm facing a problem I can't solve.
I'm at this page http://www.tangowithdjango.com/book17/chapters/models_templates.html at the sluglify function approach.
In the tutorial the author says we have to create a new line in our category model for th slugfield. I folow strictly all the steps just as I show here:
from django.db import models
from django.template.defaultfilters import slugify
class Category(models.Model):
name = models.CharField(max_length=128, unique=True)
likes = models.IntegerField(default=0)
views = models.IntegerField(default=0)
slug = models.SlugField(unique=True)
def __unicode__(self):
return self.name
class Page(models.Model):
category = models.ForeignKey(Category)
title = models.CharField(max_length=128)
url = models.URLField()
views = models.IntegerField(default=0)
def __unicode__(self):
return self.title
When I run the "makemgiration" command everything works as expected: I choose the first option and provide ‘’ . BUT when I run "migrate" I get:
django.db.utils.Integrity error: Slug column is not unique
What is going on here? I've repeated several times the migrations and tried other default codes but with the same ending. I can't figure out what im doing wrong. They only thing left is that i'm giving something else instead of ‘’ (Firstly I thoughtthey were '' or ").
Thankyou for your time and help!
Delete db.sqlite3 and re run
python manage.py syncdb
Then perform the migrations
python manage.py makemigrations rango
python manage.py migrate
and re run your population script. This is a downside of Django that whenever you change models.py the db must be recreated.
I am also going through the tutorial and I was having the same issue a couple days ago.
I believe the problem is that you are trying to add a new field (slug) and have it be unique for each of the elements in your table but if I'm not mistaken you already have some data in your table for which that value does not exist and therefore the value that this field would get for those rows is not unique, hence the "django.db.utils.Integrity error: Slug column is not unique".
What I did was simply to delete the data in the table (because it was only a couple of fields, so no big deal) and THEN perform the addition of the field to the model. After doing that, you can put the data back in the table (if you're following the tutorial you should have a script for automated table population so you just run that script and you're golden). Once you have done that, all the rows in the table should have a unique slug field (since it is automatically generated based on the category name) and that solves the problem.
Note that if your table is very large, this may not be a very good solution because of the deletion of data so perhaps there is a better way, like adding that field to the model without it being unique, then running a script that sets the slug field for every row to an unique value and then setting the model's field as unique but I'm not very knowledgeable on SQL and the first solution worked just fine for me so it should work for you as well.
try deleting the sqlite3.db file from the project's directory. i was stuck on a similar problem and that really works..also even if you modify your population script, you have to delete and the recreate the db file to see the changes made....

Django south migration error with unique field in postgresql database

Edit: I understand the reason why this happened. It was because of the existence of `initial_data.json` file. Apparently, south wants to add those fixtures after migration but failing because of the unique property of a field.
I changed my model from this:
class Setting(models.Model):
anahtar = models.CharField(max_length=20,unique=True)
deger = models.CharField(max_length=40)
def __unicode__(self):
return self.anahtar
To this,
class Setting(models.Model):
anahtar = models.CharField(max_length=20,unique=True)
deger = models.CharField(max_length=100)
def __unicode__(self):
return self.anahtar
Schema migration command completed successfully, but, trying to migrate gives me this error:
IntegrityError: duplicate key value violates unique constraint
"blog_setting_anahtar_key" DETAIL: Key (anahtar)=(blog_baslik) already
exists.
I want to keep that field unique, but still migrate the field. By the way, data loss on that table is acceptable, so long as other tables in DB stay intact.
It's actually the default behavior of syncdb to run initial_data.json each time. From the Django docs:
If you create a fixture named initial_data.[xml/yaml/json], that fixture will be loaded every time you run syncdb. This is extremely convenient, but be careful: remember that the data will be refreshed every time you run syncdb. So don't use initial_data for data you'll want to edit.
See: docs
Personally, I think the use-case for initial data that needs to be reloaded each and every time a change occurs is retarded, so I never use initial_data.json.
The better method, since you're using South, is to manually call loaddata on a specific fixture necessary for your migration. In the case of initial data, that would go in your 0001_initial.py migration.
def forwards(self, orm):
from django.core.management import call_command
call_command("loaddata", "my_fixture.json")
See: http://south.aeracode.org/docs/fixtures.html
Also, remember that the path to your fixture is relative to the project root. So, if your fixture is at "myproject/myapp/fixtures/my_fixture.json" call_command would actually look like:
call_command('loaddata', 'myapp/fixtures/my_fixture.json')
And, of course, your fixture can't be named 'initial_data.json', otherwise, the default behavior will take over.

Creating Custom User Backends in Django

I have a Shops model and would like each shop to be able to login to my application. Following as best I can the guide at http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/ and various other googlings, I've got part of the way there, but I've run into a problem. When I try to login as a shop, I get the following error:
OperationalError at /login/
(1054, "Unknown column 'shops.user_ptr_id' in 'field list'")
Shops model:
class Shops(User):
shop_id = models.AutoField(primary_key=True)
shop_code = models.CharField(unique=True, max_length=5)
shop_type_fk = models.ForeignKey(ShopTypes,
null=True,
db_column='shop_type_id',
blank=True)
address_fk = models.ForeignKey(Addresses, db_column='address_id')
phone_number = models.CharField(max_length=30)
#email = models.EmailField(max_length=255, blank=True)
description = models.TextField(blank=True)
does_gift_aid = models.NullBooleanField(null=True, blank=True)
objects = UserManager()
class Meta:
db_table = u'shops'
I've sync'd the database, so surely it should have made the column user_ptr_id. Does anyone know where I'm going wrong?
"I've sync'd the database, so surely it should have made the column user_ptr_id."
What makes you think that? Especially in light of this clear statement in the docs for syncdb:
Syncdb will not alter existing tables
syncdb will only create tables for
models which have not yet been
installed. It will never issue ALTER
TABLE statements to match changes made
to a model class after installation.
Changes to model classes and database
schemas often involve some form of
ambiguity and, in those cases, Django
would have to guess at the correct
changes to make. There is a risk that
critical data would be lost in the
process.
If you have made changes to a model
and wish to alter the database tables
to match, use the sql command to
display the new SQL structure and
compare that to your existing table
schema to work out the changes.
It does sound like you had an existing shops table before changing it to inherit from User (as Daniel notes), and syncdb does not update the schema for existing tables.
You need to drop the table and then run syncdb, if possible. Otherwise you need to go into your database and add the user_ptr_id field manually, if you know how to do that. The definition should look something like this:
"user_ptr_id" integer NOT NULL UNIQUE REFERENCES "auth_user" ("id")