Repository: adamchainz/django-mysql

Issue:
EnumField should set max_length if it is not specified
In order to make changes to any EnumField in django admin, a max_length must be set because it inherits from CharField



Discussion:
Thanks. I think we might just fill in `max_length` automatically to the maximum length of an enum string in mysql... although this isn't [documented](https://dev.mysql.com/doc/refman/5.7/en/enum.html).


Resolving patch:
diff --git a/django_mysql/models/fields/enum.py b/django_mysql/models/fields/enum.py
--- a/django_mysql/models/fields/enum.py
+++ b/django_mysql/models/fields/enum.py
@@ -34,11 +34,14 @@ def __init__(self, *args, **kwargs):
                 )
 
         kwargs['choices'] = choices
-        super(EnumField, self).__init__(*args, **kwargs)
 
-    def _check_max_length_attribute(self, **kwargs):
-        # Disable max length check on Django 1.7
-        return []
+        if 'max_length' in kwargs:
+            raise TypeError('"max_length" is not a valid argument')
+        # Massive to avoid problems with validation - let MySQL handle the
+        # maximum string length
+        kwargs['max_length'] = int(2 ** 32)
+
+        super(EnumField, self).__init__(*args, **kwargs)
 
     def deconstruct(self):
         name, path, args, kwargs = super(EnumField, self).deconstruct()
@@ -50,6 +53,8 @@ def deconstruct(self):
             path = 'django_mysql.models.' + self.__class__.__name__
 
         kwargs['choices'] = self.choices
+        del kwargs['max_length']
+
         return name, path, args, kwargs
 
     def db_type(self, connection):


Test patch:
diff --git a/tests/testapp/test_enumfield.py b/tests/testapp/test_enumfield.py
--- a/tests/testapp/test_enumfield.py
+++ b/tests/testapp/test_enumfield.py
@@ -2,6 +2,7 @@
 from __future__ import absolute_import, division, unicode_literals
 
 import pytest
+from django.core.exceptions import ValidationError
 from django.core.management import call_command
 from django.db import connection
 from django.db.utils import DataError
@@ -25,6 +26,11 @@ def test_invalid_choices(self):
             EnumField(choices=['red', 10])
         assert 'Invalid choice "10"' in str(exc_info.value)
 
+    def test_invalid_max_length(self):
+        with pytest.raises(TypeError) as exc_info:
+            EnumField(choices=['red'], max_length=100)
+        assert '"max_length" is not a valid argument' in str(exc_info.value)
+
     def test_correct(self):
         s = EnumModel.objects.create(field='red')
         assert s.field == 'red'
@@ -94,6 +100,23 @@ def test_contains_lookup(self):
         assert list(actual) == expected
 
 
+class TestCheck(TestCase):
+
+    def test_db_not_mariadb(self):
+        errors = EnumModel.check()
+        assert errors == []
+
+
+class TestDeconstruct(TestCase):
+
+    def test_deconstruct(self):
+        field = EnumField(choices=['a', 'b'])
+        name, path, args, kwargs = field.deconstruct()
+        assert path == 'django_mysql.models.EnumField'
+        assert 'max_length' not in kwargs
+        EnumField(*args, **kwargs)
+
+
 class TestMigrations(TransactionTestCase):
 
     @override_settings(MIGRATION_MODULES={
@@ -114,3 +137,18 @@ def test_adding_field_with_default(self):
                      verbosity=0, skip_checks=True)
         with connection.cursor() as cursor:
             assert table_name not in table_names(cursor)
+
+
+class TestFormfield(TestCase):
+    def test_formfield(self):
+        model_field = EnumField(choices=['this', 'that'])
+        form_field = model_field.formfield()
+
+        assert form_field.clean('this') == 'this'
+        assert form_field.clean('that') == 'that'
+
+        with pytest.raises(ValidationError):
+            form_field.clean('')
+
+        with pytest.raises(ValidationError):
+            form_field.clean('invalid')