diff --git a/core/admin.py b/core/admin.py
index 18fb404..0fe47f7 100644
--- a/core/admin.py
+++ b/core/admin.py
@@ -96,8 +96,8 @@ class PersonAdmin(TroggleModelAdmin):
 
 class QMAdmin(TroggleModelAdmin):
     search_fields = ('found_by__cave__kataster_number','number','found_by__date')
-    list_display = ('__unicode__','grade','found_by','ticked_off_by')
-    list_display_links = ('__unicode__',)
+    list_display = ('__str__','grade','found_by','ticked_off_by')
+    list_display_links = ('__str__',)
     list_editable = ('found_by','ticked_off_by','grade')
     list_per_page = 20
     raw_id_fields=('found_by','ticked_off_by')
diff --git a/core/models.py b/core/models.py
index 3db3b29..efba870 100644
--- a/core/models.py
+++ b/core/models.py
@@ -86,7 +86,7 @@ class Expedition(TroggleModel):
     year        = models.CharField(max_length=20, unique=True)
     name        = models.CharField(max_length=100)
         
-    def __unicode__(self):
+    def __str__(self):
         return self.year
 
     class Meta:
@@ -146,7 +146,7 @@ class Person(TroggleModel):
         verbose_name_plural = "People"
         ordering = ('orderref',)  # "Wookey" makes too complex for: ('last_name', 'first_name') 
     
-    def __unicode__(self):
+    def __str__(self):
         if self.last_name:
             return "%s %s" % (self.first_name, self.last_name)
         return self.first_name
@@ -217,7 +217,7 @@ class PersonExpedition(TroggleModel):
         ordering = ('-expedition',)
         #order_with_respect_to = 'expedition'
 
-    def __unicode__(self):
+    def __str__(self):
         return "%s: (%s)" % (self.person, self.expedition)
     
     #why is the below a function in personexpedition, rather than in person? - AC 14 Feb 09
@@ -285,9 +285,12 @@ class LogbookEntry(TroggleModel):
                 kwargs["cave_slug"] = CaveSlug.objects.get(cave=kwargs["cave"], primary=True).slug
             kwargs.pop("cave")
         # parse error in python3.8        
+        return TroggleModel.__init__(self, *args, **kwargs) # seems OK in 3.5 & 3.8! failure later elsewhere with 3.8
         #return TroggleModel().__init__(self, *args, **kwargs) # parses OK, fails at runtime in 3.8
-        return super(LogbookEntry, self).__init__(*args, **kwargs) # works in py3.5
-        #return TroggleModel.__init__(*args, **kwargs) # fails in py3.5, 
+        #return super().__init__(self, *args, **kwargs) # fails in 3.8
+        #return super().__init__(*args, **kwargs) # works in py3.5 fails in 3.8
+        #return super(LogbookEntry, self).__init__(*args, **kwargs) # works in py3.5
+        #return TroggleModel.__init__(*args, **kwargs) # fails in py3.5, runtime fail in 3.8
 
     def isLogbookEntry(self): # Function used in templates
         return True
@@ -295,7 +298,7 @@ class LogbookEntry(TroggleModel):
     def get_absolute_url(self):
         return urllib.parse.urljoin(settings.URL_ROOT, reverse('logbookentry',kwargs={'date':self.date,'slug':self.slug}))
 
-    def __unicode__(self):
+    def __str__(self):
         return "%s: (%s)" % (self.date, self.title)
 
     def get_next_by_id(self):
@@ -354,7 +357,7 @@ class PersonTrip(TroggleModel):
     def place(self):
         return self.logbook_entry.cave and self.logbook_entry.cave or self.logbook_entry.place
 
-    def __unicode__(self):
+    def __str__(self):
         return "%s (%s)" % (self.personexpedition, self.logbook_entry.date)
     
 
@@ -368,7 +371,7 @@ class Area(TroggleModel):
     name = models.CharField(max_length=200, blank=True, null=True)
     description = models.TextField(blank=True,null=True)
     parent = models.ForeignKey('Area', blank=True, null=True)
-    def __unicode__(self):
+    def __str__(self):
         if self.parent:
             return str(self.parent) + " - " + str(self.short_name)
         else:
@@ -383,7 +386,7 @@ class CaveAndEntrance(models.Model):
     cave = models.ForeignKey('Cave')
     entrance = models.ForeignKey('Entrance')
     entrance_letter = models.CharField(max_length=20,blank=True,null=True)
-    def __unicode__(self):
+    def __str__(self):
         return str(self.cave) + str(self.entrance_letter)
         
 class CaveSlug(models.Model):
@@ -469,7 +472,7 @@ class Cave(TroggleModel):
         #return settings.URL_ROOT + '/cave/' + href + '/'
         return urllib.parse.urljoin(settings.URL_ROOT, reverse('cave',kwargs={'cave_id':href,}))
 
-    def __unicode__(self, sep = ": "):
+    def __str__(self, sep = ": "):
         return str("slug:"+self.slug())
 
     def get_QMs(self):
@@ -561,7 +564,7 @@ def getCaveByReference(reference):
 class OtherCaveName(TroggleModel):
     name = models.CharField(max_length=160)
     cave = models.ForeignKey(Cave)
-    def __unicode__(self):
+    def __str__(self):
         return str(self.name)
             
 class EntranceSlug(models.Model):
@@ -609,7 +612,7 @@ class Entrance(TroggleModel):
     filename = models.CharField(max_length=200)
     cached_primary_slug = models.CharField(max_length=200,blank=True,null=True)
 
-    def __unicode__(self):
+    def __str__(self):
         return str(self.slug())
 
     def exact_location(self):
@@ -725,7 +728,7 @@ class CaveDescription(TroggleModel):
     linked_entrances = models.ManyToManyField("Entrance", blank=True,null=True)
     linked_qms = models.ManyToManyField("QM", blank=True,null=True)
 
-    def __unicode__(self):
+    def __str__(self):
         if self.long_name:
             return str(self.long_name)
         else:
@@ -748,7 +751,7 @@ class CaveDescription(TroggleModel):
 
 class NewSubCave(TroggleModel):
     name = models.CharField(max_length=200, unique = True)
-    def __unicode__(self):
+    def __str__(self):
         return str(self.name)
 
 class QM(TroggleModel):
@@ -776,7 +779,7 @@ class QM(TroggleModel):
     completion_description = models.TextField(blank=True,null=True)
     comment=models.TextField(blank=True,null=True)
 
-    def __unicode__(self):
+    def __str__(self):
         return "%s %s" % (self.code(), self.grade)
 
     def code(self):
@@ -819,7 +822,7 @@ class QM(TroggleModel):
     #object_id = models.PositiveIntegerField()
     #location = generic.GenericForeignKey('content_type', 'object_id')
 
-    # def __unicode__(self):
+    # def __str__(self):
         # return self.caption
 
 scansFileStorage = FileSystemStorage(location=settings.SURVEY_SCANS, base_url=settings.SURVEYS_URL)
@@ -853,7 +856,7 @@ class ScannedImage(TroggleImageModel):
     def correctURL(self):
         return string.replace(self.file.url,r'#',r'%23')
 
-    def __unicode__(self):
+    def __str__(self):
         return get_scan_path(self,'')
 
 class Survey(TroggleModel):
@@ -874,7 +877,7 @@ class Survey(TroggleModel):
     integrated_into_main_sketch_on = models.DateField(blank=True,null=True)
     integrated_into_main_sketch_by = models.ForeignKey('Person' ,related_name='integrated_into_main_sketch_by', blank=True,null=True)
     rendered_image = models.ImageField(upload_to='renderedSurveys',blank=True,null=True)
-    def __unicode__(self):
+    def __str__(self):
         return self.expedition.year+"#"+"%02d" % int(self.wallet_number)
 
     def notes(self):
@@ -894,5 +897,5 @@ class DataIssue(TroggleModel):
     class Meta:
         ordering = ['date']
 
-    def __unicode__(self):
+    def __str__(self):
         return "%s - %s" % (self.parser, self.message)
diff --git a/core/models_survex.py b/core/models_survex.py
index 6ab6f8a..629b4df 100644
--- a/core/models_survex.py
+++ b/core/models_survex.py
@@ -184,7 +184,7 @@ class SurvexPersonRole(models.Model):
     persontrip          = models.ForeignKey('PersonTrip', blank=True, null=True)  
     expeditionday       = models.ForeignKey("ExpeditionDay", null=True)
     
-    def __unicode__(self):
+    def __str__(self):
         return str(self.person) + " - " + str(self.survexblock) + " - " + str(self.nrole)
         
     
@@ -198,7 +198,7 @@ class SurvexScansFolder(models.Model):
     def get_absolute_url(self):
         return urllib.parse.urljoin(settings.URL_ROOT, reverse('surveyscansfolder', kwargs={"path":re.sub("#", "%23", self.walletname)}))
 
-    def __unicode__(self):
+    def __str__(self):
         return str(self.walletname) + " (Survey Scans Folder)"
     
 class SurvexScanSingle(models.Model):
@@ -212,7 +212,7 @@ class SurvexScanSingle(models.Model):
     def get_absolute_url(self):
         return urllib.parse.urljoin(settings.URL_ROOT, reverse('surveyscansingle', kwargs={"path":re.sub("#", "%23", self.survexscansfolder.walletname), "file":self.name}))
  
-    def __unicode__(self):
+    def __str__(self):
         return "Survey Scan Image: " + str(self.name) + " in " + str(self.survexscansfolder)
     
         
diff --git a/flatpages/models.py b/flatpages/models.py
index 7631881..23739ca 100644
--- a/flatpages/models.py
+++ b/flatpages/models.py
@@ -8,5 +8,5 @@ class Redirect(models.Model):
 class EntranceRedirect(models.Model):
     originalURL = models.CharField(max_length=200)
     entrance = models.ForeignKey(Entrance)
-    def __unicode__(self):
+    def __str__(self):
         return self.entrance.slug