Django south datamigrations not running post saves - django

I am using django south data-migrations to update data in new tables after schema-migrations that create some new tables. I have written some post-save methods on existing tables to update data on newly created tables. For this, I am using data-migrations and in forward method, I am saving existing table rows so that in post-saves, new tables will get data populated.
However, the post saves dont run after running the data migrations.
One way is to call the post-save function directly from forward method in datamigrations. But south documentations recommends that you should use orm objects to freeze the state. But in post-save methods, we will be using these models normally. Another way is to copy same code in migration but that way, everytime I make changes in post-save method, I also need to update code in datamigration forward method.
What is the best way to achieve this?

Migration files are just Python modules. You can always import code from other parts of the project hence reusing logic.
That however is a slippery slope because:
Lets say you have a migration which migrates database from state X to state Y (and backwards). Now lets say this migration reuses some code from foo.py. Now after some time you need to change your db state from state Y to state Z. If again you reuse some logic from foo.py, then you can no longer execute your first migration on a fresh db since some logic is shared between 2 migrations.
If you leave the migration code completely independent, it will make it much easier to maintain many migrations in a long run, even though it can introduce some code duplication.

Related

Declarative mechanism for Django model rows

With some frequency, I end up with models who contents are approximately constant. For example, I might have a set of plans that users can sign up for, with various attributes -- ID, name, order in the list of plans, cost, whether the purchaser needs to be a student/FOSS project/etc.. I'm going to rarely add/remove/change rows, and when I do there's likely going to be code changes too (eg, to change landing pages), so I'd like the contents of the model (not just the schema) to be managed in the code rather than through the Django admin (and consequently use pull requests to manage them, make sure test deploys are in sync, etc.). I'd also like it to be in the database, though, so I can select them using any column of the model, filter for things like "show me any project owned by a paid account", etc..
What are good ways of handling this?
I think my ideal would be something like "have a list of model instances in my code, and either Django's ORM magically pretends they're actually in the database, or makemigrations makes data migrations for me", but I don't think that exists?
The two workable approaches that come to mind are to either write data migrations by hand or use regular classes (or dicts) and write whatever getters and filters I actually want by hand.
Data migrations give me all the Django ORM functionality I might want, but any time I change a row I need to write a migration by hand, and figuring out the actual state involves either looking in the Django admin or looking through all the data migrations to figure out their combined impact. (Oh, and if somebody accidentally deletes the objects in the database (most like on a test install...) or a migration is screwy recovering will be a mess.)
Just using non-ORM classes in the source is a clearer, more declarative approach, but I need to replacements for many things I might normally do in the ORM (.objects.get(...), __plan__is_student, .values(plan__is_student).annotate(...), etc.).
Which of these approaches is better presumably depends on how much ORM functionality I actually want and how often I expect to be changing things.
Are there other good approaches for this? Am I missing some Django feature (or add-on) that makes this easier?

Things to do when remove a model from Django 1.7+

I want to know if any one could give a complete list of things which need to be done when we want to remove a model from Django. I know that a similar question was asked. But it seems to be several years ago, when people were still using South to deal with Database. So I expect an answer for the recent version of Django.
I conclude what I know as follows:
Delete the codes for model from model.py
Make sure that no other file imports this model or uses them
(admin.py, views.py, etc)
Run makemigrations and migrate commands
Since Django doesn't clean database for you, you delete the table of
this model manually from you database
Also note that there is a table called ContentTypes, which keeps
records about the info our your every model. So you need to delete
the record for this model manually (But I don't know how to do it
exactly. Would any one give some explanation?)
These are all the things I know. Is there anything wrong? And did I forget anything? Maybe I'm over-cautious, but I'd like to keep the database clean.
Thanks a lot!
In Django 1.7, this is actually much simpler than you think. Let's say you have an app, books, with two models: Book and BookReview. You want to remove the Book model.
Remove all references to the Book model in your code. For example, remove the ForeignKey('books.Book') field on the BookReview model. There is no need to make a separate migration for this change.
Remove the code for the Book model from books/models.py. Now, create a migration (manage.py makemigrations). If you look at the migration that is generated, it should include a migrations.DeleteModel operation.
Run the auto-generated migration (manage.py migrate), and you should be asked about the relevant ContentType objects that are no longer needed:
Running migrations:
Applying books.0002_auto_20150314_0604... OK
The following content types are stale and need to be deleted:
books | book
Any objects related to these content types by a foreign key will also
be deleted. Are you sure you want to delete these content types?
You probably do want to delete the content types. If you don't want to be asked for input, you can use manage.py migrate --noinput.
The DeleteModel operation in this migration will drop the books_book table in your database, so you don't have to worry about manually cleaning up at all.

Rails remove table

Using rails 4 and generated a table and then did a rake db:migrate to add the table to my schema.rb. However, I have destroyed the table, which removed its model and views but it still seems to appear in my schema.rb file, which is due to the migration. Is it safe to simply remove the lines from my codebase in sublime or is there a particular method for handling this in terminal.
You should create another migration that will revert the effects of previous one. That is, on up it will drop that table.
Of course, if you don't have existing production installation to care about, then you can just delete the original migration file, recreate database and pretend that table never existed.
If you do have existing database with important data, then full recreation is not an option, write the reverse migration.

Django -- add model to database without losing data

I have a simple Django website (just a form, really) which asks a few questions and saves the data in a SQL database using Model.save(). Pretty simple. I want to add a model to do page counting, though -- it'll just be a single object with a field that gets incremented each time the page's view function is called.
Now, I know little to nothing about SQL. I imagine this is not terribly difficult to do, but I would like to avoid losing or breaking all my data because of a slight misunderstanding of how the database works. So how can I go about doing this? I've heard of some third-party apps that will implement such functionality, but I'd like to do it myself just for learning purposes.
I don't understand why your existing data would be affected at all. You're talking about adding a completely new table to the database, which is supported within Django by simply running manage.py syncdb. The case where that doesn't work is when you're modifying existing tables, but you're not doing that here.
I must say though that learning and using South would be of benefit in any case. It's good practice to have a tool that can maintain your model tables.
(Plus, of course, you would never lose any data, because your database is backed up, right? Right?)
Since you're adding new model, you can just run syncdb and it will create new table for your model. If you were to change existing model, then you'd need to manually update database schema using "ALTER TABLE" statements or use South instead.

How do I make changes to a model in Django?

How does Django handle changes to my Model? Or, what help does it offer me to do this?
I am thinking of a situation where I have already have published data to my DB which I don't want to lose, but I need to make changes to my data model - for example, adding extra fields to a particular class, changing the types of fields, etc. My understanding is that syncdb won't ever alter tables that already exist in the DB.
For example, let's say I have the following model:
class Person(models.Model):
name = models.CharField(max_length=200)
phone_number=models.CharField(max_length=200)
hair_colour=CharField(max_length=50)
Things I might want to do to Person off the top of my head:
I wish to add an 'age' field.
I realise I want to use IntegerField instead of CharField for phone_number (whether this is a good idea or not, is out of scope...) - assuming it's possible.
I realise that I no longer wish to define hair_colour 'inline' within Person, because several people share the same hair colour - I wish instead to change this to be a foreign key to some other model.
Whilst I can imagine some of these are tough/impossible for the framework to 'guess' exactly what needs to be done to my data if all I do is update the models.py, I can imagine that there might still be some tooling to help enable it - does it exist?
In particular I imagine there must be some good patterns for option 1.
I'm very new to Django and have no experience with any other ORM-type stuff, which I think this is - I've always been a bit suspicious of ORMs, mainly for the reasons above :)
Django itself will not attempt to modify an already created database table. What you are trying to do is typically called "Migration" and there are a couple of different Database Migration tools available for Django.
South
Schema Migrations
Data Migrations
Backwards Migrations
Nash Vegas
Schema Migrations
Data Migrations
Django Evolution
Schema Migrations
Data Migrations (Unknown)
Backwards Migrations (Unknown)
Of the three South is probably the most widely used but they each have different ways of dealing with migrations. You can see more details on the comparison on Django Packages.
Much of what you're asking about can be done with the django project South. You add it as an INSTALLED_APP. Create a baseline, then as your model changes it creates SQL statements to convert your tables and the rows with-in the tables to the new model format.