Django - syncdb doesn't create tables - python

I added a many-to-many field to an existing model and was expecting syncdb to create a new table, but there's nothing there. This is what the model looks like:
class Author(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
email = models.EmailField()
def __unicode__(self):
return "{0} {1}".format(self.first_name, self.last_name)
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
def __unicode__(self):
return self.title
Running sql myapp prints the correct statements with the new table, but this is not reflected when I run syncdb. validate also returns no errors. Does anyone know what could be the matter here? Or a better diagnostic?

The syncdb command does not create many to many tables for existing models by design. This decision is explained on ticket 2229.
That leaves you with a few options.
If you don't have any data in your Book model, drop the table and rerun syncdb. Django will recreate the book table and the many to many table.
Use the dbshell command, and create the many to many joining table using the output of sql myapp.
If you're doing multiple schema migrations with Django, make friends with South.

I found this explanation at the django docs useful: SchemaEvolution.
The de facto standard for database migration is Django South.
Its not perfect, but, it works pretty well. You should always check(and edit if necessary) your migration file before running it, to make sure that it actually does what it supposed to do.
You can check out their tutorial here.
Also, if you run:
python manage.py inspectdb > somefile.txt
You can get quickly check out if your database structure is matching your django models.

Related

How to update Django model fields in MySQL database

I created a model for posts in Django and I'm trying to update one of the fields in the database (MySQL).
I have the following block of code:
model.py
class Post (models.Model):
title = models.CharField()
preamble = models.CharField()
body = models.TextField ()
createdAt = models.DateTimeField(auto_now_add=True, blank=True)
I want to add another field called author author=models.ForeignKey(User, on_delete=models.CASCADE
Also, I want to change the name of one of the fields from preamble to introduction
Whenever I run the command python manage.py makemigrations and then python manage.py migrate, I get an error which terminates the migration process. it's telling me that the field preamble which I have in my database is not recognized. Is it possible to update preamble to introduction?
Ensure you have a migration of the initial state of your app, before any modifications.
Rename the preamble field to introduction in your model, making no other changes.
Run makemigrations. It should ask you whether it was a rename.
Add the author foreign key.
Run makemigrations. It should ask you for a default for the user field if it's not nullable; 1 should hopefully refer to the first user created in your system.
Run migrate.
This should be work:
delete the SQLite database and also migrations directory
change the model
then run the migrate command

Create database tables from models in django 1.10 with Postgres

I have multiple models that I'd like to create tables for. So far I've been running sql code to create them and then i can make use of them. This seems tedious and I'm pretty sure django can do it for me. After all it creates tables with makemigrations and migrate. But this does not seem to work with my models.
EDIT: Here's what I mean
I have a model like the following
class Article(models.Model):
headline = models.CharField(max_length=200)
content = models.TextField()
...
class Meta:
managed = False
db_table = 'main_article'
So far I've been creating the main_article table manually by running this code in psycopg2:
CREATE TABLE IF NOT EXISTS public.main_article (
id SERIAL PRIMARY KEY,
headline varchar 200 NOT NULL,
content text NOT NULL,
...
);
This is a real pain and I'm sure it will lead to errors and bugs. How can i get this table to be created automatically? I tried doing
python manage.py makemigrations main
python manage.py migrate main
With no success.
Btw 'main' is the name of my app.
Hope it's more clear now.
Thanks in advance!
For anyone still wondering, my problem was that I had set managed to false. Simply changing this did the trick.

"Relation not found" error when using Django without syncdb

I have a small Django project with simple models. However, instead of creating my database via python manage.py syncdb I decided to create it manually and map the tables via Meta, as shown below
class Item(models.Model):
name = models.CharField(max_length=50)
class Meta:
managed = False
db_table = 'ITEM'
but this doesn't work. When I start the development server and run the main view, Django throws an error saying that the relation named ITEM doesn't exist in the database, when in fact it does exist.
I have done some research but couldn't find anyone with such a problem. Is there a way I can get it working?
The db_table name should be in lowercase:
db_table = 'item'
Postgres converts table names to lowercase letters unless the queries have quotes around them. See for example:
http://binodsblog.blogspot.com/2011/02/postgresql-is-case-sensitive.html
Normally that detail is abstracted away by the ORM, but if you don't use syncdb, you have to manage it.

Django many to many relationship with built in "User" model

Scenario
I have a basic Django app in which users (django's authentication built in model) and reports have a many-to-many relationship.
The Problem
Django does not create a corresponding table to handle this relationship. My application is called reports. There is an error in the admin system upon trying to create a report and assign users to it. It tries to query the table reports_report_users and it fails as it does not exist.
models.py code
from django.db import models
from django.contrib.auth.models import User
class Report(models.Model):
name = models.CharField(max_length=30, blank=False)
users = models.ManyToManyField(User, related_name='reports')
def __unicode__(self):
return self.name
Attempted Solutions
Used this link as a reference: https://docs.djangoproject.com/en/1.4/topics/db/examples/many_to_many/
Ran manage.py syncdb about 300 times - ok, only once, but there were no errors and upon inspecting the SQLite db there were no additional tables created :(
It seems like you've added to the Report model after the first sync. Thus you're dealing with a migration, which django doesn't do natively.
First, Inspect the sql output, make sure that the create table instruction for your many to many relationship is there.
python manage.py sqlall
Assuming the problem is that this is a migration, which django doesn't handle natively, you've got three options:
1) Delete all db tables for this app, then run syncdb again.
2) Manually create the tables (fairly easy to copy paste the create sql from the sqlall command)
3) Start using a migration framework like South.
In the long run you'll appreciate the investment in learning south. In the short term, deleting the DB file is the fastest.-
Have you deleted your db file and run manage.py syncdb again?

Want to add a one-to-one column to an existing table

I have a new field in the Client called note which has a one-to-one relation with Notes.
I want to be able to add the note column under the Client table in mysql. It does not work when I use python manage.py syncdb. So I would like to know how to add a one-to-one field in mysql to an existing table.
models.py
class Note(models.Model):
datetime = models.DateTimeField(default=datetime.now)
user = models.ForeignKey(User)
note = models.TextField()
def __unicode__(self):
return unicode(self.name)
class Client(models.Model):
note = models.OneToOneField(Note) # new
def __unicode__(self)
return unicode(self.user)
Syncdb doesn't change your database in order not to destroy your data. See django book.
You can update the database manually or use an automated migration tool (at your own risk) like South.
EDIT:
In django book, you can also read detailed instructions about manual changes along with SQL examples. Other useful information can be found in MySQL manual.
You didn't say what the application name is so I'll assume it is fooapp.
First look at the SQL Django would have used to create the relevant tables:
python manage.py sql fooapp
For additional fields run this sql command:
ALTER TABLE fooapp_client ADD ...
where ... is the field declaration you saw in the output of "manage.py sql fooapp"
Remember to also execute any index/constraint commands in the "manage.py sql fooapp" output that operate on the new field.

Categories

Resources