I am ready to start a new project with django,and it invloves some operations with database.I have 2 way to get the scheme:
use powerdesigner design the database scheme and output sql,then use python manage.py inspectdb to generate models.
design the model then use python manage.py makemigrations and python manage.py migrate to get the database scheme.
Does someone explain what this 2 ways' difference are and how should I choose?
From inspectdb's documentation:
Use this if you have a legacy database with which you’d like to use
Django. The script will inspect the database and create a model for
each table within it.
Its better if you already have a working DB and want to use django on it. It has limitations like:
If inspectdb cannot map a column’s type to a model field type, it’ll use TextField and will insert the Python comment 'This field
type is a guess.' next to the field in the generated model.
If the database column name is a Python reserved word (such as 'pass', 'class' or 'for'), inspectdb will append '_field' to the
attribute name. For example, if a table has a column 'for', the
generated model will have a field 'for_field', with the db_column
attribute set to 'for'. inspectdb will insert the Python comment
'Field renamed because it was a Python reserved word.' next to the
field.
Also its a shortcut method, not recommended for if you are starting django project.
Also writing models, running makemigration and migrate command will create database scheme containing custom fields such as :
auth_group
auth_group_permissions
auth_permission
auth_user
auth_user_groups
auth_user_user_permissions
Which are essential for django system if you want to use its authentication backend, User model etc which are core parts of django.
Related
I have a DB (lets call it data_db) containing some tables. I want to create a dashboard to present data from data_db, so I created a Django project for that purpose.
When I want to get data from one of the tables in data_db, is there a way to do it with Models? (I want Django security management with the DB) or do I have to use raw SQL?
One note: there is existing data in the data_db's table, and I don't want to create a new table with the same exact data on the default Django DB. I also use 2 DBs, Django default's and data_db and I created a database router for data_db to prevent Django from creating all its tables in there.
Thanks.
Yes. In fact Django can even help you create the models. Models that you do not migrate with the help of Django are unmanaged models. These have a managed = False attribute in the Meta class, so something like:
class MyModel(models.Model):
# … fields …
class Meta:
managed = False
If you thus write these unmanaged models, you can make queries with the Django ORM, without Django trying to create new models for these tables.
Of course, specifying models that match with the database is cumbersome. Therefore Django can often construct models based on the tables. You can generate the models with the inspectdb command [Django-doc].
You can generate these models on the stdout with:
python3 manage.py inspectdb
or you can save these to a file through I/O redirection:
python3 manage.py inspectdb > app_name/models.py
I have an existing database that I'm trying to access with Django. I used python manage.py inspectdb to create the models for the database. Currently I'm able to import the models into the python shell however when I try to access any of the actual objects in any way, I get this error OperationalError: (1054, "Unknown column 'some_table.id' in 'field list'"). I see that the table in the database in fact does not have an id field. How can I fix this? Do I need to update the managed field in the Meta class and run a migration so it can create this field automatically?
From the Django documentation: This feature is meant as a shortcut, not as definitive model generation. See the documentation of inspectdb for more information. (Reference: https://docs.djangoproject.com/en/1.8/howto/legacy-databases/)
You're going to need to manually clean up the models and migrate. The line you'll have to add for adding the "id" field is:
id = models.IntegerField(primary_key=True)
Warning: I'd definitely create a copy of the database to toy with, rather than the original. This will likely take you some trial and error to get right. After you're absolutely sure you have it right, you can changed Managed=True, but be VERY careful!
How do I make syncdb execute SQL queries (for table creation) defined by me, rather then generating tables automatically.
I'm looking for this solution as some particular models in my app represent SQL-table-views for a legacy-database table.
So, I've created their SQL-views in my django-DB like this:
CREATE VIEW legacy_series AS SELECT * FROM legacy.series;
I have a reverse engineered model that represents the above view/legacytable. But whenever I run syncdb, I have to create all the views first by running sql scripts, otherwise syncdb simply creates tables for them (if a view is not found).
How do I make syncdb run the above mentioned SQL?
There are 2 possible approaches I know of to adapt your models to a legacy database table (without using views that is):
1) Run python manage.py inspectdb within your project. This will generate models for existing database tables, you can then continue to work with those.
2) Modify your tables with some specific settings. First of all you define the table name in your model by setting the db_table option in your meta options. Secondly you define for each field the column name to match your legacy database by setting the db_column option. Note there are other db_ options listed you possibly could use to match your legacy database.
If you really want the views approach an (ugly) workaround is possible, you can define custom sql commands per application model. This file is found in "application"/sql/"model".sql . Django will call this sql's after it created all tables. You can try to specify DROP statements for the generated tables followed by your view create statement in this file. Note that this will be a bit tricky for the tables with foreign keys as django guarantees no order of execution of these files (so stuffing all statements in one .sql will be the easiest way I think, I've never tried this before).
You could use unmanaged models for your reverse-engineered models, and initial SQL scripts for creating your views.
EDIT:
A bit more detailed answer. When you use unmanaged models, syncdb will not create your database tables for you, so you have to take care of it yourself. An important point is the table name, and how django maps Model classes to table names, I suggest you read the doc on that point.
Basically, your Series model will look like that :
class Series(models.Model):
# model fields...
...
class Meta:
managed = False
db_table = "legacy_series"
Then, you can put your SQL commands, in the yourapp/sql/series.sql file :
### yourapp/sql/series.sql
CREATE VIEW legacy_series AS SELECT * FROM legacy.series;
You can then syncdb as usual, and start using your legacy models.
I have some models I'm working with in a new Django installation. Is it possible to change the fields without losing app data?
I tried changing the field and running python manage.py syncdb. There was no output from this command.
Renavigating to admin pages for editing the changed models caused TemplateSyntaxErrors as Django sought to display fields that didn't exist in the db.
I am using SQLite.
I am able to delete the db file, then re-run python manage.py syncdb, but that is kind of a pain. Is there a better way to do it?
Django does not ever alter an existing database column. Syncdb will create tables, but it does not do 'migrations' as found in Rails, for instance. If you need something like that, check out Django South.
See the docs for syndb:
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.
You have to change the column names in your DB manually through whatever administration tools sqlite provides. I've done this with MySQL, for instance, and since MySQL lets you change column names without affecting your data, it's no problem.
Of course there is.
Check out South
You'll have to manually update the database schema/layout, if you're only talking about adding/removing columns.
If you're attempting to rename a column, you'll have to find another way.
You can use the python manage.py sql [app name] (http://docs.djangoproject.com/en/dev/ref/django-admin/#sql-appname-appname) command to see what the new SQL should look like, to see what columns, of what type/specification Django would have you add, and then manually run corresponding ALTER TABLE commands.
There are some apps/projects that enable easier model/DB management, but Django doesn't support this out of the box, on purpose/by design.
Our website uses a PHP front-end and a PostgreSQL database. We don't have a back-end at the moment except phpPgAdmin. The database admin has to type data into phpPgAmin manually, which is error-prone and tedious. We want to use Django to build a back-end.
The database has a few dozen of tables already there. Is it possible to import the database schema into Django and create models automatically?
Yes it is possible, using the inspectdb command:
python manage.py inspectdb
or
python manage.py inspectdb > models.py
to get them in into the file
This will look at the database configured in your settings.py and outputs model classes to standard output.
As Ignacio pointed out, there is a guide for your situation in the documentation.
If each table has an autoincrement integer PK then you can use the legacy database instructions.