It's my first time doing tests in a Django app, and I don't understand my error. When i run python manage.py test, I got this error :
D:\Users\boucardale\Documents\code\djangotest>python manage.py test
You are in dev mode
Found 1 test(s).
Creating test database for alias 'default'...
Traceback (most recent call last):
File "D:\Users\boucardale\Documents\code\djangotest\venv\lib\site-packages\django\db\models\fields\__init__.py", line 1988, in get_prep_value
return int(value)
TypeError: int() argument must be a string, a bytes-like object or a number, not 'datetime.datetime'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "manage.py", line 21, in <module>
main()
File "manage.py", line 17, in main
execute_from_command_line(sys.argv)
File "D:\Users\boucardale\Documents\code\djangotest\venv\lib\site-packages\django\core\management\__init__.py", line 446, in execute_from_command_line
utility.execute()
File "D:\Users\boucardale\Documents\code\djangotest\venv\lib\site-packages\django\core\management\__init__.py", line 440, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "D:\Users\boucardale\Documents\code\djangotest\venv\lib\site-packages\django\core\management\commands\test.py", line 24, in run_from_argv
super().run_from_argv(argv)
File "D:\Users\boucardale\Documents\code\djangotest\venv\lib\site-packages\django\core\management\base.py", line 414, in run_from_argv
self.execute(*args, **cmd_options)
File "D:\Users\boucardale\Documents\code\djangotest\venv\lib\site-packages\django\core\management\base.py", line 460, in execute
output = self.handle(*args, **options)
File "D:\Users\boucardale\Documents\code\djangotest\venv\lib\site-packages\django\core\management\commands\test.py", line 68, in handle
failures = test_runner.run_tests(test_labels)
File "D:\Users\boucardale\Documents\code\djangotest\venv\lib\site-packages\django\test\runner.py", line 1000, in run_tests
old_config = self.setup_databases(
File "D:\Users\boucardale\Documents\code\djangotest\venv\lib\site-packages\django\test\runner.py", line 898, in setup_databases
return _setup_databases(
File "D:\Users\boucardale\Documents\code\djangotest\venv\lib\site-packages\django\test\utils.py", line 220, in setup_databases
connection.creation.create_test_db(
File "D:\Users\boucardale\Documents\code\djangotest\venv\lib\site-packages\django\db\backends\base\creation.py", line 79, in create_test_db
call_command(
File "D:\Users\boucardale\Documents\code\djangotest\venv\lib\site-packages\django\core\management\__init__.py", line 198, in call_command
return command.execute(*args, **defaults)
File "D:\Users\boucardale\Documents\code\djangotest\venv\lib\site-packages\django\core\management\base.py", line 460, in execute
output = self.handle(*args, **options)
File "D:\Users\boucardale\Documents\code\djangotest\venv\lib\site-packages\django\core\management\base.py", line 98, in wrapped
res = handle_func(*args, **kwargs)
File "D:\Users\boucardale\Documents\code\djangotest\venv\lib\site-packages\django\core\management\commands\migrate.py", line 290, in handle
post_migrate_state = executor.migrate(
File "D:\Users\boucardale\Documents\code\djangotest\venv\lib\site-packages\django\db\migrations\executor.py", line 131, in migrate
state = self._migrate_all_forwards(
File "D:\Users\boucardale\Documents\code\djangotest\venv\lib\site-packages\django\db\migrations\executor.py", line 163, in _migrate_all_forwards
state = self.apply_migration(
File "D:\Users\boucardale\Documents\code\djangotest\venv\lib\site-packages\django\db\migrations\executor.py", line 248, in apply_migration
state = migration.apply(state, schema_editor)
File "D:\Users\boucardale\Documents\code\djangotest\venv\lib\site-packages\django\db\migrations\migration.py", line 131, in apply
operation.database_forwards(
File "D:\Users\boucardale\Documents\code\djangotest\venv\lib\site-packages\django\db\migrations\operations\fields.py", line 108, in database_forwards
schema_editor.add_field(
File "D:\Users\boucardale\Documents\code\djangotest\venv\lib\site-packages\django\db\backends\sqlite3\schema.py", line 381, in add_field
self._remake_table(model, create_field=field)
File "D:\Users\boucardale\Documents\code\djangotest\venv\lib\site-packages\django\db\backends\sqlite3\schema.py", line 230, in _remake_table
self.effective_default(create_field)
File "D:\Users\boucardale\Documents\code\djangotest\venv\lib\site-packages\django\db\backends\base\schema.py", line 410, in effective_default
return field.get_db_prep_save(self._effective_default(field), self.connection)
File "D:\Users\boucardale\Documents\code\djangotest\venv\lib\site-packages\django\db\models\fields\related.py", line 1126, in get_db_prep_save
return self.target_field.get_db_prep_save(value, connection=connection)
File "D:\Users\boucardale\Documents\code\djangotest\venv\lib\site-packages\django\db\models\fields\__init__.py", line 910, in get_db_prep_save
return self.get_db_prep_value(value, connection=connection, prepared=False)
File "D:\Users\boucardale\Documents\code\djangotest\venv\lib\site-packages\django\db\models\fields\__init__.py", line 2668, in get_db_prep_value
value = self.get_prep_value(value)
File "D:\Users\boucardale\Documents\code\djangotest\venv\lib\site-packages\django\db\models\fields\__init__.py", line 1990, in get_prep_value
raise e.__class__(
TypeError: Field 'id' expected a number but got datetime.datetime(2022, 9, 16, 9, 7, 36, 977154).
Here is my test file:
from django.urls import reverse
import datetime
from django.test import TestCase
from django.core.management import call_command
from comptes.models import User
from projects.models import Project
class ProjectTest(TestCase):
def setUp(self):
call_command("init_config")
self.admin_user = User.objects.create(email="admin_user@fabdev.fr", username="admin_user")
self.admin_user.set_password('123456TEST')
self.admin_user.save()
self.standard_user = User.objects.create(email="standard_user@fabdev.fr", username="standard_user")
self.standard_user.set_password('123456TEST')
self.standard_user.save()
def test_ProjectCreate(self):
"""
Test qui vérifie la création d'un nouveau projet
"""
field = ['operations', 'state', 'name', 'eotp', 'creation_date', 'eotp_validation_date', 'analysis_date',
'end_date', 'entity', 'synthese', 'aoi', 'price', 'estimated_price', 'decision', 'decision_in_explorer',
'description', 'commentary', 'decision_level', 'decision_sheet', 'qualification', 'decision_number',
'decision_number_link', 'code_site', 'applicant', 'immobilisation_family_a', 'immobilisation_family_b',
'immobilisation_family_c', 'immobilisation_family_d', 'immobilisation_family_e', 'immobilisation_family_f',
'immobilisation_family_g', 'immobilisation_family_h', 'archived', 'last_editor', 'last_modification_date',
'related_projects', 'old_project_pk', 'copy', 'responsible', 'auto_created']
excpected = [None, 'Nouvelle décision - à traiter', 'test_project', 'TESTEOTP',
datetime.datetime.strptime("15/09/2022", "%d/%m/%y"),
datetime.datetime.strptime("15/09/2022", "%d/%m/%y"),
datetime.datetime.strptime("15/09/2022", "%d/%m/%y"),
datetime.datetime.strptime("15/09/2022", "%d/%m/%y"),
'GMR Dauphiné', None, None, 5, 5, 'decision', 'decision_in_explorer', 'description', 'commentary',
'Immobilisations', 'decision_sheet', 'CAPEX', 'decision_number', 'decision_number_link', 'SITEE',
'demandeur', True, True, False, False, False, True, False, False, False,
User.objects.get(username='standard_user'), datetime.datetime.now(), None, None, False,
User.objects.get(username='standard_user'), False]
self.client.login(username='standard_user', password='123456TEST')
url = reverse('project-create')
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
response = self.client.post(url, {'state': 'Nouvelle décision - à traiter',
'name': 'test_project',
'eotp': 'TESTEOTP',
'creation_date': datetime.datetime.strptime("15/09/2022", "%d/%m/%y"),
'eopt_validation_date': datetime.datetime.strptime("15/09/2022", "%d/%m/%y"),
'analysis_date': datetime.datetime.strptime("15/09/2022", "%d/%m/%y"),
'end_date': datetime.datetime.strptime("15/09/2022", "%d/%m/%y"),
'entity': 'GMR Dauphiné',
'synthese': None,
'aoi': None,
'price': 5,
'estimated_price': 5,
'decision': 'decision',
'decision_in_explorer': 'decision_in_explorer',
'description': 'description',
'commentary': 'commentary',
'decision_level': 'Immobilisations',
'decision_sheet': 'decision_sheet',
'qualification': 'CAPEX',
'decision_number': 'decision_number',
'decision_number_link': 'decision_number_link',
'code_site': 'SITEE',
'applicant': 'demandeur',
'immobilisation_family_a': True,
'immobilisation_family_b': True,
'immobilisation_family_c': False,
'immobilisation_family_d': False,
'immobilisation_family_e': False,
'immobilisation_family_f': True,
'immobilisation_family_g': False,
'immobilisation_family_h': False,
'responsible': User.objects.get(username='standard_user')})
project = Project.objects.get(name='test_project')
for i in range(len(excpected)):
self.assertEqual(project[field[i]], excpected[i])
Does anyone know why I have this error ? Does it come from my settings ? Thanks for your help
[EDIT]
I add my 'Project' Model and my 'project-create' view :
STATES = (
('#FFFFFF', 'Présenté par la DI avant ZSM37'),
('#FFFF00', 'Nouvelle décision - à traiter'),
('#FFFF99', 'Décision arrivée dans la ZSM37 mais non analysée le jour même'),
('#FF0000', 'Non validé => demande de renseignements pour statuer'),
('#FFFFFE', "NON Validé le jour de la création de l'EOTP mais Validé ultérieurement"),
('#00CC00', "Validé le jour de la création de l'EOTP"),
('#66B2FF', 'Non validé => opération à supprimer'),
('#0080FF', 'Non validé => opération supprimée'),
)
QUALIFICATION = (
('CAPEX', 'CAPEX'),
('OPEX/CAPEX', 'OPEX/CAPEX'),
('OPEX', 'OPEX'),
)
ENTITIES = (
("SC Saint Denis et CNES", "SC Saint Denis et CNES"),
("SC et Ctre Explt Lille", "SC et Ctre Explt Lille"),
("GMR Dauphiné", "GMR Dauphiné"),
)
class Project(models.Model):
DECISION_LEVEL = ( # les différents niveaux de décision que peut avoir un projet
('Immobilisations', 'Immobilisations'),
('Immobilisations + Synthèse', 'Immobilisations + Synthèse'),
('Comité de décision', 'Comité de décision'),
('ZSM vers Qualif', 'ZSM vers Qualif'),
('RRR vers Qualif', 'RRR vers Qualif'),
)
operations = models.ManyToManyField(Operation, related_name="project_operations")
state = models.CharField(max_length=7, choices=STATES, verbose_name="Statut", default="Nouvelle décision - à traiter")
name = models.CharField(max_length=200, verbose_name="Nom du projet", default="")
eotp = models.CharField(max_length=100, verbose_name="EOTP", blank=True, null=True, unique=True)
creation_date = models.DateField(verbose_name="Date de création du projet")
eotp_validation_date = models.DateField(verbose_name="Date de validation de l'EOTP", blank=True, null=True)
analysis_date = models.DateField(verbose_name="Date d'analyse", blank=True, null=True)
end_date = models.DateField(verbose_name="Date de fin du projet", blank=True, null=True)
entity = models.CharField(max_length=200, choices=ENTITIES, verbose_name="Entité/Sous-Entité", blank=True, null=True)
synthese = models.ManyToManyField(SyntheseUser, verbose_name="Suivi à synthèse", related_name="synthese_project")
aoi = models.ManyToManyField(AOIUser, verbose_name="Suivi à AOI", related_name="aoi_project")
price = models.FloatField(verbose_name="Montant (en K€)", default=0)
estimated_price = models.FloatField(verbose_name="Montant prévisionnel (en K€)", default=0)
decision = models.TextField(verbose_name="Décision", blank=True, null=True)
decision_in_explorer = models.TextField(verbose_name="Lien vers ECPR", blank=True, null=True)
description = models.TextField(verbose_name="Description du projet", blank=True, null=True)
commentary = models.TextField(verbose_name="Commentaire (situation/avis)", blank=True, null=True)
decision_level = models.CharField(max_length=26, choices=DECISION_LEVEL, verbose_name="Niveau de décision",
default='Immobilisations')
decision_sheet = models.TextField(verbose_name="Lien vers la fiche de décision", blank=True, null=True)
qualification = models.CharField(max_length=10, choices=QUALIFICATION, verbose_name="Qualification comptable",
default="Non défini")
decision_number = models.CharField(verbose_name="Numéro de décision", max_length=50, blank=True, null=True, unique=True)
decision_number_link = models.TextField(verbose_name="Lien vers le numéro de décision", blank=True, null=True)
code_site = models.CharField(max_length=5, verbose_name="Code site", blank=True, null=True)
applicant = models.CharField(max_length=200, verbose_name="Demandeur(s)", blank=True, null=True)
immobilisation_family_a = models.BooleanField(default=False, verbose_name="A")
immobilisation_family_b = models.BooleanField(default=False, verbose_name="\tB")
immobilisation_family_c = models.BooleanField(default=False, verbose_name="\tC")
immobilisation_family_d = models.BooleanField(default=False, verbose_name="\tD")
immobilisation_family_e = models.BooleanField(default=False, verbose_name="\tE")
immobilisation_family_f = models.BooleanField(default=False, verbose_name="\tF")
immobilisation_family_g = models.BooleanField(default=False, verbose_name="\tG")
immobilisation_family_h = models.BooleanField(default=False, verbose_name="\tH")
archived = models.BooleanField(default=False, verbose_name="Archiver le projet")
last_editor = models.ForeignKey(User, null=True, on_delete=models.SET_NULL, verbose_name="Dernier modificateur", related_name="last_editor")
last_modification_date = models.DateTimeField(blank=True, null=True, verbose_name="Date de modification")
related_projects = models.ManyToManyField('self', blank=True)
old_project_pk = models.IntegerField(blank=True, null=True)
copy = models.BooleanField(default=False)
responsible = models.ForeignKey(User, null=True, on_delete=models.SET_NULL,
verbose_name="Interlocuteur", related_name="project_responsible")
auto_created = models.BooleanField(default="False", verbose_name="Créé automatiquement")
def __str__(self):
return self.name
def get_operations(self):
return ", ".join([str(o) for o in self.operations.all()])
def get_related_projects(self):
return ", ".join([str(o) for o in self.related_projects.all()])
def get_aoi_users(self):
if self.aoi.all().count() == 0:
return "[vide]"
return ", ".join([str(a) for a in self.aoi.all()])
def get_synthese_users(self):
if self.synthese.all().count() == 0:
return "[vide]"
return ", ".join([str(s) for s in self.synthese.all()])
class ProjectForm(forms.ModelForm): # formulaire pour les projets (création ou modification)
class Meta:
model = Project
fields = ['state', 'name', 'eotp', 'creation_date', 'eotp_validation_date', 'analysis_date',
'end_date', 'entity', 'synthese', 'aoi', 'price', 'estimated_price', 'decision',
'decision_in_explorer', 'description', 'commentary', 'decision_level',
'decision_sheet', 'qualification', 'decision_number', 'decision_number_link', 'code_site',
'applicant', 'immobilisation_family_a', 'immobilisation_family_b',
'immobilisation_family_c', 'immobilisation_family_d', 'immobilisation_family_e',
'immobilisation_family_f', 'immobilisation_family_g', 'immobilisation_family_h', 'responsible']
synthese = forms.ModelMultipleChoiceField(
queryset=SyntheseUser.objects.all(),
widget=forms.CheckboxSelectMultiple,
required=False, label="Suivi à Synthèse")
aoi = forms.ModelMultipleChoiceField(
queryset=AOIUser.objects.all(),
widget=forms.CheckboxSelectMultiple,
required=False, label="Suivi à AOI")
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request")
super(ProjectForm, self).__init__(*args, **kwargs)
self.initial['eotp'] = get_initial_eotp(self.request.path)
if self.request.path == "/creation/":
self.initial['responsible'] = self.request.user
class ProjectCreate(LoginRequiredMixin, SuccessMessageMixin, CreateView): # formulaire de création de projet
model = Project
form_class = ProjectForm
success_url = reverse_lazy("project-list")
success_message = "Nouveau projet créé"
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs.update({'request': self.request})
return kwargs
def get_form(self, form_class=None):
form = super(ProjectCreate, self).get_form(form_class)
form.fields['creation_date'].widget = AdminDateWidget(attrs={'type': 'date'})
form.fields['eotp_validation_date'].widget = AdminDateWidget(attrs={'type': 'date'})
form.fields['analysis_date'].widget = AdminDateWidget(attrs={'type': 'date'})
form.fields['end_date'].widget = AdminDateWidget(attrs={'type': 'date'})
return form
def form_valid(self, form):
form.instance.decision_sheet = add_https(form.instance.decision_sheet)
form.instance.last_editor = self.request.user
form.instance.last_modification_date = datetime.datetime.now()
form.instance.save()
if self.request.POST.get('related_projects'):
form.instance.related_projects.add(get_project_from_eotp(self.request.POST.get('related_projects')))
form.instance.save()
return super().form_valid(form)
def get_success_url(self):
url = self.request.GET.get('next')
if url:
return url
return reverse_lazy("project-list")