diff --git a/.gitignore b/.gitignore index 60b68e62..d52beced 100644 --- a/.gitignore +++ b/.gitignore @@ -93,7 +93,6 @@ venv/ ENV/ env.bak/ venv.bak/ - # Spyder project settings .spyderproject .spyproject diff --git a/CHANGELOG.md b/CHANGELOG.md index 813e4e46..a2a26806 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ # Version History +# Version History We follow [Semantic Versions](https://semver.org/) starting at the `0.14.0` release. @@ -13,6 +14,13 @@ We follow [Semantic Versions](https://semver.org/) starting at the `0.14.0` rele - Enhance BaseEntityAdmin by @Dresdn in https://github.com/jazzband/django-eav2/pull/541 - Remove support for Django < 3.2 and Python < 3.8 by @Dresdn in https://github.com/jazzband/django-eav2/pull/542 +## 1.5.1 (2023-12-04) + +### Bug Fixes + +- Fixes errors in migrations [#406](https://github.com/jazzband/django-eav2/issues/406) + + ## 1.5.0 (2023-11-08) ### Bug Fixes diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ba24fa05..7094e135 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,6 +3,7 @@ This is a [Jazzband](https://jazzband.co/) project. By contributing you agree to abide by the [Contributor Code of Conduct](https://jazzband.co/about/conduct) and follow the [guidelines](https://jazzband.co/about/guidelines). # Contributing + We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's: - Reporting a bug @@ -23,6 +24,19 @@ poetry install To activate your `virtualenv` run `poetry shell`. +## Configuration + +Set EAV2_PRIMARY_KEY_FIELD value to `django.db.models.UUIDField` or `django.db.models.BigAutoField` in your settings. + +```python +EAV2_PRIMARY_KEY_FIELD = "django.db.models.UUIDField" # as example +``` + +and run +```bash +python manage.py makemigrations +python manage.py migrate +``` ## Tests @@ -34,10 +48,20 @@ To run all tests: pytest ``` +## Cleanup + +At the end of the test, ensure that you delete the migration file created by the EAV2_PRIMARY_KEY_FIELD change. Additionally, verify that the migration files are clean and reset the value to django.db.models.CharField in your settings. + +```python +EAV2_PRIMARY_KEY_FIELD = "django.db.models.CharField" +``` + ## We develop with Github + We use github to host code, to track issues and feature requests, as well as accept pull requests. ### We use [Github Flow](https://guides.github.com/introduction/flow/index.html), so all code changes from community happen through pull requests + Pull requests are the best way to propose changes to the codebase (we use [Github Flow](https://guides.github.com/introduction/flow/index.html)). We actively welcome your pull requests: 1. Fork the repo and create your branch from `master`. @@ -48,11 +72,12 @@ Pull requests are the best way to propose changes to the codebase (we use [Githu 6. Describe the pull request using [this](https://github.com/jazzband/django-eav2/blob/master/PULL_REQUEST_TEMPLATE.md) template. ### Any contributions you make will be under the GNU Lesser General Public License v3.0 + In short, when you submit code changes, your submissions are understood to be under the same [LGPLv3](https://choosealicense.com/licenses/lgpl-3.0/) that covers the project. Feel free to contact the maintainers if that's a concern. ### Report bugs using Github's [issues](https://github.com/jazzband/django-eav2/issues) -We use GitHub issues to track public bugs. Report a bug by opening a new issue. Use [this](https://github.com/jazzband/django-eav2/blob/master/.github/ISSUE_TEMPLATE/bug_report.md) template to describe your reports. +We use GitHub issues to track public bugs. Report a bug by opening a new issue. Use [this](https://github.com/jazzband/django-eav2/blob/master/.github/ISSUE_TEMPLATE/bug_report.md) template to describe your reports. ### Use a consistent coding style diff --git a/eav/migrations/0010_dynamic_pk_type_for_models.py b/eav/migrations/0010_dynamic_pk_type_for_models.py index 28028ac8..c5054b6f 100644 --- a/eav/migrations/0010_dynamic_pk_type_for_models.py +++ b/eav/migrations/0010_dynamic_pk_type_for_models.py @@ -1,8 +1,9 @@ +# Generated by Django 4.2.11 on 2024-03-26 09:01 + from django.db import migrations, models class Migration(migrations.Migration): - """Migration to use BigAutoField as default for all models.""" dependencies = [ ('eav', '0009_enchance_naming'), @@ -12,37 +13,29 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='attribute', name='id', - field=models.BigAutoField( - editable=False, - primary_key=True, - serialize=False, + field=models.CharField( + editable=False, max_length=40, primary_key=True, serialize=False ), ), migrations.AlterField( model_name='enumgroup', name='id', - field=models.BigAutoField( - editable=False, - primary_key=True, - serialize=False, + field=models.CharField( + editable=False, max_length=40, primary_key=True, serialize=False ), ), migrations.AlterField( model_name='enumvalue', name='id', - field=models.BigAutoField( - editable=False, - primary_key=True, - serialize=False, + field=models.CharField( + editable=False, max_length=40, primary_key=True, serialize=False ), ), migrations.AlterField( model_name='value', name='id', - field=models.BigAutoField( - editable=False, - primary_key=True, - serialize=False, + field=models.CharField( + editable=False, max_length=40, primary_key=True, serialize=False ), ), ] diff --git a/eav/queryset.py b/eav/queryset.py index da5587d2..8c0fff8d 100644 --- a/eav/queryset.py +++ b/eav/queryset.py @@ -22,11 +22,10 @@ from functools import wraps from itertools import count -from django.core.exceptions import FieldDoesNotExist, ObjectDoesNotExist +from django.core.exceptions import ObjectDoesNotExist from django.db.models import Case, IntegerField, Q, When from django.db.models.query import QuerySet from django.db.utils import NotSupportedError -from django.db.models import Subquery from eav.models import Attribute, EnumValue, Value diff --git a/test_project/migrations/0001_initial.py b/test_project/migrations/0001_initial.py index ca50039f..b843ad94 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 07f7f724..7cfab18b 100644 --- a/test_project/settings.py +++ b/test_project/settings.py @@ -63,16 +63,11 @@ # Database # https://docs.djangoproject.com/en/3.1/ref/settings/#databases -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': ':memory:', - }, -} +DATABASES = {'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:'}} DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' -EAV2_PRIMARY_KEY_FIELD = 'django.db.models.AutoField' +EAV2_PRIMARY_KEY_FIELD = 'django.db.models.CharField' # Password validation diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_primary_key_format.py b/tests/test_primary_key_format.py index 4b9410c8..a87c155a 100644 --- a/tests/test_primary_key_format.py +++ b/tests/test_primary_key_format.py @@ -1,6 +1,5 @@ import uuid -import pytest from django.db import models from eav.logic.object_pk import get_pk_format diff --git a/tests/test_widgets.py b/tests/test_widgets.py new file mode 100644 index 00000000..01719f3b --- /dev/null +++ b/tests/test_widgets.py @@ -0,0 +1,40 @@ +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)