Django testing: DatabaseError: no such table for ManyToManyField - python

I've written a couple of tests for really simple blog app, but the many to many relationship fails when I run the test: ./manage.py test myblog
DatabaseError: no such table: myblog_post_tag
Yet when I do ./manage.py sql myblog:
BEGIN;
CREATE TABLE "myblog_tag" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(50) NOT NULL
)
;
CREATE TABLE "myblog_post_tag" (
"id" integer NOT NULL PRIMARY KEY,
"post_id" integer NOT NULL,
"tag_id" integer NOT NULL REFERENCES "myblog_tag" ("id"),
UNIQUE ("post_id", "tag_id")
)
;
CREATE TABLE "myblog_post" (
"id" integer NOT NULL PRIMARY KEY,
"title" varchar(200) NOT NULL,
"pub_date" datetime NOT NULL,
"content" text NOT NULL
)
;
COMMIT;
It does create a table, yet it fails to do so while testing? Any help is appreciated.
Here's my test:
class TagModelTest(TestCase):
def test_create_tags_for_posts(self):
# tests tagging posts, postodd will have tags 1 & 3, posteven will be 2 & 4
postodd = Post(
title="testing odd tags",
pub_date=timezone.now(),
content='''hello everybody, we are testing some tagging
functionality here. This post should have odd tags.''',
)
posteven = Post(
title="test even tags",
pub_date=timezone.now(),
content ='''hello everybody, we are testing some tagging
functionality here. This post should have even tags.''',
)
#save them to db
postodd.save()
posteven.save()
# create the tags
tag1 = Tag(name="1")
tag2 = Tag(name="2")
tag3 = Tag(name="3")
tag4 = Tag(name="4")
# save all tags to db
tag1.save()
tag2.save()
tag3.save()
tag4.save()
# create the many2many relationship
postodd.tag.add(tag1)
And my models.py if needed:
from django.db import models
class Tag(models.Model):
name = models.CharField(max_length=50)
def __unicode__(self):
return self.name
class Post(models.Model):
tag = models.ManyToManyField(Tag)
title = models.CharField(max_length=200)
pub_date = models.DateTimeField(verbose_name="Date published")
content = models.TextField()
def __unicode__(self):
return self.title

./manage.py sql myblog does not execute the SQL, it just outputs what it would execute if you ran syncdb.
In this case, it seems the table is missing from your db.
If this was a result of a modification to an existing app; for example you just added a new field to your model; then running syncdb won't affect the changes to your database. syncdb doesn't do any destructive operations (like adding or dropping tables or columns).
In this case you can manually run the query to add the column; or drop and recreate your tables with syncdb.
Since this is a common problem most people use a data migration tool like south to handle these changes for you. South will manage these small changes intelligently.

Related

table items_item has no column named category_id

While creating item I got this error, though I can see category_id at sqlall:
table items_item has no column named category_id
migration commands:
$ python manage.py makemigrations items
No changes detected
$ python manage.py migrate
Running migrations:
No migrations to apply.
model.py
from django.db import models
class Category(models.Model):
name = models.CharField(max_length=200)
# Create your models here.
class Item(models.Model):
name = models.CharField(max_length=200)
description = models.TextField(null=True, blank=True)
image = models.ImageField(upload_to="item_images")
category = models.ForeignKey(Category)
show_in_front_page= models.BooleanField(default=True)
always_show_in_front_page= models.BooleanField(default=True)
is_trending=models.BooleanField(default=True)
sqlall
# $ python manage.py sqlall items
BEGIN;
CREATE TABLE "items_category" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"name" varchar(200) NOT NULL
)
;
CREATE TABLE "items_item" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"name" varchar(200) NOT NULL,
"description" text,
"image" varchar(100) NOT NULL,
"category_id" integer NOT NULL REFERENCES "items_category" ("id"),
"show_in_front_page" bool NOT NULL,
"always_show_in_front_page" bool NOT NULL,
"is_trending" bool NOT NULL
)
;
CREATE INDEX "items_item_6f33f001" ON "items_item" ("category_id");
COMMIT;
admin.py
from django.contrib import admin
# Register your models here.
from .models import Item, Category
admin.site.register(Item)
admin.site.register(Category)
If the category_id column is already in an applied migration file, but hasn't been created in the database., then the easiest fix would be to add the column manually. It's easy to work out the SQL from your sqlall output above.
./manage.py dbshell # open a db shell
# Add the column
ALTER TABLE items_item ADD COLUMN "category_id" integer NOT NULL REFERENCES "items_category" ("id");
# Add the index
CREATE INDEX "items_item_6f33f001" ON "items_item" ("category_id");
try deleting your db.sqlite3 file.
Then run makemigrations and migrate (the sqlite file will generates automatically).

Setting database with django

I created a db with such tracks.models:
class Song(models.Model):
title = models.CharField(max_length=30)
album = models.ForeignKey(Album)
def __unicode__(self):
return self.title
and used
python manage.py sqall tracks
python manage.py syncdb
but then I changed models to
class Song(models.Model):
songid = models.CharField(max_length=30)
title = models.CharField(max_length=30)
album = models.ForeignKey(Album)
def __unicode__(self):
return self.title
and did
python manage.py sqall tracks
python manage.py syncdb
again. Output of sqall:
BEGIN;
CREATE TABLE "tracks_song" (
"id" integer NOT NULL PRIMARY KEY,
"songid" varchar(30) NOT NULL,
"title" varchar(30) NOT NULL,
"album_id" integer NOT NULL REFERENCES "tracks_album" ("id")
)
;
CREATE INDEX "tracks_song_6781e42a" ON "tracks_song" ("album_id");
COMMIT;
syncdb:
Creating tables ...
Installing custom SQL ...
Installing indexes ...
Installed 0 object(s) from 0 fixture(s)
But whenever I tried to access tracks.models.Song.all() it said:
OperationalError: no such column: tracks_song.songid
So I decided to
python manage.py flush
python manage.py sqall tracks
python manage.py syncdb
(same output)
But problem hasn't gone and there's still no such column: tracks_song.songid.
What's the problem behind it?
python manage.py sqlall app-name will only print SQL sentences, not create or change database structures, that is to say, it's used to check or tell you what django actually do in databases. Howerver, django version<1.7 doesn't track changes of class in models.py(newly increased or delete existed class could be detected and syncdb), but you can use south, or django 1.7 to do such thing.
python manage.py flush will IRREVERSIBLY DESTROY all data, but not change tables in database.
South: http://south.aeracode.org/
Django 1.7: https://docs.djangoproject.com/en/dev/releases/1.7/#django-1-7-release-notes-under-development
you should also notice that if you only need an id field, class Song has a default AutoField id, just use song.id Django models Quick Example

Django no such column error

I have the following code in my models.py file:
from django.db import models
from django.db.models import permalink
class Page(models.Model):
name = models.CharField(max_length=100,db_index=True, unique=True)
slug = models.SlugField(max_length=100,db_index=True, unique=True)
def __unicode__(self):
return '%s' % self.name
class Category(models.Model):
name = models.CharField(max_length=100, db_index=True, unique=True)
slug = models.SlugField(max_length=100, db_index=True, unique=True)
def __unicode__(self):
return '%s' % self.name
class Post(models.Model):
title = models.CharField(max_length=100, unique=True, db_index=True)
body = models.TextField()
post_date = models.DateField(db_index = True, auto_now_add=True)
category = models.ForeignKey('board.Category')
page = models.ForeignKey('board.Page')
def __unicode__(self):
return '%s' % self.title
#permalink
def get_absolute_url(self):
return "/%i/%i" % Page.slug, self.id
When I try to add a Post object in the admin page (I configured the admin.py too), I get the following error:
no such column: board_category.name
I did my research and tried dropping the table and doing syncdb again but somehow it still shows this error.
So I listed my tables:
CREATE TABLE "board_page" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(100) NOT NULL UNIQUE,
"slug" varchar(100) NOT NULL UNIQUE
)
;
CREATE TABLE "board_category" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(100) NOT NULL UNIQUE,
"slug" varchar(100) NOT NULL UNIQUE
)
;
CREATE TABLE "board_post" (
"id" integer NOT NULL PRIMARY KEY,
"title" varchar(100) NOT NULL UNIQUE,
"body" text NOT NULL,
"post_date" date NOT NULL,
"category_id" integer NOT NULL REFERENCES "board_category" ("id"),
"page_id" integer NOT NULL REFERENCES "board_page" ("id")
)
;
CREATE INDEX "board_post_896eb94b" ON "board_post" ("post_date");
CREATE INDEX "board_post_6f33f001" ON "board_post" ("category_id");
CREATE INDEX "board_post_3fb9c94f" ON "board_post" ("page_id");
I'm not exactly an expert in SQL but I can clearly see that the board_page.name column exists so I really have no idea why this is giving me an error.
And the strangest thing is that adding another page or category actually works....
--EDIT
from django.contrib import admin
from board.models import Page, Post, Category
class PageAdmin(admin.ModelAdmin):
#fields = ['name','slug']
pass
class PostAdmin(admin.ModelAdmin):
#fields = ['title','body','category','page']
pass
class CategoryAdmin(admin.ModelAdmin):
#fields = ['name','slug']
pass
admin.site.register(Page, PageAdmin)
admin.site.register(Post, PostAdmin)
admin.site.register(Category, CategoryAdmin)
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.
better use South to migrate the changes of your models.
first migration with:
python manage.py schemamigration yourapp --initial
python manage.py migrate yourapp
other migrations:
python manage.py schemamigration yourapp --auto
python manage.py migrate yourapp
If you add something to your models and after that you did not sync, this happens.
If you are in beginning for your project, I recommend to remove your db and recreate it and then:
python manage.py syncdb
Otherwise use South.
http://south.readthedocs.org/en/latest/
It's interesting but sometimes rebooting the server helps. It worked for me a few times in past.

Django - Create Category Views doesn't create Column

I am doing this tutorial tangowithdjango 5 Models and databases
In the exercises it asks to create a views and likes column with default=0 in the categories. Then to use population script to update them with values.
Direct quote from site
Update the Category model to include the additional attributes, views
and likes where the default value is zero.
So I have gone and created the categories in models.py
from django.db import models
from django.template.defaultfilters import default
# Create your models here.
class Category(models.Model):
name = models.CharField(max_length=128, unique=True)
views = models.IntegerField(default=0)
likes = models.IntegerField(default=0)
class Meta:
verbose_name_plural = "Categories"
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)
Then I sync.db
However the columns aren't creating I get this error from the view.
Exception Type: DatabaseError at /admin/rango/category/
Exception Value: no such column: rango_category.views
What is wrong with how I have created them? Do I have to remove all my database tables and recreate them?
Edit: The solution to Incorrect Duplicate doesn't resolve the issue, as well as my answer I thought would. Deleting the database and re-syncing didn't resolve the issue with creating the population script.
The sql appears to be ok I am unsure what is wrong.
BEGIN;
CREATE TABLE "rango_category" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(128) NOT NULL UNIQUE,
"views" integer NOT NULL,
"likes" integer NOT NULL
)
;
CREATE TABLE "rango_page" (
"id" integer NOT NULL PRIMARY KEY,
"category_id" integer NOT NULL REFERENCES "rango_category" ("id"),
"title" varchar(128) NOT NULL,
"url" varchar(200) NOT NULL,
"views" integer NOT NULL
)
;
COMMIT;
Finished "/home/sayth/workspace/tango_project/manage.py sql rango" execution.
Even re deleting database and redesigning and recreating models doesn't reolved.
BEGIN;
CREATE TABLE "rango_category" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(128) NOT NULL UNIQUE
)
;
CREATE TABLE "rango_page" (
"id" integer NOT NULL PRIMARY KEY,
"category_id" integer NOT NULL REFERENCES "rango_category" ("id"),
"title" varchar(128) NOT NULL,
"url" varchar(200) NOT NULL,
"views" integer NOT NULL,
"likes" integer NOT NULL
)
;
COMMIT;
Finished "/home/sayth/workspace/tango_project/manage.py sql rango" execution.
Ah yes I overlooked a warning in the doc.
Warning Whenever you add to existing database models, you will have to
delete the database file and then re-sync the database by running
python manage.py syncb again. This is a drawback of Django 1.5.4, and
can be quite frustrating. If you however add a new model, you can
syncdb your database without having to delete and recreate it. You
must therefore bear this in mind when tweaking your database: new
models will be synchronised with syncdb - but changes to existing
models will not be. When adding a new model to your application’s
models.py file, you can simply run the following command to
synchronise the database with the command $ python manage.py syncdb.
When updating an existing model to your application’s models.py file,
you must perform the following steps. Delete the database. Recreate
the database with the command $ python manage.py syncdb. Populate the
new database with data. Deleting and recreating the database from
scratch is a frustrating process. A possible solution to this issue
could be to use a third party application like South to handle
database schema migrations (changes to your models). South is
currently in active development and is considered a standard solution
for Django schema migrations until this functionality becomes part of
the standard Django codebase. We don’t cover South here - but the
official South documentation provides a handy tutorial if you’re
interested. If you don’t want to use South, we discuss a technique in
Section 5.8 to speed up the updating process. You may have also
noticed that our Category model is currently lacking some fields that
we defined in Rango’s requirements. We will add these in later to
remind you of the updating process.
And it appears migrations in core will not be available until django 1.7.
I had incorrectly updated the populate script it should have looked like.
def add_page(cat, title, url, views=0):
p = Page.objects.get_or_create(category=cat, title=title, url=url, views=views)[0]
return p
def add_cat(name, views=0, likes=0):
c = Category.objects.get_or_create(name=name, views=views, likes=likes)[0]
return c
see
https://stackoverflow.com/a/19759473/461887
django migrations

Django - set ForeignKey deferrable foreign key constraint in SQLite3

I seem to be stuck with creating an initialy deferrable foreign key relationship between two models in Django and using SQLite3 as my backend storage.
Consider this simple example. This is what models.py looks like:
from django.db import models
class Investigator(models.Model):
name = models.CharField(max_length=250)
email = models.CharField(max_length=250)
class Project(models.Model):
name = models.CharField(max_length=250)
investigator = models.ForeignKey(Investigator)
And this is what the output from sqlall looks like:
BEGIN;
CREATE TABLE "moo_investigator" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(250) NOT NULL,
"email" varchar(250) NOT NULL
)
;
CREATE TABLE "moo_project" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(250) NOT NULL,
"investigator_id" integer NOT NULL REFERENCES "moo_investigator" ("id")
)
;
CREATE INDEX "moo_project_a7e50be7" ON "moo_project" ("investigator_id");
COMMIT;
"DEFERRABLE INITIALLY DEFERRED" is missing from the *investigator_id* column in the project table. What am I doing wrong?
p.s. I am new to Python and Django - using Python version 2.6.1 Django version 1.4 and SQLite version 3.6.12
This behavior is now the default. See https://github.com/django/django/blob/803840abf7dcb6ac190f021a971f1e3dc8f6792a/django/db/backends/sqlite3/schema.py#L16
Sqlite backend does not add "DEFERRABLE INITIALLY DEFERRED". Check the code

Categories