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
Related
We have two different groups working on the same Django database:
The web team
A team of data scientists
We'd like to make it easy for the data scientists to read/write to a subset of a tables using Django models but without giving them write/delete access to the rest of the tables.
Our current thought is that we'd like to lock down the tables in the data layer (Postgres) with GRANT and REVOKE style SQL statements, but we'd like to manage those permissions in the models.
We'd have two ROLES:
data_scientists_rw
web_team_admin
Instead of manually writing GRANT and REVOKE permissions in each migration, we'd like to have a decorator or a Meta class variable on a model so that when we makemigrations, it will automatically generate the correct SQL.
# data_scientists/models.py (pseudocode)
class DataScientistModel(models.Model):
...
my_special_number = models.FloatField()
...
class Meta:
data_science_team_editable = True
Make the migration:
$ ./manage.py makemigrations
Auto-generated model (pseudocode):
# migrations/0008_new_data_scientist_model.py
...
if data_science_team_editable:
RunSQL('GRANT INSERT, UPDATE, DELETE ON {tablename} TO data_scientists_rw;')
...
Questions:
Does this approach seem sensible?
How I do hook into makemigrations so that I can auto-generate the RunSQL code?
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.
Let's say I have the following table showing how the columns would be declared for a MySQL table: (I can't think of a very realistic example, so here's something that's so silly. This table is created with the help of Excel)
I want to create a model in Django that is compatible with the MySQL table I'll have with the columns declared this way. However, from looking at the Django documentation, I can't find any model field types that in SQL are the same format as those in the picture except for the primary key field.
I did see before that by default, Django handles a database that uses the SQLite Engine, but I want to see if it's possible to handle a database of MySQL tables.
Is there a way to create Django model field types, like MEDIUMINT, TINYTEXT, and SMALLINT, (in MySQL) that are compatible with tables created through MySQL? It's simply a way for me to use the tables that I created myself, not the tables that Django generates automatically once all the models are defined.
In Django you normally create the models and let the framework generate the tables for you. If you have a legacy database you can use python manage.py inspectdb to generate the models from the database (see the documentation). But if it isn't a legacy database and you've created it just now, you are fighting against the framework and making your life more complicated.
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.
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.