Migration: Creating UserProfile in Django/MySQL - python

I have created a UserProfile field in order to add a favorites functionality to my site. Using Django's recommendation, I created a UserProfile model as follows at the bottom
Unfortunately, I already had the rest of my database created, and so I need to either use a migration utility or manually edit my database. However, I do not have sufficient permissions to utilize a migration utility, so I have to edit the database directly, and am struggling to do so.
This answer is similar to what I want to accomplish, but I can't quite get the syntax to work in my case.
MySQL - One To One Relation?
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
favorites = models.ManyToManyField(Media, related_name='favorited_by')

In my experience, the best migration utility is South. Once you've installed and added it to your settings, you'll need to create initial migrations for your existing modules using
./manage.py schemamigration --initial my_module,
which will include the one containing your UserProfile model, then from there you can migrate using
manage.py migrate my_module.
The real power in using a utility like this is portability and reversibility. You can migrate forward and backward as needed, and you'll be able to bring your schema to virtually any SQL database without all the fuss of rebuilding using SQL directly.

I would certainly agree with Steves recommendation to use South.
However if you for some reason wouldn't want to, you can issue the following command:
python manage.py sql <appname>
This will output the SQL statements which django will use to create your tables. This can then be used to manually modify the database.

Related

How can I use one database with multiple django servers?

I saw lots of information about using multiple databases with one server but I wasn't able to find contents about sharing one database with multiple servers.
Using Micro Service Architectures, If I define a database and models in a django server, named Account, How can I use the database and models in Account server from another server named like Post??
What I'm thinking is to write same models.py in both servers and use the django commands --fake
Then, type these commands
python manage.py makemigrations
python manage.py migrate
and in another server
python manage.py makemigrations
python manage.py migrate --fake
I'm not sure if this would work and I wonder whether there is any good ways.
I doubt this is the best approach, but if you want two separate Django projects to use the same database you could probably create the first like normal then, in the second project, copy over all of the models.py and migration files. Django creates a database table behind the scenes to track which migrations have been applied, so as long as the apps, models, and migration files are identical in the second app it should work without having to fake any migrations.
That said, this sounds like a mess to maintain going forward. I think what I would do is create a single Django project that talks to the database, then create an API in that first project that all other apps can interface with to communicate with the database. That way you avoid duplicating code or having to worry about keeping multiple projects in sync.
When using additional Django servers with the same database that is already managed by the initial Django server, the tables don't need to be managed by the additional servers.
So you can add into the Meta for the models that managed = False and Django will not need to touch them, but can still use them. You will need to copy your models across to the additional servers, or use inspectdb (see below).
from django.db import models
class ExampleModel(models.Model):
id = models.IntegerField(db_column='db', primary_key=True)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
class Meta:
managed = False
db_table = 'example_table'
You will probably need to state the name of the table being referenced in the Meta as well, otherwise Django may generate a name that doesn't match the database.
You can even cut down the models when using them unmanaged.
It's not necessary to declare all the fields, just the ones you're using.
You can also use python manage.py inspectdb to automatically generate unmanaged models for all the tables in your database, saving time and ensuring the model fields conform to the actual database setup.
This is detailed in the documentation:
https://docs.djangoproject.com/en/4.0/ref/models/options/#managed
https://docs.djangoproject.com/en/4.0/ref/django-admin/#inspectdb
In my project, I have the same case that I have 2 Django servers and 1 database.
I did that I run on server 1
python manage.py makemigrations
and
python manage.py migrate
and on server 2 I just run:
python manage.py makemigrations
I did not run migrate commands on server 2
Now if there is any change on model then I run makemigrations command on both servers and migrate command on any of one server. I am using only one database

How to create a new table using model

So I have this django installation in which there are a bunch of migration scripts. They look like so:
00001_initial.py
00002_blah_blah.py
00003_bleh_bleh.py
Now I know these are "database building" scripts which will take stuff defined in models.py and run them against the db to "create" tables and stuff.
I want to create a new table(so I created its definition in models.py). For this, I have copied another model class and edited its name and fields and it is all fine. Lets call this new model class 'boom'.
My question is now how do I "create" this boom table using the migration script and the boom model?
I am worried that I might accidentally disrupt anything that is already in DB. How do I run the migration to create only boom table? How do I create a migration script specifically for it?
I know that it has something to do with manage.py and running migrate or runmigration (or is it sqlmigrate?...im confused). While creating the boom table, I dont want the database to go boom if you know what I mean :)
First, create a backup of your database. Copy it to your development machine. Try things out on that. That way it doesn't matter if it does go "boom" for some reason.
The first thing to do is
python manage.py showmigrations
This shows all the existing migrations, and it should show that they have been applied with an [X].
Then,
python manage.py makemigrations
Makes a new migration file for your new model (name 00004_...).
Then do
python manage.py migrate
to apply it. To undo it, go back to the state of migrations 00003, with
python manage.py migrate <yourappname> 00003
There are two steps to migrations in Django.
./manage.py makemigrations
will create the migration files that you see - these describe the changes that should be made to the database.
You also need to run
./manage.py migrate
this will apply the migrations and actually run the alter table commands in SQL to change the actual database structure.
Generally adding fields or tables won't affect anything else in the database. Be more careful when altering or deleting existing fields as that can affect your data.
The reason for two steps is so that you can make changes on a dev machine and once happy commit the migration files and release to your production environment. Then you run the migrate command on your production machine to bring the production database to the same state as your dev machine (no need for makemigrations on production assuming that your databases started the same).
My question is now how do I "create" this boom table using the
migration script and the boom model?
./manage.py makemigrations
I am worried that I might accidentally disrupt anything that is
already in DB.
The whole point of migrations, is that it doesn't
I know that it has something to do with manage.py and running migrate
or runmigration
For more information please refer to : https://docs.djangoproject.com/en/1.10/topics/migrations/
And rest assured that your database will not go boom! :-)
I solved it simply, changing the name of the new model to the original name, and then I checked if there is the table in the database, if not, I just create a new table with the old name with just a field like id.
And then clear migrations and create new migrations, migrate and verify table was fixed in DB and has all missing fields.
If it still doesn't work, then change the model name back to a new one.
but when django asks you if you are renaming the model you should say NO to get the old one removed properly and create a new one.
This type of error usually occurs when you delete some table in dB manually, and then the migration history changes in the tables are lost.
But it is not necessary to erase the entire database and start from scratch.

Migrating from auth_user in Django

I created a custom user model in Django and it worked up fine. However, I decided to create a custom model to suit my needs after the project was up and running.
As a result, I will need to migrate the schema (Currently, when I register a user, the code is still referencing to the the auth_user database tables where as the new custom user table is user.)
I have set the AUTH_USER_MODEL in settings.py to userapp.User, where userapp is my custom user app and User is the Model that inherits from the AbstractUser model.
I am fairly new to Django and cannot understand how to achieve this. One obvious way to clean install the database, which is not something that I'm looking to do as it will remove all my data.
How do I migrate then? I've heard South is used for that but I don't know how to use it. Besides I think South isn't required in the recent versions of Django.
My version of Django is 1.8.2.
I did this recently - we used a data migration to move between the two models. Rough steps:
Create the new user model (without telling Django about it), make/apply migrations to create the database table(s)
Write a the data-migration to copy the data over to the new user model. Then run this migration and update Django to use the new model
Now you should be switched over, and can delete/archive the old auth_user table as needed

In Django, how to create tables from an SQL file when syncdb is run

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.

Django: Change models without clearing all data?

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.

Categories