diff --git a/core/models/caves.py b/core/models/caves.py
index fc3e80f..4737c82 100644
--- a/core/models/caves.py
+++ b/core/models/caves.py
@@ -284,7 +284,6 @@ class Entrance(TroggleModel):
     alt = models.TextField(blank=True, null=True)
     approach = models.TextField(blank=True, null=True)
     bearings = models.TextField(blank=True, null=True)
-    cached_slug = models.CharField(max_length=200, blank=True, null=True)
     easting = models.TextField(blank=True, null=True)
     entrance_description = models.TextField(blank=True, null=True)
     exact_station = models.TextField(blank=True, null=True)
@@ -304,6 +303,7 @@ class Entrance(TroggleModel):
     other_description = models.TextField(blank=True, null=True)
     other_station = models.TextField(blank=True, null=True)
     photo = models.TextField(blank=True, null=True)
+    slug = models.SlugField(max_length=50, unique=True, default="default_slug_id")
     tag_station = models.TextField(blank=True, null=True)
     underground_description = models.TextField(blank=True, null=True)
     url = models.CharField(max_length=200, blank=True, null=True)
@@ -312,7 +312,7 @@ class Entrance(TroggleModel):
         ordering = ["caveandentrance__entrance_letter"]
 
     def __str__(self):
-        return str(self.slug())
+        return str(self.slug)
 
     def exact_location(self):
         return SurvexStation.objects.lookup(self.exact_station)
@@ -394,16 +394,17 @@ class Entrance(TroggleModel):
         res = "/".join((self.get_root().cave.get_absolute_url(), self.title))
         return res
 
-    def slug(self):
-        """Returns the first slug with primary=True that it can find,
-        if there are none with primary=True, then it returns the first slug it finds
-        """
-        if not self.cached_slug:
-            slugs = self.entranceslug_set.filter()
-            if slugs:
-                self.cached_slug = slugs[0].slug
-                self.save()
-        return self.cached_slug
+    #REPLACE this with a slug filed on the Entrance itself
+    # def slug(self):
+        # """Returns the first slug with primary=True that it can find,
+        # if there are none with primary=True, then it returns the first slug it finds
+        # """
+        # if not self.cached_slug:
+            # slugs = self.entranceslug_set.filter()
+            # if slugs:
+                # self.cached_slug = slugs[0].slug
+                # self.save()
+        # return self.cached_slug
 
     def cavelist(self):
         rs = []
diff --git a/parsers/caves.py b/parsers/caves.py
index 3f88c45..4e1f171 100644
--- a/parsers/caves.py
+++ b/parsers/caves.py
@@ -39,47 +39,55 @@ def dummy_entrance(k, slug, msg="DUMMY"):
     """Returns an empty entrance object for either a PENDING cave or a DUMMY entrance if
     user forgot to provide one when creating the cave
     """
-    ent = Entrance(
-        name=k,
+    ent = Entrance.objects.create( # creates object and saves into db
+        name=k, slug=k, filename = k + ".html",
         entrance_description="Dummy entrance: auto-created when registering a new cave "
         + "and you forgot to create an entrance for it. Click on 'Edit' to enter the correct data, then 'Submit'.",
         marking="?",
     )
     if ent:
-        ent.save()  # must save to have id before foreign keys work.
-        try:  # Now create a entrance slug ID
+        try:  # Now create a entranceslug object 
             EntranceSlug(entrance=ent, slug=slug)
         except:
             message = f" ! {k:11s}  {msg}-{slug} entrance create failure"
-            DataIssue.objects.create(parser="caves", message=message, url=f"{slug}")
+            DataIssue.objects.create(parser="entrances", message=message, url=f"{slug}")
             print(message)
 
-        ent.cached_slug = slug
-        ent.filename = slug + ".html"
-        ent.save()
+        # ent.cached_slug = slug
+        # ent.filename = slug + ".html"
+        # ent.save()
         return ent
     else:
         message = f" ! {k:11s}  {msg} cave SLUG '{slug}' create failure"
-        DataIssue.objects.create(parser="caves", message=message, url=f"{slug}")
+        DataIssue.objects.create(parser="entrances", message=message, url=f"{slug}")
         print(message)
         raise
 
 
+
 def set_dummy_entrance(id, slug, cave, msg="DUMMY"):
-    """Entrance field either missing or holds a null string instead of a filename in a cave_data file."""
+    """Called only when reading the cave and entrance html files
+    Entrance field either missing or holds a null string instead of a filename in a cave_data file."""
     global entrances_xslug
     try:
         entrance = dummy_entrance(id, slug, msg="DUMMY")
         entrances_xslug[slug] = entrance
         CaveAndEntrance.objects.update_or_create(cave=cave, entrance_letter="", entrance=entrance)
-        message = f" ! Warning: Dummy Entrance successfully set for entrance {id} on cave {cave}"
-
-        DataIssue.objects.create(parser="caves", message=message, url=f"{cave.url}")
-        print(message)
+        message = f" - Note: Dummy Entrance successfully set for entrance {id} on cave {cave}"
+        DataIssue.objects.create(parser="entrances", message=message, url=f"{cave.url}")
+        # print(message)
     except:
         # raise
         message = f' ! Entrance Dummy setting failure, slug:"{slug}" cave id :"{id}" '
-        DataIssue.objects.create(parser="caves", message=message, url=f"{cave.url}")
+        DataIssue.objects.create(parser="entrances", message=message, url=f"{cave.url}")
+        print(message)
+        
+    try:
+        EntranceSlug.objects.update_or_create(entrance=entrance, slug=slug)
+    except:
+        # raise
+        message = f' ! EntranceSlug setting failure for Dummy cave, slug:"{slug}" cave id :"{id}" '
+        DataIssue.objects.create(parser="entrances", message=message, url=f"{cave.url}")
         print(message)
 
 def make_areas():
@@ -274,21 +282,23 @@ def do_pending_cave(k, url, area):
             print(message)
 
         try:
-            ent = dummy_entrance(k, slug, msg="PENDING")
-            ceinsts = CaveAndEntrance.objects.update_or_create(cave=cave, entrance_letter="", entrance=ent)
-            for ceinst in ceinsts:
-                if str(ceinst) == str(cave):  # magic runes... why is the next value a Bool?
-                    ceinst.cave = cave
-                    ceinst.save()
-                    break
+            set_dummy_entrance(k, slug, cave, msg="PENDING")
+            # ent = dummy_entrance(k, slug, msg="PENDING")
+            # ceinsts = CaveAndEntrance.objects.update_or_create(cave=cave, entrance_letter="", entrance=ent)
+            # for ceinst in ceinsts:
+                # if str(ceinst) == str(cave):  # magic runes... why is the next value a Bool?
+                    # ceinst.cave = cave
+                    # ceinst.save()
+                    # break
         except:
-            message = f" ! {k:11s}  PENDING entrance + cave UNION create failure  '{cave}' [{ent}]"
+            message = f" ! {k:11s}  PENDING entrance + cave UNION create failure  '{cave}' [{slug}] {k}"
+            # message = f" ! {k:11s}  PENDING entrance + cave UNION create failure  '{cave}' [{ent}]"
             DataIssue.objects.create(parser="caves", message=message)
             print(message)
     return cave
 
 def readentrance(filename):
-    """Reads an enrance description from the .html file
+    """Reads an entrance description from the .html file
     Convoluted. Sorry.This is as I inherited it and I haven't fiddled with it. Needs rewriting
     """
     global entrances_xslug
@@ -303,7 +313,7 @@ def readentrance(filename):
     entrancecontentslist = getXML(contents, "entrance", maxItems=1, context=context)
     if len(entrancecontentslist) != 1:
         message = f'! BAD ENTRANCE at "{filename}"'
-        DataIssue.objects.create(parser="caves", message=message)
+        DataIssue.objects.create(parser="entrances", message=message)
         print(message)
     else:
         entrancecontents = entrancecontentslist[0]
@@ -362,8 +372,13 @@ def readentrance(filename):
             bearings=bearings[0],
             url=url[0],
             filename=filename,
-            cached_slug=slugs[0],
+            slug=slugs[0],
         )
+        if len(slugs) >1:
+            # Only ever one of these in the expo dataset
+            message = f" ! - More than one slug for an entrance: {entrance}, slugs: {slugs}. Aborting."
+            DataIssue.objects.create(parser="entrances", message=message, url=f"/cave/{slug}/edit/")
+            print(message)
         for slug in slugs:
             # print("entrance slug:{} filename:{}".format(slug, filename))
             try:
@@ -371,22 +386,17 @@ def readentrance(filename):
             except:
                 # need to cope with duplicates
                 message = f" ! FAILED to get precisely one ENTRANCE when updating using: cave_entrance/{filename}"
-                DataIssue.objects.create(parser="caves", message=message, url=f"/cave/{slug}/edit/")
+                DataIssue.objects.create(parser="entrances", message=message, url=f"/cave/{slug}/edit/")
                 # kents = EntranceSlug.objects.all().filter(entrance=e, slug=slug, primary=primary)
                 kents = EntranceSlug.objects.all().filter(entrance=e, slug=slug)
                 for k in kents:
                     message = " ! - DUPLICATE in db. entrance:" + str(k.entrance) + ", slug:" + str(k.slug())
-                    DataIssue.objects.create(parser="caves", message=message, url=f"/cave/{slug}/edit/")
+                    DataIssue.objects.create(parser="entrances", message=message, url=f"/cave/{slug}/edit/")
                     print(message)
                 for k in kents:
                     if k.slug() is not None:
                         print(" ! - OVERWRITING this one: slug:" + str(k.slug()))
                         k.notes = "DUPLICATE entrance found on import. Please fix\n" + k.notes
-        # else: # more than one item in long list. But this is not an error, and the max and min have been checked by getXML
-        # slug = Path(filename).stem
-        # message = f' ! ABORT loading this entrance. in "{filename}"'
-        # DataIssue.objects.create(parser='caves', message=message, url=f'/cave/{slug}/edit/')
-        # print(message)
 
 
 def readcave(filename):
@@ -526,13 +536,13 @@ def readcave(filename):
 
             if not entrances or len(entrances) < 1:
                 # missing entrance link in cave_data/1623-* .html file
-                set_dummy_entrance(slug[5:], slug, c, msg="DUMMY")
+                set_dummy_entrance(slug[5:], slug, c, msg="DUMMY: no entrances")
             else:
                 for entrance in entrances:
                     eslug = getXML(entrance, "entranceslug", maxItems=1, context=context)[0]
                     letter = getXML(entrance, "letter", maxItems=1, context=context)[0]
                     if len(entrances) == 1 and not eslug:  # may be empty: <entranceslug></entranceslug>
-                        set_dummy_entrance(slug[5:], slug, c, msg="DUMMY")
+                        set_dummy_entrance(slug[5:], slug, c, msg="DUMMY: no entrance slug read from file")
                     else:
                         try:
                             if eslug in entrances_xslug:
@@ -545,7 +555,7 @@ def readcave(filename):
                             )
                         except:
                             message = f' ! Entrance setting failure, slug:"{slug}" #entrances:{len(entrances)} {entrance} letter:"{letter}" cave:"{c}" filename:"cave_data/{filename}"'
-                            DataIssue.objects.create(parser="caves", message=message, url=f"{c.url}_edit/")
+                            DataIssue.objects.create(parser="entrances", message=message, url=f"{c.url}_edit/")
                             print(message)
 
             if survex_file[0]:
@@ -601,8 +611,8 @@ def getXML(text, itemname, minItems=1, maxItems=None, printwarnings=True, contex
 
 def readcaves():
     """Reads the xml-format HTML files in the EXPOWEB repo, not from the loser repo."""
-    # For those caves which do not have cave_data/1623-xxx.html XML files even though they exist and have surveys
-    # should put this in a simple list
+    # Pending is for those caves which do not have cave_data/1623-xxx.html XML files even though 
+    # they exist and have surveys. 
     pending = set()
     fpending = Path(CAVEDESCRIPTIONS, "pendingcaves.txt")
     if fpending.is_file():
diff --git a/templates/cave_debug.html b/templates/cave_debug.html
index 7de0ce0..6ff51c0 100644
--- a/templates/cave_debug.html
+++ b/templates/cave_debug.html
@@ -18,7 +18,7 @@
      #{{ent.id}} {{ent}}
   </td>
   <td>
-    {{ent.cached_slug}}
+    {{ent.slug}}
   </td>
     <td>
     {{ent.entranceslug_set.all|length }}