Whenever I try to migrate my application in Django, the python manage.py migrate command throws Operational errors that say:
django.db.utils.OperationalError: table "main_site_prescription" already exists
I tried deleting the table and that didn't work. I tried to --fake the migration, but then the database doesn't recognize the change to models.py. This is thrown on the site when I it tries to use one of the columns in a view:
Exception Type: OperationalError
Exception Value: table main_site_event has no column named initiated_by_id
Here are the tables:
sqlite> .tables
auth_group
auth_group_permissions
auth_permission
auth_user
auth_user_groups
auth_user_user_permissions
django_admin_log
django_content_type
django_migrations
django_session
main_site_appointment
main_site_doctor
main_site_doctor_listOfPatients
main_site_event
main_site_hospital
main_site_hospital_listOfDoctors
main_site_hospital_listOfHospitalAdmins
main_site_hospital_listOfNurses
main_site_hospital_listOfPatients
main_site_hospitaladmin
main_site_hospitaladmin_listOfDoctors
main_site_hospitaladmin_listOfHospitalAdmins
main_site_hospitaladmin_listOfNurses
main_site_hospitaladmin_listOfPatients
main_site_message
main_site_nurse
main_site_nurse_listOfDoctors
main_site_nurse_listOfPatients
main_site_patient
main_site_patient_prescriptions
main_site_patient_records
main_site_prescription
main_site_record
and here is the PRAGMA table_info(main_site_event) output...
sqlite> PRAGMA table_info(main_site_event);
0|id|integer|1||1
1|activity|text|1||0
2|time|datetime|1||0
sqlite>
This is the representation in the model...
'''Class representing an event, used for the activity log'''
class Event(models.Model):
activity = models.TextField(max_length=500, blank=True) # an action from the list of actions
time = models.DateTimeField(auto_now_add=True) # the time of the action in datetime format
initiated_by = models.ForeignKey(User, related_name="initiator") # the user who initiated the action
target_of = models.ForeignKey(User, default = None, related_name="target", null = True) # the user who is the target of the action
hospitals = models.ForeignKey(Hospital, default=None, null = True)
prescriptions = models.ForeignKey(Prescription, default=None, null = True)
Which obviously aren't correct (table missing multiple columns)
Related
I'm trying to create models taking a MySQL database as reference using Django, but when I try to migrate, it throws me the following error:
Cannot change column 'id': used in a foreign key constraint 'fk_post' of table 'demoniosmv.images'"
My models look like this:
from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
class Images(models.Model):
#id = models.IntegerField(primary_key=True)
fk_post = models.ForeignKey('Post', related_name="images", blank=True, null=True, on_delete = models.CASCADE)
img_url = models.CharField(max_length=100, blank=True, null=True)
class Meta:
managed = True
class Post(models.Model):
#id = models.IntegerField(primary_key=True)
author = models.ForeignKey(User, related_name="posts", on_delete = models.CASCADE)
title = models.CharField(max_length=200, blank=True, null=True)
text = models.TextField(blank=True, null=True)
created_date = models.DateTimeField(default = timezone.now)
class Meta:
managed = True
And the SQL script from which I'm creating the database is this:
-- MySQL Script generated by MySQL Workbench
-- Sun Jul 21 14:14:44 2019
-- Model: New Model Version: 1.0
-- MySQL Workbench Forward Engineering
SET #OLD_UNIQUE_CHECKS=##UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
-- -----------------------------------------------------
-- Schema demoniosmv
-- -----------------------------------------------------
-- -----------------------------------------------------
-- Schema demoniosmv
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `demoniosmv` DEFAULT CHARACTER SET utf8 ;
USE `demoniosmv` ;
-- -----------------------------------------------------
-- Table `demoniosmv`.`post`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `demoniosmv`.`post` (
`id` INT NOT NULL,
`title` VARCHAR(200) NULL,
`text` TEXT(1000) NULL,
`created_date` DATETIME NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `demoniosmv`.`images`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `demoniosmv`.`images` (
`id` INT NOT NULL,
`fk_post` INT NULL,
`img_url` VARCHAR(100) NULL,
PRIMARY KEY (`id`),
INDEX `fk_post_idx` (`fk_post` ASC) VISIBLE,
CONSTRAINT `fk_post`
FOREIGN KEY (`fk_post`)
REFERENCES `demoniosmv`.`post` (`id`)
ON DELETE CASCADE
ON UPDATE NO ACTION)
ENGINE = InnoDB;
SET SQL_MODE=#OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS;
For creating the models I used the insepctdb command, I'm using sqlclient for the MySQL connection, and I'm using Django 2.2.3 with Python 3.7.
I had to delete the files inside migrations and py_cache folders to make it work. All the files except for the init.py files
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).
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
A duplicate model field is giving me trouble (no such table appname_modelname when I run my webpage). Whenever I do ./manage.py migrate appname, it gives me "duplicate field". I checked my models.py, there is only one of them there. How do I delete that duplicate field? It seems no matter what I do, it stays. I've tried:
Deleting the database
Deleting migrations folder in app folder
Doing ./manage.py sqlclear south and then dropping the south_migrationhistory table in the dbshell
./manage.py schemamigration appname --initial, ./manage.py migrate appname --fake
I've run out of ideas.
class Document(models.Model):
filename = models.CharField(max_length=255, blank=True, null=True, default=None)
identity = models.CharField(max_length=255, default=None, null=True)
user = models.ForeignKey(User, null=False)
user_id = models.IntegerField(User, null=True)
docfile = models.FileField(upload_to=_upload_path, storage=fs) # upload_to is a path inside the storage path
def get_upload_path(self,filename):
return str(self.user.id) + '/' + str(date.today()) + '/' + filename
You can't do this, for your user foreign key, Django ORM will create a database field named user_id (your foreign key field name plus _id) to use it as a FK in the database.
You don't have to create this field yourself (the ORM will take care), even if you need it, change the name of the attribute user or user_id.
From the documentation:
Behind the scenes, Django appends "_id" to the field name to create its database column name. In the above example, the database table for the Car model will have a manufacturer_id column. (You can change this explicitly by specifying db_column) However, your code should never have to deal with the database column name, unless you write custom SQL. You’ll always deal with the field names of your model object.
Not sure but problem causing here in these two line
user = models.ForeignKey(User, null=False)
user_id = models.IntegerField(User, null=True)
Better to use "related name" attribute to avoid the duplicate error as in database "user" will be added as user_id.
user = models.ForeignKey(User, related_name="id_user") # Change the related field as your convenience
user_id = models.IntegerField(null=True, related_name="user_id")
Check if this resolve your issues
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.