Is there any way to alter add table column in django? - django

Table name is TestTable. How can I add a new column to the table which is hold in markAtrr variable?
Means how can I perform this query in django?
ALTER TABLE table_name
ADD column_name column_definition;
def createTest(request):
markAttr=request.POST.get('Attr')
obj=TestTable()

I feel you need to read the documentation harder, or work through the tutorials again.
A django Model subclass describes a database table. After you have created it for the first time you run the management commands
./manage.py makemigrations
and if there are no errors to fix,
./manage.py migrate
this latter creates a new table for your app in the database, connected to your model definition.
If you want to add a column to that model (or delete a column, or change the attributes of a column) you editing the model definition to add a field (column definition) and then again makemigrations and upon success, migrate. Your forms, views etc. can then be modified to use the column/field which migration has added or altered.

Related

Dynamic Model in Django from fields data in another model

I am working on a project where I have 2 models model
class Customer(models.Model):
name = models.CharField(...)
...
class CustomerProperty(models.Model):
name = models.CharField(...)
type = models.CharField(...)
code = models.CharField(...)
The CustomerProperty table has rows inside based on a parquet file (created at database init, not changed later on). For column in the parquet file, CustomerProperty has a row with column name from parquet as name in the table.
Now for some other purpose, I need to copy over all the data in the parquet file inside the db. So, for each row in the CustomerProperty table, this new table will have a column (plus one column for foreign key to Customer) so I can run filters based on property values. This will also be copied over at db init and not change later on, so it is an unmanaged django model.
I can't find any good docs on this, how to create a django model dynamically or how to add fields to that model dynamically. I don't need it to be managed, no need of migrations or django admin view support. I only need it to work with django ORM and be able to join and filter on it.
I've read the docs and didn't find much. Most of the answers talk about why this is a bad idea but I don't see any other way of solving my problem (I have few other tables joined together to run a complex query and I need to do further filtration based on these properties and support pagination.

What is a "state operation" and "database operation" in SeparateDatabaseAndState?

This is an extension to this question: Move models between Django (1.8) apps with required ForeignKey references
The Nostalg.io's answer worked perfectly. But I still can't get what is a "state operation" and "database operation" and what actually is going on when using SeparateDatabaseAndState.
A bit tough topic and not enough clear explanations out there, so here are my 50 cents.
It's all about state of your application models. What's a state? Imagine you have an app with a model MyModel and some migrations:
# app/migrations/
# 001.py
CreateModel(name='MyModel')
# 002.py
AddField(name='total', field=models.IntegerField)
# 003.py
RemoveField(name='total', field=models.IntegerField)
When you call manage.py makemigrations app, Django looks through all changes in app/migrations/001.py...003.py to get what's expected to be in your model - i.e. the state of the model. So, state is roughly a combined result of your migrations. If it differs from what you have in your MyModel class in app/models.py, makemigrations creates new migration with corresponding change. Like if MyModel class currently has total field, while in last migration it was removed, Django creates a migration with AddField() operation. Unlike what people often think, makemigrations does NOT look at actual database table.
Normal migration operation changes both state and database: CreateModel() tells Django "hey Django, this migration adds new table" and performs "CREATE TABLE" on the database.
SeparateDatabaseAndState is needed when you need to do different things to the state and to the database (or may be you need to modify just one of them).
Let's look at example from Django docs, where they change existing ManyToMany relation to "through" model. They had model Author and model Book with M-M relation:
class Book(models.Model):
authors = models.ManyToManyField(Author)
But now you want to have a through-model AuthorBook - optionally with some extra fields in it:
class AuthorBook(models.Model):
...
class Book(models.Model):
authors = models.ManyToManyField(Author, through=AuthorBook)
But you don't want new table - you want to use existing core_book_authors table which Django created automatically, and you want data in it.
So you create a migration with SeparateDatabaseAndState operation with database_operations and state_operations.
operations = [
migrations.SeparateDatabaseAndState(
database_operations=[
migrations.RunSQL(
sql='ALTER TABLE core_book_authors RENAME TO core_authorbook',
reverse_sql='ALTER TABLE core_authorbook RENAME TO core_book_authors',
),
],
state_operations=[
migrations.CreateModel(name='AuthorBook'),
]
),
]
In database_operations they rename existing M-M table according to new model name. That's the only thing you actually need to do with the database, unless you're adding new field to AuthorBook at the same time.
state_operations with CreateModel() tells Django: "this migration adds new table" (actually it does not - as we know from database_operations, it renames existing table). But because of this state_operations our new model gets into the state and Django knows this model is "created" and will not try to create it on next makemigrations call.
So, in SeparateDatabaseAndState operation, database_operations affect the database and not the state, state_operations affect the state and not the database.

Is it safe to make a empty field non-empty for a existing database?

Hi, I'm trying to alter my current django project schema, the data migration tool is south. django version is 1.6.9.
It is a existing database so I don't want to mess up with my historical data.
What I'm trying to alter is making a blank=true field non-empty(blank=false)
here is my model class:
class Post(DraftableModel, EditTrackingModel):
title = models.CharField(max_length=120,
verbose_name='headline')
description = models.CharField(max_length=260,
blank=True,
verbose_name='lead-in',
help_text="260 character limit")
/*rest of the code*/
I want change the description from models.CharField(blank=True) to models.CharField(blank=False), which is the default blank value
considering the existence of my database, some of my old Post model do have empty description.
After my migration and change of database schema, will my database be corrupted?
When you try to migrate, django will warn you about those empty fields. so you have few options.
You can add a default value in your model like default="Some Default Value" and django will chose that default value for all empty fields on migration.
You can just send the migrate request and on the terminal, django will ask you to add an one-off value to be added to all the empty fields.
Also you can edit the migrate files and add different values for those empty fields based on conditions you have in mind.
You can write a function to check for all the empty fields for exiting rows and add some data based on some conditions.
Also i highly recommend to make a backup first. Doesn't matter how small the changes are or how good you are in coding.

Calling loaddata in Django 1.7 migrations is throwing "Unknown column '[field]' in 'field list'"

I'm running into an issue in Django 1.7 when attempting to write multiple migrations in a row. Here's the basic setup of the migrations:
Initial schema migration to create the models for an app
Data migration that calls loaddata on a specific fixture that contains one-time default data
A new optional field was added to one of the models, so it's a schemamigration to add the field
If I generate the first migration, run it, generate the second, run it, and then add the new field, generate the third migration, and run it, everything is fine. However, if my database were on migration #1 and then I pulled down from a source repository, migration 2 would fail because it uses the models from models.py when calling loaddata rather than the models as of the time of that migration. It then produces the following error:
"Unknown column '[field]' in 'field list'"
In this case, [field] is the new field that I added for migration #3. The error makes sense, because my database doesn't have the new field yet but loaddata expects it to be there (even though the fixture doesn't reference the new field), but is there any way to make loaddata use the database at the time of the migration rather than the current state in models.py? Or are there any other ways to get around this issue?
Thanks.
I ended up writing a hack to get around this for now, but I feel like there has to be a better way. Instead of calling loaddata in the migration, I now call this function:
def load_fixture_in_data_migration(apps, schema_editor, fixture_filename, migration_file):
"""
Load fixture data in data migrations without breaking everything
when the models change later on
"""
fixture_dir = os.path.abspath(os.path.join(os.path.dirname(migration_file), '../fixtures'))
fixture_file = os.path.join(fixture_dir, fixture_filename)
fixture = open(fixture_file, 'rb')
objects = serializers.deserialize('json', fixture, ignorenonexistent=True)
for obj in objects:
ObjApp = apps.get_model(obj.object._meta.app_label, obj.object._meta.object_name)
new_obj = ObjApp(pk=obj.object.pk)
for field in ObjApp._meta.fields:
setattr(new_obj, field.name, getattr(obj.object, field.name))
new_obj.save()
fixture.close()
And I call it like this from the data migration:
load_fixture_in_data_migration(apps, schema_editor, 'initial_add_ons.json', __file__)
Does anyone know a better way to do this? It feels really like a hack since I have to access object meta data to accomplish this.

Using South to convert ForeignKey TO ManyToManyField not working out

I am using South to change a ForeignKey TO ManyToManyField in one of the models in Django but it is not working out as expected.
# Original Schema
class Item(models.Model):
category = models.ForeignKey(Category, default=default_category)
To be changed to
# Original Schema
class Item(models.Model):
category = models.ManyToManyField(Category, default=default_category)
So after commenting out the ForeignKey line in the model I do,
python manage.py schemamigration affected_model --auto
? The field 'Item.category' does not have a default specified, yet is NOT NULL.
? Since you are removing this field, you MUST specify a default
? value to use for existing rows. Would you like to:
? 1. Quit now, and add a default to the field in models.py
? 2. Specify a one-off value to use for existing columns now
? 3. Disable the backwards migration by raising an exception.
? Please select a choice:
I am confused by this because 1. I have specified a default value which is "default_category" and 2. I am not removing any field I am just changing it to ManyToManyField. My question is how to go ahead in this case? Is there any other trick to make this conversion using South?
BTW I am using South 0.7 and Django 1.1.1
Thanks for the help.
In fact you are removing the field. Foreignkeys are represented by a column in your database that in that case would be named category_id. ManyToMany relationships are represented by a "through" table. With django you can either specif the through table or have one generated for you automatically.
This is a very nontrivial migration and you will need to hand code it. It will require a bit of understanding what the underlying database representation of your model is.
You will require 3 migrations to cleanly do this. First create a schemamigration with a dummy manytomany relationship to hold your data.
Then create a datamigration to copy the foreignkey relationships to your dummy manytomany
Finally create schemamigration to delete the foreignkey and rename the dummy manytomany table.
Steps 2 and 3 will both require you to manually write the migrations. I should emphasize this is a very nontrivial style of migration. However, it's entirely doable you just have to really understand what these relationships mean to the database more than your average migration. If you have little or no data it would be much simpler to just drop the tables and start over fresh with your migrations.