I want to migrate a site written in PHP/MySQL to a Python/Django. There will be some significant modifications to the application, but I am not expecting any significant changes to the backend persistence.
Essentially I would like to find a tool that will create the
django.db.models.Model
classes for me. For example consider:
create table blah (
a varchar(10) not null
, b varchar(10) not null
)
and I run the tool and it generates the following models.py file for me
class Blah(models.Model):
a = models.CharField(max_length=10)
b = models.CharField(max_length=10)
Something I can run command line OR wherever. Thanks, and I am new to python/django so I apologize if there is well known solution (although google isn't showing me one).
T
Django can handle it, see inspectdb management command:
Introspects the database tables in the database pointed-to by the NAME
setting and outputs a Django model module (a models.py file) to
standard output.
Also, consider using south for further schema and data migrations.
Related
I'm trying to find out if there is a way to programmatically generate Django models for legacy databases. So given a list of legacy tables, create a model for each one. Here is an example of what I mean
class Person_001(models.Model):
id = models.IntegerField(primary_key=True)
huge_dataset = models.CharField(max_length=70)
class Meta:
managed = False
db_table = 'person_001'
So for example, create this model for person_001, person_002 etc...
I realize there may be a more efficient way of storing this data and I am opened to suggestions, but the data has been stored this way because huge_dataset is, well, huge.
I think the documentation will help you tremendously here Django Docs
from the docs --
Auto-generate the modelsĀ¶
Django comes with a utility called inspectdb that can create models by introspecting an existing database. You can view the output by running this command:
$ python manage.py inspectdb
Save this as a file by using standard Unix output redirection:
$ python manage.py inspectdb > models.py
First of all I'm not a fan of "do it the django way" thing. Instead of spending hours to learn the django way I prefer to utilize my basic programming knowledge when I develop an application.
Background :
Application I'm developing is a REST backend that stores localization values like language information.
I want to take language information that is stored in the database and load it into memory once at startup and then serve that data from memory when a request comes.
I created my model
class Text(models.Model):
language = models.CharField()
key = models.CharField()
text = models.CharField()
Then ran python manage.py makemigrations and migrate commands as a regular step
Then I jumped ahead and implemented my caching code and put it directly under admin.py(it could be urls.py it does not matter, it only needs to be run once)
cached_languages = models.Text.objects.all()
I go ahead and run my app and it is just working fine.
Then I wanted to add a field to my Text model like
class Text(models.Model):
language = models.CharField()
key = models.CharField()
text = models.CharField()
**dummy = models.CharField()**
Then hit python manage.py makemigrations command and boom at line
cached_languages = models.Text.objects.all()
We get an error saying that
sqlite3.OperationalError: no such column: app_text.dummy
What should I do to fix this?
The problem is that django executes every line of code that is written even when you call python manage.py makemigrations. This means before django actually reflects the alterations to database it executes entire project and when it comes to the caching line it tries to get all rows from Text table which does not yet have column dummy but from django perspective (in code) table Text has a column dummy that's why it throws an error.
Solution A workaround is to put a flag in say settings.py
IS_RUNNING = False
and in manage.py add the following
from app import settings
if 'runserver' in sys.argv:
settings.IS_RUNNING = True
and put your cache code after a flag check
if settings.IS_RUNNING:
cached_languages = models.Text.objects.all()
then django won't try to get records while making migrations before applying them. The cache algorithm will only execute when you actually call runserver.
How does Isolation dependencies between mongdb and django work?
I have made several projects with JAVA/SPRING, and the recent days,
I am studying Python django .
I successed to get connection between django and sqlite, and few days ago,
when I tried to connect to mongodb, it is hard to seperate dependencies database and django because of django-admin.
Django-admin require to attain specific Fields to each model, however, every database has each their own Field properties. Therefore, when project should change database structure, we should change a lot of code in model.py.
e.g
What if sqlite to Mongodb? only using different driver cannot make server work. e.g models.TextField(sqlite) -> models.StringField(mongodb). It is unavoidable, right? It seems difficult that solating dependencies completely between database and django
Is it Okay? do I miss something?
What if sqlite to Mongodb? only using different driver cannot make server work. e.g models.TextField(sqlite) -> models.StringField(mongodb). It is unavoidable, right? It seems difficult that solating dependencies completely between database and django
TextField and StringField isn't where you will have problems since it is supported in almost all databases, but consider this library django-mongodb-engine, it reuses the basic fields that already exist in Django ORM to the extent of what's possible, e.g.
class Post(models.Model):
title = models.CharField() <-- both Django ORM and mongodb-engine have this
text = models.TextField() <-- both Django ORM and mongodb-engine have this
This model will work as is both in SQL and MongoDB engines, but if you use a MongoDB-only (as in not in default Django ORM engine) feature like ListField()
class Post(models.Model):
title = models.CharField()
text = models.TextField()
tags = ListField() # <-- not supported everywhere
Then you migration to a SQL engine will involve some manual work to map that field.
Therefore, when project should change database structure, we should change a lot of code in models.py. Is it Okay?
Typically yes, to change the database structure you make changes in models.py. After which you would be running a migration, which is a step that generates scripts to alter the database (e.g. adding a new SQL table column). For MongoDB there's no explicit migration, as its schema is flexible (or schemaless if you prefer).
As for the admin, it's fairly smart when it comes to Django models, you may need to define the models and fields you want to appear in the admin, but in the detail view you don't have to worry about every single field, as Django admin understands them based on the information in models.py
And to change database drivers, it's the DATABASES value in settings.py
I am just learning Django, I have created a model inside an app Book
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=50)
read = models.CharField(max_length=50)
Now I want to generate it's correspondence SQL sentence with the help of
python manage.py sql books
But it's showing me error
CommandError: App 'Books' has migrations. Only the sqlmigrate and sqlflush commands can be used when an app has migrations.
I have used makemigrartion and migrate command it's showing no migration is remaining.
Can anyone have any idea regarding to this error?
Since there is still a bit of backwards compatibility with django 1.6 and below you can still use the sql commands from django-admin. However, you have to delete the migrations folder first.
To get the create statements you need to remove the migrations folder
rm -rf books/migrations
Then you can run the sql statement
./manage.py sql books
Should give you something like this:
BEGIN;
CREATE TABLE "books_book" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"title" varchar(100) NOT NULL,
"author" varchar(50) NOT NULL,
"read" varchar(50) NOT NULL
)
;
COMMIT;
However if what you are after is the select statements. Add back your migrations folder:
mkdir books/migrations/
Then do your create migrations and migrate commands.
From there open up the shell:
./manage.py shell
In the shell you can create a queryset and print the query:
from books.models import Book
print Book.objects.all().query
With that you should get an output like this:
SELECT "book_book"."id", "book_book"."title", "book_book"."author", "book_book"."read" FROM "book_book"
Those are a couple of ways to get sql back, depending on what you are trying to generate. The great thing about the queryset in the shell is you can make that as complex as possible and do a print of the .query and it gives it to you.
Hmm, interesting. Right now, there are two ways of turning models into SQL. The old syncdb method, which will ultimately be removed, and the new migrations method. The old sql* commands were based on the first method, and won't generally work the same way with the migrations approach. So I think this is a technical limitation (though perhaps it's philosophical as well).
Probably the best way to accomplish this is to first squash your migrations (in most cases this should produce a single migrations file) and then generate the SQL for that new migration with the sqlmigrate command.
Inside the app, there will be a directory for migrations where the django will store your model changes as migrations files.
To see the query you have to use the command python manage.py sqlmigrate {your_app_name;{eg :polls}} {migrations_file_name:{eg:0001_init.py}}
command:
python manage.py sqlmigrate polls 0001
Hope this will help
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?