Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

'display_name' and 'name' fields are the same size #117

Open
superzazu opened this issue Apr 27, 2016 · 5 comments
Open

'display_name' and 'name' fields are the same size #117

superzazu opened this issue Apr 27, 2016 · 5 comments

Comments

@superzazu
Copy link

superzazu commented Apr 27, 2016

Hello,

Currently, if I try to create a City with a name of 200 characters (the max_length for this field), there is an exception raised on creation (DataError). Example :

country = Country.objects.get(code2='FR')
city_name = 'a' * 200
city = City(country=self.country, name=city_name)

city.save() # DataError: value too long for type character varying(200)

It seems to be because display_name and name fields have the same max_length (200), and the display_name consists of the name + the country name. Is there a way to avoid this problem ?

Best regards

@jpic
Copy link
Member

jpic commented Apr 27, 2016 via email

@superzazu
Copy link
Author

Here's the full error:

In [3]: city = City(country=country, name='a' * 250)

In [4]: city.save()
---------------------------------------------------------------------------
DataError                                 Traceback (most recent call last)
/root/.local/lib/python3.4/site-packages/django/db/backends/utils.py in execute(self, sql, params)
     63             else:
---> 64                 return self.cursor.execute(sql, params)
     65 

DataError: value too long for type character varying(200)


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

DataError                                 Traceback (most recent call last)
<ipython-input-4-1ed4f2ba6510> in <module>()
----> 1 city.save()

/root/.local/lib/python3.4/site-packages/django/db/models/base.py in save(self, force_insert, force_update, using, update_fields)
    706 
    707         self.save_base(using=using, force_insert=force_insert,
--> 708                        force_update=force_update, update_fields=update_fields)
    709     save.alters_data = True
    710 

/root/.local/lib/python3.4/site-packages/django/db/models/base.py in save_base(self, raw, force_insert, force_update, using, update_fields)
    734             if not raw:
    735                 self._save_parents(cls, using, update_fields)
--> 736             updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
    737         # Store the database on which the object was saved
    738         self._state.db = using

/root/.local/lib/python3.4/site-packages/django/db/models/base.py in _save_table(self, raw, cls, force_insert, force_update, using, update_fields)
    818 
    819             update_pk = bool(meta.has_auto_field and not pk_set)
--> 820             result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
    821             if update_pk:
    822                 setattr(self, meta.pk.attname, result)

/root/.local/lib/python3.4/site-packages/django/db/models/base.py in _do_insert(self, manager, using, fields, update_pk, raw)
    857         """
    858         return manager._insert([self], fields=fields, return_id=update_pk,
--> 859                                using=using, raw=raw)
    860 
    861     def delete(self, using=None, keep_parents=False):

/root/.local/lib/python3.4/site-packages/django/db/models/manager.py in manager_method(self, *args, **kwargs)
    120         def create_method(name, method):
    121             def manager_method(self, *args, **kwargs):
--> 122                 return getattr(self.get_queryset(), name)(*args, **kwargs)
    123             manager_method.__name__ = method.__name__
    124             manager_method.__doc__ = method.__doc__

/root/.local/lib/python3.4/site-packages/django/db/models/query.py in _insert(self, objs, fields, return_id, raw, using)
   1037         query = sql.InsertQuery(self.model)
   1038         query.insert_values(fields, objs, raw=raw)
-> 1039         return query.get_compiler(using=using).execute_sql(return_id)
   1040     _insert.alters_data = True
   1041     _insert.queryset_only = False

/root/.local/lib/python3.4/site-packages/django/db/models/sql/compiler.py in execute_sql(self, return_id)
   1058         with self.connection.cursor() as cursor:
   1059             for sql, params in self.as_sql():
-> 1060                 cursor.execute(sql, params)
   1061             if not (return_id and cursor):
   1062                 return

/root/.local/lib/python3.4/site-packages/django/db/backends/utils.py in execute(self, sql, params)
     77         start = time()
     78         try:
---> 79             return super(CursorDebugWrapper, self).execute(sql, params)
     80         finally:
     81             stop = time()

/root/.local/lib/python3.4/site-packages/django/db/backends/utils.py in execute(self, sql, params)
     62                 return self.cursor.execute(sql)
     63             else:
---> 64                 return self.cursor.execute(sql, params)
     65 
     66     def executemany(self, sql, param_list):

/root/.local/lib/python3.4/site-packages/django/db/utils.py in __exit__(self, exc_type, exc_value, traceback)
     93                 if dj_exc_type not in (DataError, IntegrityError):
     94                     self.wrapper.errors_occurred = True
---> 95                 six.reraise(dj_exc_type, dj_exc_value, traceback)
     96 
     97     def __call__(self, func):

/root/.local/lib/python3.4/site-packages/django/utils/six.py in reraise(tp, value, tb)
    683             value = tp()
    684         if value.__traceback__ is not tb:
--> 685             raise value.with_traceback(tb)
    686         raise value
    687 

/root/.local/lib/python3.4/site-packages/django/db/backends/utils.py in execute(self, sql, params)
     62                 return self.cursor.execute(sql)
     63             else:
---> 64                 return self.cursor.execute(sql, params)
     65 
     66     def executemany(self, sql, param_list):

DataError: value too long for type character varying(200)

@jpic
Copy link
Member

jpic commented Apr 27, 2016

Thanks a lot for your feedback ! This is very interresting, note that your example code works fine here:

In [1]: from cities_light.models import City, Country

In [2]: country = Country.objects.get(code2='FR')

In [3]: city_name = 'b' * 200

In [4]: city = City(country=country, name=city_name)

In [5]: city.save()
/home/jpic/env/lib/python2.7/site-packages/autoslug/utils.py:31: RuntimeWarning: Argument <type 'str'> is not an unicode object. Passing an encoded string will likely have unexpected results.
  return django_slugify(unidecode(value))


In [6]: City.objects.get(name=city_name).name
Out[6]: u'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'

In [7]: City.objects.get(name=city_name).pk
Out[7]: 23223

In your example, 'a' * 250 is used.

Could you please re-explain what the problem exactly is here ?

Thanks !!

Note that I have nothing against incrementing the size of this column, if we have an actual use case.

@superzazu
Copy link
Author

Hello,

Sorry for the delay. I have been doing a lot of tests, and I can't reproduce the bug with a fresh install of django (with python 2 or python 3). It seems the bug comes from my code, or a migration I wrote. I'll get back to you when I know more about this.

Thank you,
Best regards

@Pepedou
Copy link

Pepedou commented Sep 26, 2018

I ran into this issue while using model-mommy to generate fixtures for unit testing.
The default Region and City have a pre_save signal that generates the display_name by concatenating the Region+County names, and the City+Region+Country names, respectively.
If using max lengths, it results in 400 and 600 chars, way over the max 200.
django.db.utils.DataError: value too long for type character varying(200)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants