# TypeError: fromisoformat: argument must be str

**URL:** <https://forum.djangoproject.com/t/typeerror-fromisoformat-argument-must-be-str/12034>\
**Category:** Using the ORM\
**Created:** [February 8, 2022, 9:59am UTC](https://forum.djangoproject.com/t/typeerror-fromisoformat-argument-must-be-str/12034 "2022-02-08T09:59:11Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Sammeeey](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/sammeeey/32/7340_2.png) [@Sammeeey](https://forum.djangoproject.com/u/Sammeeey)\
**Post date:** [February 8, 2022, 9:59am UTC](https://forum.djangoproject.com/t/typeerror-fromisoformat-argument-must-be-str/12034/1 "2022-02-08T09:59:11Z")

</div>

Hi,  
I am facing the following `TypeError`, when running py manage.py migrate:

```auto
(venv) PS C:\Users\Name\codingprojects\CoderMatching\codermatching> py manage.py migrate  
System check identified some issues:

WARNINGS:
?: (mysql.W002) MariaDB Strict Mode is not set for database connection 'default'
        HINT: MariaDB's Strict Mode fixes many data integrity problems in MariaDB, such as data truncation upon insertion, by escalating warnings into errors. It is strongly recommended you activate it. See: https://docs.djangoproject.com/en/4.0/ref/databases/#mysql-sql-mode
Operations to perform:
  Apply all migrations: admin, auth, codermatch, contenttypes, sessions
Running migrations:
  Applying codermatch.0031_alter_ad_expirationtime_alter_ad_projectstartdate...Traceback (most recent call last):
  File "C:\Users\Name\codingprojects\CoderMatching\codermatching\manage.py", line 22, in <module>   
    main()
  File "C:\Users\Name\codingprojects\CoderMatching\codermatching\manage.py", line 18, in main       
    execute_from_command_line(sys.argv)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\core\management\ __init__.py", line 425, in execute_from_command_line
    utility.execute()
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\core\management\ __init__.py", line 419, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\core\management\base.py", line 373, in run_from_argv
    self.execute(*args, **cmd_options)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\core\management\base.py", line 417, in execute
    output = self.handle(*args, **options)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\core\management\base.py", line 90, in wrapped
    res = handle_func(*args, **kwargs)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\core\management\commands\migrate.py", line 253, in handle
    post_migrate_state = executor.migrate(
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\migrations\executor.py", line 126, in migrate
    state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial) File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\migrations\executor.py", line 156, in _migrate_all_forwards
    state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\migrations\executor.py", line 236, in apply_migration
    state = migration.apply(state, schema_editor)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\migrations\migration.py", line 125, in apply
    operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\migrations\operations\fields.py", line 225, in database_forwards
    schema_editor.alter_field(from_model, from_field, to_field)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\backends\base\schema.py", line 618, in alter_field
    self._alter_field(model, old_field, new_field, old_type, new_type,
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\backends\base\schema.py", line 746, in _alter_field
    new_default = self.effective_default(new_field)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\backends\base\schema.py", line 334, in effective_default
    return field.get_db_prep_save(self._effective_default(field), self.connection)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\models\fields\ __init__.py", line 839, in get_db_prep_save
    return self.get_db_prep_value(value, connection=connection, prepared=False)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\models\fields\ __init__.py", line 1293, in get_db_prep_value
    value = self.get_prep_value(value)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\models\fields\ __init__.py", line 1288, in get_prep_value
    return self.to_python(value)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\models\fields\ __init__.py", line 1250, in to_python
    parsed = parse_date(value)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\utils\dateparse.py", line 76, in parse_date
    return datetime.date.fromisoformat(value)
TypeError: fromisoformat: argument must be str

```

The migration look like this:

```auto
(venv) PS C:\Users\Name\codingprojects\CoderMatching\codermatching> py manage.py makemigrations     
Migrations for 'codermatch':
  codermatch\migrations\0034_alter_ad_expirationtime.py
    - Alter field expirationTime on ad

```

### models.py

```auto
class Ad(models.Model):
    expirationTime = models.DateTimeField('expiration time (of ad)', default=timezone.now() + datetime.timedelta(days=30))
    #... some other properties

```

### settings.py

```auto
# Internationalization
# https://docs.djangoproject.com/en/4.0/topics/i18n/

LANGUAGE_CODE = 'de-de'

TIME_ZONE = 'Europe/Berlin'

USE_I18N = True

USE_TZ = True

```

I really don’t understand what’s the issue here.  
From my point of view the error message and the traceback aren’t helpful at all…  
I may only assume that this is caused by the expirationTime property in the Ad model, since it’s the only field mentioned, when running `py manage.py makemigrations`

Maybe someone has a suggestion?

---

<div class="post-metadata">

**Author:** ![adamchainz](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/adamchainz/32/26_2.png) [@adamchainz](https://forum.djangoproject.com/u/adamchainz)\
**Post date:** [February 8, 2022, 10:25am UTC](https://forum.djangoproject.com/t/typeerror-fromisoformat-argument-must-be-str/12034/2 "2022-02-08T10:25:37Z")

</div>

> [@Sammeeey](#):
>
> ```
> expirationTime = models.DateTimeField('expiration time (of ad)', default=timezone.now() + datetime.timedelta(days=30))`
> 
> ```

Not the bug you’re experiencing, but this definition is probably not what you intend. `timezone.now()` will be evaluated once at import time, and a fixed date determined. So if you server stays up for 7 days, the expiry date will then be in 23 days time. If it stays up 31 days, the expiry date will be yesterday.

What you instead want is a callable default:

```auto
def in_30_days():
     return timezone.now() + timedelta(days=30)

class Ad(...):
     ... = models.DateTimeField(..., default=in_30_days)

```

Django will call this function when it creates a new instance, so each instance will get +30 days from the time you created this.

If you do this you’ll hit a different path, which should mean you don’t hit the particular bug you’re seeing.

> [@Sammeeey](#):
>
> ```auto
> ?: (mysql.W002) MariaDB Strict Mode is not set for database connection 'default'
> HINT: MariaDB's Strict Mode fixes many data integrity problems in MariaDB, such as data truncation upon insertion, by escalating warnings into errors. It is strongly recommended you activate it. See: https://docs.djangoproject.com/en/4.0/ref/databases/#mysql-sql-mode
> 
> ```

Don’t ignore this! I was partially responsible for this warning making its way into Django.

---

<div class="post-metadata">

**Author:** ![adamchainz](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/adamchainz/32/26_2.png) [@adamchainz](https://forum.djangoproject.com/u/adamchainz)\
**Post date:** [February 8, 2022, 10:30am UTC](https://forum.djangoproject.com/t/typeerror-fromisoformat-argument-must-be-str/12034/3 "2022-02-08T10:30:15Z")

</div>

> [@adamchainz](#):
>
> Not the bug you’re experiencing, but this definition is probably not what you intend. `timezone.now()` will be evaluated once at import time, and a fixed date determined. So if you server stays up for 7 days, the expiry date will then be in 23 days time. If it stays up 31 days, the expiry date will be yesterday.

FYI you should also be seeing this check message that warns against this bug:

```auto
...Ad.expirationTime: (fields.W161) Fixed default value provided.
	HINT: It seems you set a fixed date / time / datetime value as default for this field. This may not be what you want. If you want to have the current date as default, use `django.utils.timezone.now`

```

Unless you put `W161` in your `SILENCED_SYSTEM_CHECKS`

---

<div class="post-metadata">

**Author:** ![Sammeeey](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/sammeeey/32/7340_2.png) [@Sammeeey](https://forum.djangoproject.com/u/Sammeeey)\
**Post date:** [February 9, 2022, 3:44pm UTC](https://forum.djangoproject.com/t/typeerror-fromisoformat-argument-must-be-str/12034/4 "2022-02-09T15:44:26Z")

</div>

Thank you for the quick reply Adam!

> [@adamchainz](#):
>
> `timezone.now()` will be evaluated once at import time, and a fixed date determined. So if you server stays up for 7 days, the expiry date will then be in 23 days time. If it stays up 31 days, the expiry date will be yesterday.

I thought that my definition of `default=timezone.now() + datetime.timedelta(days=30)` always creates an instance with the current time plus 30 days.  
Honestly I was already wondering why it’s always altered when calling `py manage.py makemigrations`.

I just wanted to describe, why it works for me by showing you the different timestamps of objects in my database.  
But along the way I realized, that even if I create objects in the shell they will all have the same `expirationTime`:

```python
# objects already in database before:
>>> ads = Ad.objects.all() 
>>> for ad in ads: ime te)
... print(ad.expirationTime)
... 
2022-02-11 07:30:44.036332+00:00
2022-02-11 07:30:44.036332+00:00
2022-02-11 07:30:44.036332+00:00
2022-02-11 07:30:44.036332+00:00
2022-02-11 07:30:44.036332+00:00
2022-02-14 06:37:07+00:00       
2022-02-20 07:11:04+00:00       
2022-02-22 06:47:54.104425+00:00
2022-02-22 07:23:24.417796+00:00
2022-02-22 07:27:41.230062+00:00
2022-02-22 08:02:22.279783+00:00
2022-02-22 08:02:22.279783+00:00
2022-02-23 07:21:50.931785+00:00
2022-02-23 08:56:08.720499+00:00
2022-02-23 08:56:08.720499+00:00
2022-02-23 08:56:08.720499+00:00
2022-02-24 12:58:31.475272+00:00
2022-02-24 13:10:20.509282+00:00
2022-02-24 13:13:55.324877+00:00
2022-02-24 13:22:04.863970+00:00
2022-02-27 06:52:29.463663+00:00
2022-02-27 06:52:29.463663+00:00
2022-02-27 07:09:34.572881+00:00
2022-02-27 07:10:25.415602+00:00
2022-02-28 23:32:35.943372+00:00
2022-02-28 23:32:35.943372+00:00
2022-02-28 23:36:01.314277+00:00
2022-02-28 23:36:25.137725+00:00
2022-02-28 23:37:33.127609+00:00
2022-02-28 23:38:53.338604+00:00
2022-02-28 23:38:53.338604+00:00
2022-02-28 23:38:53.338604+00:00
2022-03-01 00:13:07.788984+00:00
2022-03-01 00:13:07.788984+00:00
2022-03-01 07:00:56.857355+00:00
2022-03-01 07:07:38.445522+00:00
2022-03-01 08:28:08.078065+00:00
2022-03-01 08:28:38.855122+00:00
2022-03-01 08:28:38.855122+00:00
2022-03-01 14:52:20.143607+00:00
2022-03-01 14:52:20.143607+00:00
2022-03-01 15:51:17.024533+00:00
2022-03-02 17:03:12.778584+00:00
2022-03-03 07:01:54.826885+00:00
2022-03-03 07:01:54.826885+00:00
2022-03-03 07:01:54+00:00
2022-03-03 10:43:28.610037+00:00
2022-03-03 10:43:28.610037+00:00
2022-03-03 10:51:08.047444+00:00
2022-03-03 11:33:02.518281+00:00
2022-03-03 11:33:02.518281+00:00
2022-03-03 11:42:45.651000+00:00
2022-03-03 11:42:45.651000+00:00
2022-03-03 13:02:57.146329+00:00
2022-03-03 13:02:57.146329+00:00
2022-03-03 13:02:57.146329+00:00
2022-03-03 13:02:57.146329+00:00
2022-03-03 13:02:57.146329+00:00
2022-03-03 13:02:57.146329+00:00
2022-03-03 13:02:57.146329+00:00
2022-03-03 13:02:57.146329+00:00
2022-03-04 06:22:43.667378+00:00
2022-03-04 07:07:39.222599+00:00
2022-03-04 07:11:18.155299+00:00
2022-03-04 07:17:55.524739+00:00
2022-03-04 07:20:45.652661+00:00
2022-03-04 11:29:31.495141+00:00
2022-03-04 11:29:31.495141+00:00

# add new object to the database
>>> newAd = Ad(projectTitle='testexpirationTimestamp')
>>> newAd.save()
>>> print(newAd.expirationTime)  
2022-03-11 14:41:13.813310+00:00

#add another new object to the database (few minutes lates)
>>> newAd = Ad(projectTitle='testexpirationTimestamp2')
>>> newAd.save()
>>> print(newAd.expirationTime)  
2022-03-11 14:41:13.813310+00:00

```

So in this case the `expirationTime` seems to be based on the time when the shell was started, right?  
Since all objects which I create in the same shell instance will have the same `expirationTime`.

**Thank you very much** for pointing this out!🙏

I haven’t deployed an app which is based on my own ideas and logic.  
But from based on your statement I understand the following:

Once I deploy the app the server would behave similar to the django shell in this case.  
It would save the time at which I deployed the app and alter the `expirationTime` property once at that time.  
So that every Ad object (created at any time after deployment) would always have this one `expirationTime`, right?

* * *

> [@adamchainz](#):
>
> FYI you should also be seeing this check message that warns against this bug:
> 
> ```auto
> ...Ad.expirationTime: (fields.W161) Fixed default value provided.
> HINT: It seems you set a fixed date / time / datetime value as default for this field. This may not be what you want. If you want to have the current date as default, use `django.utils.timezone.now`
> 
> ```
> 
> Unless you put `W161` in your `SILENCED_SYSTEM_CHECKS`

If I make the check, I don’t see warnings:

```python
(venv) PS C:\Users\Name\codingprojects\CoderMatching\codermatching> py manage.py check
System check identified no issues (0 silenced).

```

* * *

> [@adamchainz](#):
>
> If you do this you’ll hit a different path, which should mean you don’t hit the particular bug you’re seeing.
> 
> > [@Sammeeey](#):
> >
> > ````auto
> > > ?: (mysql.W002) MariaDB Strict Mode is not set for database connection 'default'
> > HINT: MariaDB's Strict Mode fixes many data integrity problems in MariaDB, such as data truncation upon insertion, by escalating warnings into errors. It is strongly recommended you activate it. See: https://docs.djangoproject.com/en/4.0/ref/databases/#mysql-sql-mode
> > > ```
> > 
> > ````
> 
> Don’t ignore this! I was partially responsible for this warning making its way into Django.

Thank you for pointing this out, too!  
I didn’t consider this to be an issue.  
Because I don’t remeber a point in the development, where this did not appear.  
So I was assuming that this is just normal.  
Besides I am not even using MariaDB.  
I am working on a MySQL database.  
But it’s the first time for me building my own web app (without just following a tutorial).  
And it’s especially the first time for me using a database which is not SQLite (Because people on the internet seem to agree, that you shouldn’t use SQLite for apps where users can create, update or delete data.

---

<div class="post-metadata">

**Author:** ![adamchainz](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/adamchainz/32/26_2.png) [@adamchainz](https://forum.djangoproject.com/u/adamchainz)\
**Post date:** [February 9, 2022, 4:08pm UTC](https://forum.djangoproject.com/t/typeerror-fromisoformat-argument-must-be-str/12034/5 "2022-02-09T16:08:18Z")

</div>

> [@Sammeeey](#):
>
> So in this case the `expirationTime` seems to be based on the time when the shell was started, right?

Yes it is defined at _import time_. So once per Python process.

> [@Sammeeey](#):
>
> So that every Ad object (created at any time after deployment) would always have this one `expirationTime` , right?

Yes, although your web server may also restart occasionally in production.

> [@Sammeeey](#):
>
> If I make the check, I don’t see warnings:

Ensure you’re on the latest django and you don’t have that in your settings. I don’t know which django version added this warning off the top of my head.

> [@Sammeeey](#):
>
> I didn’t consider this to be an issue.  
> Because I don’t remeber a point in the development, where this did not appear.

This is called “warning fatigue”. Ignore warnings long enough and your brain tunes them out. But someone put the message there for a reason 🙂

> [@Sammeeey](#):
>
> Besides I am not even using MariaDB.  
> I am working on a MySQL database.

On most linux distributions MySQL is an alias for MariaDB. You may be using MariaDB without even know it. I’d be surprised if Django’s detection logic was wrong.

> [@Sammeeey](#):
>
> And it’s especially the first time for me using a database which is not SQLite (Because people on the internet seem to agree, that you shouldn’t use SQLite for apps where users can create, update or delete data.

It’s actually fine to use SQLite up to a reasonable level of traffic: [Appropriate Uses For SQLite](https://sqlite.org/whentouse.html)

You can get streaming backups with Litestream: [https://litestream.io/](https://litestream.io/)

I’ve been meaning to play with SQLite in production myself, since finding out about Litestream.

---

<div class="post-metadata">

**Author:** ![Sammeeey](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/sammeeey/32/7340_2.png) [@Sammeeey](https://forum.djangoproject.com/u/Sammeeey)\
**Post date:** [February 10, 2022, 8:54am UTC](https://forum.djangoproject.com/t/typeerror-fromisoformat-argument-must-be-str/12034/6 "2022-02-10T08:54:08Z")

</div>

> [@adamchainz](#):
>
> What you instead want is a callable default:
> 
> ```auto
> def in_30_days():
> return timezone.now() + timedelta(days=30)
> 
> class Ad(...):
> ... = models.DateTimeField(..., default=in_30_days)
> 
> ```

I’ve implemented it like this now:

```python
class Ad(models.Model):
    ...
    def in30Days():
        return timezone.now() + datetime.timedelta(days=30)
    ...
    expirationTime = models.DateTimeField('expiration time (of ad)', default=in30Days)

```

Every time I create a new Ad object now, it really has the current time.

* * *

I’ve solved the `mysql.W002` by adding `OPTIONS` to my `DATABASES` in settings.py (as [recommended in the error message](https://docs.djangoproject.com/en/4.0/ref/databases/#mysql-sql-mode):

```python
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'codermatchingdb',
        'USER': 'root',
        'PASSWORD': 'secret😉',
        'HOST': '127.0.0.1',
        'PORT': '',
        'OPTIONS': {
            'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
        }
    }
}

```

* * *

> [@adamchainz](#):
>
> Ensure you’re on the latest django and you don’t have that in your settings. I don’t know which django version added this warning off the top of my head.

My settings.py has:

```auto
Generated by 'django-admin startproject' using Django 4.0.1.

```

and on the other hand (from my venv):

```python
>>> import django
>>> django.VERSION
(4, 0, 1, 'final', 0)

```

* * *

> [@adamchainz](#):
>
> This is called “warning fatigue”. Ignore warnings long enough and your brain tunes them out. But someone put the message there for a reason

Thank you! I’ll keep that in mind 🙂

* * *

> [@adamchainz](#):
>
> It’s actually fine to use SQLite up to a reasonable level of traffic: [Appropriate Uses For SQLite](https://sqlite.org/whentouse.html)

Thank you for the hint.  
Maybe I’ll consider switching to SQLite, if I am facing more issues which hinder the actual coding.

* * *

## TypeError still an issue

However I am still facing the `TypeError: fromisoformat: argument must be str` in the `Running migrations` when calling `py manage.py migrate` ([see above](https://forum.djangoproject.com/t/typeerror-fromisoformat-argument-must-be-str/12034)).  
When I google for it I always only find issues, which where solved with the callable default.

---

<div class="post-metadata">

**Author:** ![adamchainz](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/adamchainz/32/26_2.png) [@adamchainz](https://forum.djangoproject.com/u/adamchainz)\
**Post date:** [February 10, 2022, 9:25am UTC](https://forum.djangoproject.com/t/typeerror-fromisoformat-argument-must-be-str/12034/7 "2022-02-10T09:25:08Z")

</div>

> [@Sammeeey](#):
>
> ## TypeError still an issue
> 
> However I am still facing the `TypeError: fromisoformat: argument must be str` in the `Running migrations` when calling `py manage.py migrate` ([see above](https://forum.djangoproject.com/t/typeerror-fromisoformat-argument-must-be-str/12034)).  
> When I google for it I always only find issues, which where solved with the callable default.

I think you may need to edit your historical migrations then. It’s probably being caused by one of the defaults you placed in an old migration. It should be safe to edit the `default` field being set in old migrations, since you now have a correct default being set in a new migration.

---

<div class="post-metadata">

**Author:** ![Sammeeey](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/sammeeey/32/7340_2.png) [@Sammeeey](https://forum.djangoproject.com/u/Sammeeey)\
**Post date:** [February 10, 2022, 3:44pm UTC](https://forum.djangoproject.com/t/typeerror-fromisoformat-argument-must-be-str/12034/8 "2022-02-10T15:44:49Z")

</div>

Thank you.  
Inspired by the latest migration I amended the historical migrations from something like…

```python
import datetime
from django.db import migrations, models
from django.utils.timezone import utc

class Migration(migrations.Migration):
    ...
    operations = [
        migrations.AlterField(
            model_name='ad',
            name='expirationTime',
            # note that the following DateTimeField has a fixed time as default
            field=models.DateTimeField(default=datetime.datetime(2022, 3, 12, 7, 56, 7, 340439, tzinfo=utc), verbose_name='expiration time (of ad)'),
        ),
    ]

```

to something like…

```python
import codermatch.models
from django.db import migrations, models

class Migration(migrations.Migration):
    ...
    operations = [
        migrations.AlterField(
            model_name='ad',
            name='expirationTime',
            # note that the following DateTimeField has a callable function which provides a "dynamic" time - as recommended above by Adam 
            field=models.DateTimeField(default=codermatch.models.Ad.in30Days, verbose_name='expiration time (of ad)'),
        ),
    ]

```

* * *

Besides I _cleared up_ the migrations by deleting several trivial ones - for example those ones which always only altered the expirationTime to the current time.

* * *

### new error: django.db.utils.DataError: (1265, “Data truncated for column ‘projectStartDate’ at row 50”)

Now I have a new error when calling `py manage.py migrate`:

```auto
(venv) PS C:\Users\Name\codingprojects\CoderMatching\codermatching> py manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, codermatch, contenttypes, sessions
Running migrations:
  Applying codermatch.0034_alter_ad_expirationtime... OK
  Applying codermatch.0042_alter_ad_expirationtime... OK
  Applying codermatch.0043_alter_ad_projectstartdate...Traceback (most recent call last):
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\backends\utils.py", line 85, in _execute
    return self.cursor.execute(sql, params)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\backends\mysql\base.py", line 73, in execute
    return self.cursor.execute(query, args)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\MySQLdb\cursors.py", line 206, in execute
    res = self._query(query)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\MySQLdb\cursors.py", line 319, in _query
    db.query(q)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\MySQLdb\connections.py", line 254, in query
    _mysql.connection.query(self, query)
MySQLdb._exceptions.DataError: (1265, "Data truncated for column 'projectStartDate' at row 50")

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\Name\codingprojects\CoderMatching\codermatching\manage.py", line 22, in <module>
    main()
  File "C:\Users\Name\codingprojects\CoderMatching\codermatching\manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\core\management\ __init__.py", line 425, in execute_from_command_line
    utility.execute()
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\core\management\ __init__.py", line 419, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\core\management\base.py", line 373, in run_from_argv
    self.execute(*args, **cmd_options)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\core\management\base.py", line 417, in execute
    output = self.handle(*args, **options)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\core\management\base.py", line 90, in wrapped
    res = handle_func(*args, **kwargs)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\core\management\commands\migrate.py", line 253, in handle
    post_migrate_state = executor.migrate(
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\migrations\executor.py", line 126, in migrate
    state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\migrations\executor.py", line 156, in _migrate_all_forwards
    state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\migrations\executor.py", line 236, in apply_migration
    state = migration.apply(state, schema_editor)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\migrations\migration.py", line 125, in apply
    operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\migrations\operations\fields.py", line 225, in database_forwards
    schema_editor.alter_field(from_model, from_field, to_field)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\backends\base\schema.py", line 618, in alter_field
    self._alter_field(model, old_field, new_field, old_type, new_type,
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\backends\base\schema.py", line 775, in _alter_field
    self.execute(
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\backends\base\schema.py", line 151, in execute
    cursor.execute(sql, params)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\backends\utils.py", line 99, in execute
    return super().execute(sql, params)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\backends\utils.py", line 67, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\backends\utils.py", line 76, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\backends\utils.py", line 85, in _execute
    return self.cursor.execute(sql, params)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\backends\utils.py", line 85, in _execute
    return self.cursor.execute(sql, params)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\django\db\backends\mysql\base.py", line 73, in execute
    return self.cursor.execute(query, args)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\MySQLdb\cursors.py", line 206, in execute
    res = self._query(query)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\MySQLdb\cursors.py", line 319, in _query
    db.query(q)
  File "C:\Users\Name\codingprojects\CoderMatching\venv\lib\site-packages\MySQLdb\connections.py", line 254, in query
    _mysql.connection.query(self, query)
django.db.utils.DataError: (1265, "Data truncated for column 'projectStartDate' at row 50")

```

Since I’ve already marked a solution for the issue of the thread, the forum adviced me to open a new thread.  
Shall I open a new thread or does this still fit in here?

---

<div class="post-metadata">

**Author:** ![adamchainz](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/adamchainz/32/26_2.png) [@adamchainz](https://forum.djangoproject.com/u/adamchainz)\
**Post date:** [February 10, 2022, 6:33pm UTC](https://forum.djangoproject.com/t/typeerror-fromisoformat-argument-must-be-str/12034/9 "2022-02-10T18:33:19Z")

</div>

It’s fine here.

What is `0043_alter_ad_projectstartdate` doing to `projectStartDate`?

Truncating data means removing characters that have been stored, e.g. if you had a `varchar(8)` storing “abcdabcd” then tried to migrate it to `varchar(6)`, the last two characters would be truncated, so MySQL prevents that.

Can you perhaps figure out why that migration tries to do something so unsafe, and modify eithre the stored data or the migrration to prevent the error?

---

<div class="post-metadata">

**Author:** ![Sammeeey](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/sammeeey/32/7340_2.png) [@Sammeeey](https://forum.djangoproject.com/u/Sammeeey)\
**Post date:** [February 10, 2022, 7:54pm UTC](https://forum.djangoproject.com/t/typeerror-fromisoformat-argument-must-be-str/12034/10 "2022-02-10T19:54:09Z")

</div>

> [@adamchainz](#):
>
> What is `0043_alter_ad_projectstartdate` doing to `projectStartDate` ?

This is what it does:

```python
from django.db import migrations, models

class Migration(migrations.Migration):

    dependencies = [
        ('codermatch', '0042_alter_ad_expirationtime'),
    ]

    operations = [
        migrations.AlterField(
            model_name='ad',
            name='projectStartDate',
            field=models.DateField(blank=True, verbose_name='project started (date)'),
        ),
    ]

```

This is how `projectStartDate` looks:

```python
class Ad(models.Model):
    ...
    projectStartDate = models.DateField('project started (date)', blank=True)

```

After deleting several rows in the database, Django now complains about the row 49:

```auto
django.db.utils.DataError: (1265, "Data truncated for column 'projectStartDate' at row 49")

```

And every time I delete a line it complains about another one.

I’ve exported the database from phpmyadmin.  
And I’ve deleted the lines in the beginning. So that the line numbers fit the rows.  
So row 49 is the one with the NULL value:

 ![grafik](https://us1.discourse-cdn.com/flex026/uploads/djangoproject/original/2X/9/91aba027dce10bdd48c998b40fa94aa0a0e7a0e6.png)

Therefore I thought that the NULL value is a problem.

### add null=True

I’ve amended the projectStartDate to have `null=True`:

```python
class Ad(models.Model):
    ...
    projectStartDate = models.DateField('project started (date)', blank=True, null=True)

```

`py manage.py makemigrations` results in a new migration:

```python
...
class Migration(migrations.Migration):
...
    operations = [
        migrations.AlterField(
            model_name='ad',
            name='projectStartDate',
            field=models.DateField(blank=True, verbose_name='project started (date)'),
        ),
    ]

```

### delete row 49 (including NULL value)

Then I’ve deleted the object in row 49 from my phpmyadmin.

`py manage.py migrate` then results in:  
`django.db.utils.DataError: (1265, "Data truncated for column 'projectStartDate' at row 59")`  
After deletion of row 49, row 59 is the first one having a NULL for projectStartDate.

If I change the NULL value of row 59 (id 67) to a date (using the calender widget in phpmyadmin) and then running `py manage.py migrate` again, the output says:  
`django.db.utils.DataError: (1265, "Data truncated for column 'projectStartDate' at row 62")`

 ![grafik](https://us1.discourse-cdn.com/flex026/uploads/djangoproject/original/2X/a/ac14c5d6a47e1e9c563208d7f2d1b4d29d594f1c.png)

As you may presume, row 62 then is the first one in the database with a NULL in projectStartDate.  
If I change the value of row 59 back to NULL, the error occurs there again.

**Therefore I assume that Django (or MySQL) has a problem with the NULL values now**.  
But I don’t understand why.  
🤔Since I’ve just defined `null=True`, which should make NULL values in the database possible - in my understanding…

#### By the way

In this case it’s actually not a huge problem.  
If I just create a new database (which I can easily do, since I don’t have important data in the database so far) and connect my Django project to this one, I don’t have this issue anymore.

The reason why I am trying to investigate this further is:  
I think it’s good to learn how to solve those kind of issues while I am not working with sensitive or important data in a deployed project.  
But rather now while I it’s not too much of a problem (actually).  
Do you think it’s good to do it and learn it like this?  
Or do you think that it’s better to focus on the actual development of the application and solve problems (which might be considered trivial) later😅?
