1

When I started my current position, I inherited a Django Rest API that sits on top of our Postgres database. It was still running on Django v.1.7.11. Now almost two years later, I decided it's finally time to upgrade.

I first upgraded to Django v1.11.29 (planning on getting it more current, but wanted to upgrade somewhat incrementally). I fixed any errors caused by the upgrade and was all set. I was able to access it and everything worked properly, except for reading data from one table. This table contains four date fields, and when accessing it's API endpoint, I get the following error:

Request Method: GET
Request URL:    http://obis.twalk.tech:81/api/obis/occurrence/
Django Version: 1.11.29
Exception Type: ValueError
Exception Value:    
year is out of range
Exception Location: /usr/local/lib/python2.7/site-packages/django/db/utils.py in inner, line 101
Python Executable:  /usr/local/bin/python
Python Version: 2.7.18

From what I could tell initially with the debug output, this error was caused by having a null values in one of the date fields. I'm working in a personal development environment so I was able to change, at the database level, each instance of a null value in any of the date fields to be a properly formatted date. I still got the same error. I changed the field type in my model to be a text field instead of a date field; same error still occurs.

I've been stuck on this for about a week now, and after much research and many failed attempts to solve this, I'm at a loss. Does anybody have any suggestions or insight on what's going on here? I've posted the relevant code and traceback below.

models.py (the relevant fields are commented here for visibility):

class Occurrence(models.Model):
    resourcetype = models.ForeignKey('ResourceTypeLookup', db_column='resourcetype', blank=True, null=True)
    gid = models.IntegerField(primary_key=True)
    acode = models.ForeignKey(Acctax, db_column='acode', blank=True, null=True)
#   eventdate = models.DateField(blank=True, null=True)
    recordedby = models.CharField(max_length=500, blank=True)
    county = models.ForeignKey(County, db_column='county', blank=True, null=True)
    locality = models.CharField(max_length=500, blank=True)
    behavior = models.CharField(max_length=500, blank=True)
    habitat = models.CharField(max_length=500, blank=True)
    sex = models.CharField(max_length=500, blank=True)
    lifestage = models.CharField(max_length=500, blank=True)
    associatedtaxa = models.CharField(max_length=500, blank=True)
    verbatimelevation = models.FloatField(blank=True, null=True)
    depth = models.FloatField(blank=True, null=True)
    depthaccuracy = models.IntegerField(blank=True, null=True)
    individualcount = models.IntegerField(blank=True, null=True)
    occurrenceremarks = models.CharField(max_length=500, blank=True)
    taxonremarks = models.CharField(max_length=500, blank=True)
    institutioncode = models.ForeignKey(Institution, db_column='institutioncode', blank=True, null=True)
    basisofrecord = models.ForeignKey(BasisOfRecordLookup, db_column='basisofrecord', blank=True, null=True)
    catalognumber = models.CharField(max_length=500, blank=True)
    othercatalognumbers = models.CharField(max_length=500, blank=True)
    typestatus = models.CharField(max_length=25, blank=True)
    recordnumber = models.CharField(max_length=500, blank=True)
    samplingprotocol = models.CharField(max_length=500, blank=True)
    preparations = models.CharField(max_length=500, blank=True)
    primary_data = models.CharField(max_length=500, blank=True)
    associatedreferences = models.CharField(max_length=500, blank=True)
    datasetname = models.ForeignKey('Source', db_column='datasetname', blank=True, null=True)
    coordinateprecision = models.IntegerField(blank=True, null=True)
    decimallatitude = models.FloatField(blank=True, null=True)
    decimallongitude = models.FloatField(blank=True, null=True)
    geodeticdatum = models.CharField(max_length=10, blank=True)
    georeferencedby = models.CharField(max_length=500, blank=True)
#   georeferenceddate = models.DateField(blank=True, null=True)
    georeferenceremarks = models.CharField(max_length=500, blank=True)
    georeferencesources = models.CharField(max_length=500, blank=True)
    georeferenceverificationstatus = models.CharField(max_length=500, blank=True)
    geom = models.TextField(blank=True)  # This field type is a guess.
    problem_with_record = models.CharField(max_length=500, blank=True)
    previousidentifications = models.CharField(max_length=500, blank=True)
    identificationverificationstatus = models.CharField(max_length=500, blank=True)
    identificationconfidence = models.CharField(max_length=10, blank=True)
    identificationremarks = models.CharField(max_length=500, blank=True)
#   datelastmodified = models.DateField(blank=True, null=True)
    associatedoccurrences = models.CharField(max_length=500, blank=True)
    associatedsequences = models.CharField(max_length=500, blank=True)
    entby = models.CharField(max_length=500, blank=True)
#   entrydate = models.DateField(blank=True, null=True)
    obs_gid = models.IntegerField(blank=True, null=True)
    mtr = models.TextField(blank=True)
    township = models.IntegerField(blank=True, null=True)
    ns = models.TextField(blank=True)
    range = models.IntegerField(blank=True, null=True)
    ew = models.TextField(blank=True)
    section = models.IntegerField(blank=True, null=True)
    quarter = models.TextField(blank=True)
    zone = models.IntegerField(blank=True, null=True)
    utme = models.IntegerField(blank=True, null=True)
    utmn = models.IntegerField(blank=True, null=True)
    hiderecord = models.NullBooleanField()
    hiderecordcomment = models.CharField(max_length=500, blank=True)
    relationshipremarks = models.CharField(max_length=500, blank=True)
    informationwitheld = models.NullBooleanField()
    awaitingreview = models.IntegerField(blank=True, null=True)
    occurrenceid = models.TextField(blank=True)  # This field type is a guess.

    class Meta:
        managed = False
        db_table = 'occurrence'

filters.py:

class OccurrenceFilter(django_filters.FilterSet):
    acode = django_filters.CharFilter(lookup_expr='exact')
    catalognumber = django_filters.CharFilter(lookup_expr='icontains')

    class Meta:
        model = Occurrence
        fields = '__all__'

serializers.py:

class OccurenceSerializer(serializers.HyperlinkedModelSerializer):
     class Meta:
        model = Occurrence
        fields = ('url','resourcetype','gid','acode','eventdate','recordedby','county','locality','behavior','habitat','sex','lifestage','associatedtaxa','verbatimelevation','depth','depthaccuracy','individualcount','occurrenceremarks','taxonremarks','institutioncode','basisofrecord','catalognumber','othercatalognumbers','typestatus','recordnumber','samplingprotocol','preparations','primary_data','associatedreferences','datasetname','coordinateprecision','decimallatitude','decimallongitude','geodeticdatum','georeferencedby','georeferenceddate','georeferenceremarks','georeferencesources','georeferenceverificationstatus','geom','problem_with_record','previousidentifications','identificationverificationstatus','identificationconfidence','identificationremarks','datelastmodified','associatedoccurrences','associatedsequences','entby','entrydate','obs_gid','mtr','township','ns','range','ew','section','quarter','zone','utme','utmn','hiderecord','hiderecordcomment','relationshipremarks','informationwitheld','awaitingreview','occurrenceid')

views.py:

class OccurrenceViewSet(obisTableViewSet):
    """
    This is the Occurrence ViewSet with hyperlinked tables.
    """
    model = Occurrence
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
    renderer_classes = (BrowsableAPIRenderer, JSONRenderer)
    serializer_class = OccurenceSerializer
    filter_class = OccurrenceFilter
    search_fields = ('acode','catalognumber')

    def get_queryset(self):
        user = self.request.user

        if user.is_authenticated() == False or user.is_staff:
            return Occurrence.objects.all()
        else:
            institutioncodes = [g.name for g in user.groups.all()]
            return Occurrence.objects.filter(institutioncode__in=institutioncodes)

Traceback:

File "/usr/local/lib/python2.7/site-packages/django/core/handlers/exception.py" in inner
  41.             response = get_response(request)

File "/usr/local/lib/python2.7/site-packages/django/core/handlers/base.py" in _legacy_get_response
  249.             response = self._get_response(request)

File "/usr/local/lib/python2.7/site-packages/django/core/handlers/base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)

File "/usr/local/lib/python2.7/site-packages/django/core/handlers/base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/usr/local/lib/python2.7/site-packages/django/views/decorators/csrf.py" in wrapped_view
  58.         return view_func(*args, **kwargs)

File "/usr/local/lib/python2.7/site-packages/rest_framework/viewsets.py" in view
  116.             return self.dispatch(request, *args, **kwargs)

File "/usr/local/lib/python2.7/site-packages/rest_framework/views.py" in dispatch
  495.             response = self.handle_exception(exc)

File "/usr/local/lib/python2.7/site-packages/rest_framework/views.py" in handle_exception
  455.             self.raise_uncaught_exception(exc)

File "/usr/local/lib/python2.7/site-packages/rest_framework/views.py" in dispatch
  492.             response = handler(request, *args, **kwargs)

File "/usr/local/lib/python2.7/site-packages/rest_framework/mixins.py" in list
  48.         return Response(serializer.data)

File "/usr/local/lib/python2.7/site-packages/rest_framework/serializers.py" in data
  768.         ret = super(ListSerializer, self).data

File "/usr/local/lib/python2.7/site-packages/rest_framework/serializers.py" in data
  262.                 self._data = self.to_representation(self.instance)

File "/usr/local/lib/python2.7/site-packages/rest_framework/serializers.py" in to_representation
  686.             self.child.to_representation(item) for item in iterable

File "/usr/local/lib/python2.7/site-packages/django/db/models/query.py" in __iter__
  250.         self._fetch_all()

File "/usr/local/lib/python2.7/site-packages/django/db/models/query.py" in _fetch_all
  1121.             self._result_cache = list(self._iterable_class(self))

File "/usr/local/lib/python2.7/site-packages/django/db/models/query.py" in __iter__
  62.         for row in compiler.results_iter(results):

File "/usr/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py" in results_iter
  844.         for rows in results:

File "/usr/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py" in cursor_iter
  1289.                          sentinel):

File "/usr/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py" in <lambda>
  1288.         for rows in iter((lambda: cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE)),

File "/usr/local/lib/python2.7/site-packages/django/db/utils.py" in inner
  101.                 return func(*args, **kwargs)

Any help is much appreciated.

  • You haven't posted enough of the right info, but maybe this will help: https://stackoverflow.com/questions/10286224/ –  Oct 31 '20 at 00:35
  • @diogenesjunior the dates in the database are stored in the format YYYY-MM-DD, so that link isn't super relevant to me. is there any other information I could provide that would be helpful? – twalker1998 Oct 31 '20 at 18:16

0 Answers0