I am new to Django and am trying to create a simple CRUD for an existing table in a database.
The thing is, that database is not local and I do not want Django to create its built-in tables in it -- I want it to create its tables in a local database. The correct way to do that is by using database routers, right?
I created an app myapp, and declared the external table I want to write the CRUD for in its models.py.
Now, I have written two routers (in two separate files) -- one that routes myapp to the external database (the DataRouter), and another one that routes all other requests to the local database (the SystemRouter). Is that the correct way to do that? Where should I place those files? I have tried placing them in multiple different directories inside my project, but can't make the DATABASE_ROUTERS list in settings.py find them.
For example, if I place them in the root directory for the project and make:
DATABASE_ROUTERS = ['DataRouter', 'SystemRouter']
I get:
ImportError: DataRouter doesn't look like a module path
I am really lost. Is that the best way to solve my problem? How do I route the data correcty?
Related
I have a Django app named app1 with models and migrations files.
I renamed this app to app2 and I fixed all imports, urls etc...
I now have a problem with migrations files and data in tables.
How can I write migrations with the correct way to ensure:
New installation => create the new tables
Update old versions => create new tables, move data, remove old tables
Note 1: there is several tables with many Foreign Keys.
Here is my progress so far and I am not sure if I am on the good way:
I removed all older migrations
I ran python manage.py makemigrations to generate new migrations files
After these 2 steps, I can install my application but I still have problems with old version.
Question: What is the best way to migrate data?
Note 2: I don't use South.
I found a solution that's works
Fix old migrations with new Foreign Keys and new app dependencies.
Force old migrations to create tables with old app name, so for that in migrations.CreateModel.options, add db_table: 'app1_table_name'
In each migration file add replaces = [('app1', 'migration_file_name')]. This will tell to Django that current migration (app2.migration_file_name) will replace the old file, this will prevenent django to execute migrations twice.
Create a migration file to rename tables with migrations.AlterModelTable
This is eloquently answered in this blog post.
The bullet points are:
Rename the folder of the application you want to update.
Update any and import statements to the folder you updated.
Update entries for the django_content_type table to refer to the application's app_label.
Update the table names of any models you haven't explicitly set the table name of. These table names inferred by the application name and need to be updated.
Update entries for the django_migrations table and update the reference for each migration by setting the app field your new app label.
Update any namespaced folder names that are within your /static or /templates folder. For example, you might have
./foo_app/templates/foo_app/index.html and it should be updated to ./bar_app/templates/bar_app/index.html.
Renaming an app is always a tricky issue.
If you do the migration like a simple table renaming migration, at any moment the apps.get_model() for the old app cannot work because the app simply doesn't exist.
I found this answer. I know you are not using south, but I think it might work the same way, just skip the south steps.
Basically, you have to:
Dump the data, before rename, into a json file
Run the script in the answer to rename references in the json file from the app1 to app2
Rename app1 to app2 (all import references, settings.py, etc)
Run the migrations to create the tables for app2
Load the data from json file to the database
Drop the app1 tables
I hope this help.
I was just wondering why each project does not just have one model.py file, considering its just a file full of classes ( acting as database tables), because the whole project runs on one database, why can there be more than one models.py file if all files work with the same database?
Thanks.
So that the apps can be taken and used with a different database if desired without needing to modify the code (much).
Django is set up to have projects that are collections of reusable, self contained apps. Each has its own model.py because they're tied closely to the views and templates for that app but may not be needed for the rest of the project.
Ususally you will start writing one app. Once in a time, you will recognize that there are features which are not very tightly related (e.g. user management or different sub-parts). Additionally, your models.py will start to be lengthy and want to have a clearer structure.
This is the point in time where you start splitting your project in independent sub-parts - the apps. Still, they will work with the same database. And even better: some friendly guys might have built apps whih you can include in your project - each bringing teir models and - of course - interacting with your database.
If everything in yourproject is closely related, there is no need for different apps.
I want to create a table, and then a list of data that should be inserted into that table. Does South have the capability to do such a thing? If so, do you have any reference as to show me how this can be done?
I want to be able to do this because at this point, it seems like the only way to have the 'exact' same data is to manually insert them into the database ourselves.
I want some 'nice' automated way of inserting rows in a table.
You can! It's called a "data migration".
There are plenty of times you might want to use one: the link above gives a good example, another is the "data migration for every Django project":
from south.v2 import DataMigration
from django.conf import settings
class Migration(DataMigration):
def forwards(self, orm):
Site = orm['sites.Site']
site = Site.objects.get(id=settings.SITE_ID)
site.domain = settings.DOMAIN_NAME
site.name = settings.SITE_NAME
site.save()
(this picks up the domain and site name from settings.py, for use with the sites framework)
You'd want to use fixtures.
Create a fixtures directory in your app's folder.
Create a dictionary file in that folder, intial_data.json (or XML/YAML)
Populate the file with the data you'd want to insert. Example
Run manage.py loaddata <fixturename>, where <fixturename> is the name of the fixture file you've created.
South handles this pretty much the same way, but it seems like Django's core approach is more documented.
I am refactoring a Django application. Specifically, I have an application with a big models.py file and I am trying to split it into a bunch of small files, like
myapp/
models/
__init__.py
somemodels.py
someothers.py
somemore.py
...
and in models/__init__.py I import all models from all other files so that I do not have to change client code.
The problem is that Django now complains about table names. Table for model Foo used to be myapp_foo, but it seems that Django now looks for a table myapp.models_foo. That is, it seems that it uses as prefix the package where the models are defined instead of their application (of course myapp.models is not registered as a Django application).
I know I could manually set the table name for each and every models, but is there a way to avoid this and tell Django that these models are actually part of myapp?
Use Meta.app_label
Think of this:
You create a CMS of some sort, which asks you for an application name and a csv file for that application.
Then it automatically creates that app on the fly, creates the required model.py based on the csv columns, activates the admin page for it and allows only you to have the full permission to this new table via django admin, then it inserts the the app into the url.py and creates the view.py for it as well.
Then all you'd have to do is upload a csv, name your app and whola!, you have an admin page to play with.
Now, is there anyway to create an app or at least a model.py out of a csv file in django or is there any django-app that can do this?
Note: Look beyond (./manage.py inspectdb > models.py)
While this does not involve creating an actual models.py and application, you may want to look into dynamically creating Model classes at runtime. You could have "meta" models that store the information on the dynamic models, and then have your CSV view import the data into those models, create the classes, and register them with the admin. Or something like that.
Creating an actual application directory, with models.py, views.py, and so on, is fairly easy (just create the directory, create the files, and write formatted strings to them based on the CSV data). Editing the project's settings.py and urls.py, and reloading the modules, wouldn't be too difficult either. But, I wouldn't trust automatically generated Django applications without first looking at them.