Django BooleanField default for mysql - mysql

I am using Django 1.7 with MySQL.
I have an existing model that I want to add a BooleanField to. I want the field to default to true. Seems simple enough right? So I create my field like so:
class MyModel(models.Model):
my_field = models.BooleanField(default=True)
Then I run makemigrations and I get the following migration generated:
operations = [
migrations.AddField(
model_name='mymodel',
name='myfield',
field=models.BooleanField(default=True),
preserve_default=True,
),
]
Looks legit, however when I apply the migration the field created in my database does not have the default value, it looks like this:
my_field tinyint(1) NOT NULL,
Now, when I apply the migration existing records have the field set to 1 but what I want is for the migration to create a field that defaults to true, or 1. What am I missing here? Could anyone shed some light on what I am doing incorrectly? Any advice would be appreciated, thanks much!

Django never sets the default on a database level. If you want to support the default in legacy code, you can add a RunSQL operation to your migration that adds the default to the database column.

Related

(1054, "Unknown column '' in 'field list'")

I know this question has been asked a couple of time but no previous answer was able to solve my problem.
I had a perfectly working model in Django that looked like this:
class Template(models.Model):
mat = models.CharField(max_length=50, null=True)
...
I had many instances of this model and up to now I was very happy with it. I recently decided that instead of a Charfield, this model was better suited to work with a ForeignKey in this position instead.
To get into details, the attribute ''mat'' was previously only referring to the name of another object instance. I decided to change it to the full fledged instance with a ForeignKey instead, like it should have always been. Therefore, the model was modified as follows:
class Template(models.Model):
mat = models.ForeignKey(Stock, on_delete=models.CASCADE, related_name='mat_stock', verbose_name="mat", null=True)
...
I followed this change with the regular */manage.py makemigrations, */manage.py migrate. While these two commands worked, I was unable to select any instance of Template in the shell without raising the following error:
OperationalError: (1054, "Unknown column 'myapp_template.mat_id' in 'field list'")
Similar situations I encountered were solved by manually adding a column in SQL with the following line:
ALTER TABLE database.myapp_template ADD mat INT;
Unfortunately this did not solve my problem.
I figured maybe the problem was that I already had instances of my object that had character values in the ''mat'' column. Django would expect integer values (specifically "id") after my migration, so I decided to create a completely new attribute for Template as follows:
class Template(models.Model):
pos_mat = models.ForeignKey(Stock, on_delete=models.CASCADE, related_name='mat_stock', verbose_name="mat", null=True)
...
This, I thought, would delete (or disregard) the "mat" column and create new "pos_mat" columns with the desired properties without having to handle old character values that wouldn't fit with the requirements. From there on it should be like adding a completely new ForeignKey attribute.
After the required and successful */manage.py makemigrations, */manage.py migrate I am still unable to access an instance of my model in the shell. I still get the same unpleasing:
OperationalError: (1054, "Unknown column 'myapp_template.mat_id' in 'field list'")
Would anybody know how to convince Django to go along with my changes? I am skeptical that rolling back migrations to zero will help me (it did not solve my problems in the past) and I hope it will not come to the deletion of my data. It is acceptable for my model to have an empty field in this column since I added a null=True to my attribute.
Thank you very much for your help. Have a good day.
I have solved my problem by rolling back to my last stable migration. From there I was able to migrate a model where 'mat' was absent and 'pos_mat' was the only attribute. This means my problem arose in the first migration from the old version of 'mat' to the new version of 'mat'. Basically keeping the same name but changing the attribute characteristics is a no go. I hope those with the same problem will be able to fix it with this.

How to Alter Blob to Varchar in Laravel Make:Migration

I need to change a Blob field type to a Varchar(128). The data in the field will fit the target field size, it's text, and shouldn't have a problem with UTF-8.
Sample data, all data is in this format:
{"weight":"0","height":"0","width":"0","length":"0"}
I'm using Laravel Make:migrate to handle the conversion.
How should I write the SQL?
I know how to write a Laravel Migration. I also know how to alter a field. But a Blob isn't a text field nor is a Blob normally converted down to a Varchar. I've done some manual UTF-8 conversion of Blobs in the past and know you can mess up your data if you don't do it right. So my concern here is to not mess up my data with a Laravel Migrate. I don't believe the migrate 'down' method can undo corrupted data.
If my data fits the varchar target size and if the data fits the UTF-8 charset, am I good with a straight forward Alter statement:
DB::query("ALTER TABLE DB1.products CHANGE COLUMN dimensions dimensions varchar(128) DEFAULT NULL;");
You shouldn't use sql for this, just create a migration and use change method
Schema::table('table_name', function ($table) {
$table->string('column_name')->change();
});
https://laravel.com/docs/5.7/migrations#modifying-columns
Considering your comment sql would be
ALTER TABLE tablename MODIFY column_name VARCHAR(128);
Run composer install and then composer update in the console and
drop your table from the database and also delete the migration ,then create a new migration using
php artisan make:migration change_col_datatype --table=table_name
and then make changes as below
Schema::table('your_table_name', function ($table) {
$table->string('your_table_name');
});
public function down()
{
Schema::dropIfExists('tablename');
}
The SQL statment:
\DB::statement('ALTER TABLE products CHANGE COLUMN dimensions dimensions VARCHAR(128) DEFAULT NULL;');
Worked fine.

Doctrine schema update always try to add NOT NULL

I have a fresh Symfony 2.8 installation, with doctrine and MySQL 5.6 stack.
After executing a doctrine:schema:update --force, i can see
Database schema updated successfully! "x" queries were executed
Here is my problem : Even if i execute it multiple time, doctrine always find schema differences.
With the --dump-sql, i can see that all of these queries are related to :
adding NOT NULL on string primary key
adding NOT NULL on datetime
field
However, when i check my database, these columns already have a NOT NULL.
Here is an example on a single property/column :
class MyEntity
{
/**
* #ORM\Id
* #ORM\Column(type="string", length=5, name="cd_key")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $code;
...
Here is the result of a SHOW CREATE TABLE my_entity; :
CREATE TABLE `my_entity` (
`cd_key` varchar(5) COLLATE utf8_unicode_ci NOT NULL,
`label` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`number` int(11) NOT NULL,
PRIMARY KEY (`cd_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ;
And here the query doctrine try to execute with the doctrine:schema:update command :
ALTER TABLE my_entity CHANGE cd_key cd_key VARCHAR(5) NOT NULL;
I clean my Symfony cache between each command execution.
I try to add nullable=false on #Column annotation (event if it's already defined as an #Id), but no effect.
a doctrine:schema:validate don't find any mapping problem (except sync of course)
I try to drop and recreate the full database, but no effet.
Any ideas ?
This issue has been reported in 2017 at least here, here and here and supposed to be fixed by this PR.
Updating doctrine/dbal would be the solution (not working for me though):
$ composer require doctrine/dbal:^2.7.1
Unsetting the server version (mysql/mariadb) from the configuration would also fix the problem (still not for me though).
If one is using migrations he can still adjust them manually (but his schema will always be unsynced).
I've encountered a similar problem. For me deleting the table using SQL and then running again DOCTRINE:SCHEMA:UPDATE --FORCE worked for me.
It seems that doing some SQL requests manualy confuses Doctrine.
Saying that, i'm assuming you've put #ORM\Table(name="my_entity") and #ORM\Entity(repositoryClass="myrepository") over your class definition ;).
Hope it helped.

CakePHP can't find table after creating a table

I create a table directly by a query. I only want to Import some data. Therefor i execute a query which is built dynamicly and i try execute this query in a Component-class. (I use a random existing model to execute this query is there a better why?)
$query= "CREATE TABLE IF NOT EXISTS testerdbs (
'Ü1' varchar(6) COLLATE utf8_swedish_ci DEFAULT NULL,
'Ü2' varchar(6) COLLATE utf8_swedish_ci DEFAULT NULL,
'Ü3' int(3) DEFAULT NULL,
'Ü4' varchar(6) COLLATE utf8_swedish_ci DEFAULT NULL,
'Ü5' date DEFAULT NULL
)"
$data = ClassRegistry::init('import_files');
$data->query($query);
This works fine.
In the same request i want to access the created table in the controller.
App::import('Model', "testerdb");
//$this->loadModel("testerdb");
$newTable = ClassRegistry::init("testerdb");
echo '<pre>', print_r($newTable->getColumnTypes()), '</pre>';
If I try to execute this in same request i always get the error:
Error: Table testerdbs for model testerdb was not found in datasource default.
If I do exactly the same request again, everything works fine...
I google about an hour and it seemed that cake cache the model. If I execute this request again cake cache again all the tables and than cake find my new table. So I hoped to load or import the created Table in the same request, but i don't work.
Is there another way to load the table? Where is my mistake?
Thanks for help!
This might be a bit stale, but I just spent the last week trying to work around the problem and maybe this will help someone.
The root problem is that the cache of table names is initialized before you created the temporary table, so the 'setSource' function returns an error that the temporary table does not exist.
The solution is to overrid the 'setSource' function for the Model that you are creating for 'testerdb' and remove the check on table existence (i.e. everything within the test:
if (method_exists($db, 'listSources'))' )
Your model definition should look something like this:
App::uses('AppModel', 'Model');
class testerdb extends AppModel {
public function setSource($tableName) {
$this->setDataSource($this->useDbConfig);
$db = ConnectionManager::getDataSource($this->useDbConfig);
$this->table = $this->useTable = $tableName;
$this->tableToModel[$this->table] = $this->alias;
$this->schema();
}
}
Many thanks to whomever posted the link below. This has worked with my CakePHP 2.0 instance.
http://web2.0goodies.com/blog/uncategorized/mysql-temporary-tables-and-cakephp-1-3/
Why would you only want to have a temporary table? I would just temporarily store whatever data you are importing in an in-memory model or data-structure.
If the table is not temporary, then just create it statically before you run your program.

Reset to MySQL DEFAULT value on update in CakePHP

I am wondering how to reset a field to the DEFAULT value (the one set in MySQL structure) when performing an update action in CakePHP. Like using the DEFAULT keyword in SQL:
INSERT INTO items (position) VALUES (DEFAULT);
edit: I am not searching for a way to use the default on create, I am rather looking for a way to reset the field to it's default when it has been already used.
You can simply unset the form input from the requested array, if you want to save its default value into the mysql database. You can try the following to achieve the same:
$item_details = $this->request->data;
unset($item_details['Item']['position']);
$this->Item->create();
$this->Item->save($item_details);
According to your edited question, if you want to reset any field during updating a record. you just need to use the MySql default() function.
$item_details = $this->request->data;
$this->Item->id = $item_details['Item']['id'];
$this->Item->saveField('position', DboSource::expression('DEFAULT(position)'));
To answer my own question, it could be done with:
$this->Item->saveField('position', DboSource::expression('DEFAULT(position)'));
or
$data['Item']['position'] = DboSource::expression('DEFAULT(position)');
$this->Item->save($data)
But - and here we go with the lost hours: to be able to use DboSource there had to be a database query before! Otherwise CakePHP throws the error Class 'DboSource' not found.