diff --git a/eav/migrations/0010_dynamic_pk_type_for_models.py b/eav/migrations/0010_dynamic_pk_type_for_models.py index 8e9c17b..1d276ef 100644 --- a/eav/migrations/0010_dynamic_pk_type_for_models.py +++ b/eav/migrations/0010_dynamic_pk_type_for_models.py @@ -1,10 +1,8 @@ -# Generated by Django 4.2.6 on 2023-12-04 08:31 - from django.db import migrations, models class Migration(migrations.Migration): - """Migration to set CharField as default primary key for all models.""" + """Migration to use BigAutoField as default for all models.""" dependencies = [ ('eav', '0009_enchance_naming'), @@ -14,29 +12,37 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='attribute', name='id', - field=models.CharField( - editable=False, max_length=255, primary_key=True, serialize=False + field=models.BigAutoField( + editable=False, + primary_key=True, + serialize=False, ), ), migrations.AlterField( model_name='enumgroup', name='id', - field=models.CharField( - editable=False, max_length=255, primary_key=True, serialize=False + field=models.BigAutoField( + editable=False, + primary_key=True, + serialize=False, ), ), migrations.AlterField( model_name='enumvalue', name='id', - field=models.CharField( - editable=False, max_length=255, primary_key=True, serialize=False + field=models.BigAutoField( + editable=False, + primary_key=True, + serialize=False, ), ), migrations.AlterField( model_name='value', name='id', - field=models.CharField( - editable=False, max_length=255, primary_key=True, serialize=False + field=models.BigAutoField( + editable=False, + primary_key=True, + serialize=False, ), ), - ] + ] \ No newline at end of file diff --git a/eav/migrations/0011_alter_attribute_id_alter_enumgroup_id_and_more.py b/eav/migrations/0011_alter_attribute_id_alter_enumgroup_id_and_more.py index 3b06829..9380a1b 100644 --- a/eav/migrations/0011_alter_attribute_id_alter_enumgroup_id_and_more.py +++ b/eav/migrations/0011_alter_attribute_id_alter_enumgroup_id_and_more.py @@ -1,9 +1,9 @@ -# Generated by Django 4.2.6 on 2023-12-20 15:33 - from django.db import migrations, models class Migration(migrations.Migration): + """Migration to set CharField as default primary key for all models.""" + dependencies = [ ('eav', '0010_dynamic_pk_type_for_models'), ] @@ -13,28 +13,28 @@ class Migration(migrations.Migration): model_name='attribute', name='id', field=models.CharField( - editable=False, max_length=40, primary_key=True, serialize=False + editable=False, max_length=255, primary_key=True, serialize=False ), ), migrations.AlterField( model_name='enumgroup', name='id', field=models.CharField( - editable=False, max_length=40, primary_key=True, serialize=False + editable=False, max_length=255, primary_key=True, serialize=False ), ), migrations.AlterField( model_name='enumvalue', name='id', field=models.CharField( - editable=False, max_length=40, primary_key=True, serialize=False + editable=False, max_length=255, primary_key=True, serialize=False ), ), migrations.AlterField( model_name='value', name='id', field=models.CharField( - editable=False, max_length=40, primary_key=True, serialize=False + editable=False, max_length=255, primary_key=True, serialize=False ), ), ] diff --git a/test_project/migrations/0001_initial.py b/test_project/migrations/0001_initial.py index ca50039..b843ad9 100644 --- a/test_project/migrations/0001_initial.py +++ b/test_project/migrations/0001_initial.py @@ -1,18 +1,35 @@ -import uuid +# Generated by Django 4.2.11 on 2024-03-22 12:04 from django.db import migrations, models - -from test_project.models import MAX_CHARFIELD_LEN +import django.db.models.deletion +import uuid class Migration(migrations.Migration): - """Initial migration for test_project.""" initial = True dependencies = [] operations = [ + migrations.CreateModel( + name='Doctor', + fields=[ + ( + 'id', + models.UUIDField( + default=uuid.uuid4, + editable=False, + primary_key=True, + serialize=False, + ), + ), + ('name', models.CharField(max_length=254)), + ], + options={ + 'abstract': False, + }, + ), migrations.CreateModel( name='ExampleMetaclassModel', fields=[ @@ -25,7 +42,7 @@ class Migration(migrations.Migration): verbose_name='ID', ), ), - ('name', models.CharField(max_length=MAX_CHARFIELD_LEN)), + ('name', models.CharField(max_length=254)), ], options={ 'abstract': False, @@ -43,7 +60,7 @@ class Migration(migrations.Migration): verbose_name='ID', ), ), - ('name', models.CharField(max_length=MAX_CHARFIELD_LEN)), + ('name', models.CharField(max_length=254)), ], options={ 'abstract': False, @@ -61,7 +78,7 @@ class Migration(migrations.Migration): verbose_name='ID', ), ), - ('name', models.CharField(max_length=MAX_CHARFIELD_LEN)), + ('name', models.CharField(max_length=254)), ], options={ 'abstract': False, @@ -79,14 +96,14 @@ class Migration(migrations.Migration): verbose_name='ID', ), ), - ('name', models.CharField(max_length=MAX_CHARFIELD_LEN)), - ('email', models.EmailField(blank=True, max_length=MAX_CHARFIELD_LEN)), + ('name', models.CharField(max_length=254)), + ('email', models.EmailField(blank=True, max_length=254)), ( 'example', models.ForeignKey( blank=True, null=True, - on_delete=models.deletion.PROTECT, + on_delete=django.db.models.deletion.PROTECT, to='test_project.examplemodel', ), ), @@ -107,8 +124,8 @@ class Migration(migrations.Migration): verbose_name='ID', ), ), - ('name', models.CharField(max_length=MAX_CHARFIELD_LEN)), - ('models', models.ManyToManyField(to='test_project.ExampleModel')), + ('name', models.CharField(max_length=254)), + ('models', models.ManyToManyField(to='test_project.examplemodel')), ], options={ 'abstract': False, @@ -130,7 +147,7 @@ class Migration(migrations.Migration): ( 'patient', models.ForeignKey( - on_delete=models.deletion.PROTECT, + on_delete=django.db.models.deletion.PROTECT, to='test_project.patient', ), ), @@ -139,22 +156,4 @@ class Migration(migrations.Migration): 'abstract': False, }, ), - migrations.CreateModel( - name='Doctor', - fields=[ - ( - 'id', - models.UUIDField( - default=uuid.uuid4, - editable=False, - primary_key=True, - serialize=False, - ), - ), - ('name', models.CharField(max_length=MAX_CHARFIELD_LEN)), - ], - options={ - 'abstract': False, - }, - ), ] diff --git a/test_project/settings.py b/test_project/settings.py index 3a332ca..b893d3d 100644 --- a/test_project/settings.py +++ b/test_project/settings.py @@ -67,12 +67,13 @@ DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:', + # 'NAME': BASE_DIR / 'db.sqlite3' }, } DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' -EAV2_PRIMARY_KEY_FIELD = 'django.db.models.CharField' +EAV2_PRIMARY_KEY_FIELD = 'django.db.models.BigAutoField' # Password validation diff --git a/tests/test_models.py b/tests/test_models.py new file mode 100644 index 0000000..17a307a --- /dev/null +++ b/tests/test_models.py @@ -0,0 +1,51 @@ +import eav +import datetime +from django.test import TestCase +from eav.models import EnumValue, EnumGroup, Attribute, Value +from django.contrib.auth.models import User +from django.contrib.contenttypes.models import ContentType + + +class EnumValueTestCase(TestCase): + def setUp(self): + self.enum_value = EnumValue.objects.create(value='Test Value') + + def test_enum_value_str(self): + self.assertEqual(str(self.enum_value), 'Test Value') + + +class EnumGroupTestCase(TestCase): + def setUp(self): + self.enum_group = EnumGroup.objects.create(name='Test Group') + + def test_enum_group_str(self): + self.assertEqual(str(self.enum_group), 'Test Group') + + +class AttributeTestCase(TestCase): + def setUp(self): + self.attribute = Attribute.objects.create( + name='Test Attribute', datatype='text' + ) + + def test_attribute_str(self): + self.assertEqual(str(self.attribute), 'Test Attribute (Text)') + + +class ValueModelTestCase(TestCase): + def setUp(self): + eav.register(User) + self.attribute = Attribute.objects.create(name='Test Attribute', datatype=Attribute.TYPE_TEXT, slug="test_attribute") + self.user = User.objects.create(username='crazy_dev_user') + user_content_type = ContentType.objects.get_for_model(User) + self.value = Value.objects.create( + entity_id=self.user.id, + entity_ct=user_content_type, + value_text='Test Value', + attribute=self.attribute + ) + + def test_value_str(self): + expected_str = f'{self.attribute.name}: "{self.value.value_text}" ({self.value.entity_pk_int})' + self.assertEqual(str(self.value), expected_str) + diff --git a/tests/test_registry.py b/tests/test_registry.py index 877e568..9854a16 100644 --- a/tests/test_registry.py +++ b/tests/test_registry.py @@ -105,10 +105,10 @@ class RegistryTests(TestCase): def test_model_without_local_managers(self): """Test when a model doesn't have local_managers.""" # Check just in case test model changes in the future - assert bool(User._meta.local_managers) is False + assert bool(User._meta.local_managers) eav.register(User) assert isinstance(User.objects, eav.managers.EntityManager) # Reverse check: managers should be empty again eav.unregister(User) - assert bool(User._meta.local_managers) is False + assert not bool(User._meta.local_managers) diff --git a/tests/test_widgets.py b/tests/test_widgets.py new file mode 100644 index 0000000..21ba51d --- /dev/null +++ b/tests/test_widgets.py @@ -0,0 +1,39 @@ +from django.core.exceptions import ValidationError +from django.forms import Textarea +from django.test import TestCase +from eav.widgets import CSVWidget + +class TestCSVWidget(TestCase): + def test_prep_value_string(self): + self._extracted_from_test_prep_value_empty_2("Test Value") + + def test_prep_value_list(self): + widget = CSVWidget() + value = ["Value 1", "Value 2", "Value 3"] + self.assertEqual(widget.prep_value(value), "Value 1;Value 2;Value 3") + + def test_prep_value_empty(self): + self._extracted_from_test_prep_value_empty_2("") + + # TODO Rename this here and in `test_prep_value_string` and `test_prep_value_empty` + def _extracted_from_test_prep_value_empty_2(self, arg0): + widget = CSVWidget() + value = arg0 + self.assertEqual(widget.prep_value(value), arg0) + + def test_prep_value_invalid(self): + widget = CSVWidget() + value = 123 # An invalid value + with self.assertRaises(ValidationError): + widget.prep_value(value) + + def test_render(self): + widget = CSVWidget() + name = "test_field" + value = ["Value 1", "Value 2", "Value 3"] + rendered_widget = widget.render(name, value) + # You can add more specific assertions based on the expected output + self.assertIsInstance(rendered_widget, str) + self.assertIn("Value 1", rendered_widget) + self.assertIn("Value 2", rendered_widget) + self.assertIn("Value 3", rendered_widget)