We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Dynamic page permissions aren't called on the content model
The documentation mentions a `can_add` method to define on a a custom page model. When this is called in `page_tags.set_page_permissions`, it only calls in on the `Page` instance, never using `Page.get_content_model()`.

I will submit a pull request to fix this, but I'm not sure where the check should go -- is it better in the Page class, having the base `can_add` method delegate to `get_content_model().can_add`, or should it go in the template tag?

Dynamic page permissions aren't called on the content model
The documentation mentions a `can_add` method to define on a a custom page model. When this is called in `page_tags.set_page_permissions`, it only calls in on the `Page` instance, never using `Page.get_content_model()`.

I will submit a pull request to fix this, but I'm not sure where the check should go -- is it better in the Page class, having the base `can_add` method delegate to `get_content_model().can_add`, or should it go in the template tag?


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mezzanine/pages/templatetags/pages_tags.py`
Content:
```
1 
2 from collections import defaultdict
3 
4 from django.core.exceptions import ImproperlyConfigured
5 from django.core.urlresolvers import reverse, NoReverseMatch
6 from django.template import TemplateSyntaxError, Variable
7 from django.template.loader import get_template
8 from django.utils.translation import ugettext_lazy as _
9 
10 from mezzanine.conf import settings
11 from mezzanine.pages.models import Page
12 from mezzanine.utils.urls import admin_url
13 from mezzanine import template
14 
15 
16 register = template.Library()
17 
18 
19 @register.render_tag
20 def page_menu(context, token):
21     """
22     Return a list of child pages for the given parent, storing all
23     pages in a dict in the context when first called using parents as keys
24     for retrieval on subsequent recursive calls from the menu template.
25     """
26     # First arg could be the menu template file name, or the parent page.
27     # Also allow for both to be used.
28     template_name = None
29     parent_page = None
30     parts = token.split_contents()[1:]
31     for part in parts:
32         part = Variable(part).resolve(context)
33         if isinstance(part, unicode):
34             template_name = part
35         elif isinstance(part, Page):
36             parent_page = part
37     if template_name is None:
38         try:
39             template_name = context["menu_template_name"]
40         except KeyError:
41             error = "No template found for page_menu in: %s" % parts
42             raise TemplateSyntaxError(error)
43     context["menu_template_name"] = template_name
44     if "menu_pages" not in context:
45         try:
46             user = context["request"].user
47             slug = context["request"].path
48         except KeyError:
49             user = None
50             slug = ""
51         num_children = lambda id: lambda: len(context["menu_pages"][id])
52         has_children = lambda id: lambda: num_children(id)() > 0
53         published = Page.objects.published(for_user=user)
54         if slug == admin_url(Page, "changelist"):
55             related = [m.__name__.lower() for m in Page.get_content_models()]
56             published = published.select_related(*related)
57         else:
58             published = published.select_related(depth=2)
59         # Store the current page being viewed in the context. Used
60         # for comparisons in page.set_menu_helpers.
61         if "page" not in context:
62             try:
63                 context["_current_page"] = published.get(slug=slug)
64             except Page.DoesNotExist:
65                 context["_current_page"] = None
66         elif slug:
67             context["_current_page"] = context["page"]
68         # Maintain a dict of page IDs -> parent IDs for fast
69         # lookup in setting page.is_current_or_ascendant in
70         # page.set_menu_helpers.
71         context["_parent_page_ids"] = {}
72         pages = defaultdict(list)
73         for page in published.order_by("_order"):
74             page.set_helpers(context)
75             context["_parent_page_ids"][page.id] = page.parent_id
76             setattr(page, "num_children", num_children(page.id))
77             setattr(page, "has_children", has_children(page.id))
78             pages[page.parent_id].append(page)
79         context["menu_pages"] = pages
80         context["on_home"] = slug == reverse("home")
81     # ``branch_level`` must be stored against each page so that the
82     # calculation of it is correctly applied. This looks weird but if we do
83     # the ``branch_level`` as a separate arg to the template tag with the
84     # addition performed on it, the addition occurs each time the template
85     # tag is called rather than once per level.
86     context["branch_level"] = 0
87     parent_page_id = None
88     if parent_page is not None:
89         context["branch_level"] = getattr(parent_page, "branch_level", 0) + 1
90         parent_page_id = parent_page.id
91 
92     context["page_branch"] = context["menu_pages"].get(parent_page_id, [])
93     context["page_branch_in_menu"] = False
94     for page in context["page_branch"]:
95         # footer/nav for backward compatibility.
96         page.in_footer = page.in_navigation = page.in_menu = True
97         for i, l, t in settings.PAGE_MENU_TEMPLATES:
98             if not unicode(i) in page.in_menus and t == template_name:
99                 page.in_navigation = page.in_menu = False
100                 if "footer" in template_name:
101                     page.in_footer = False
102                 break
103         if page.in_menu:
104             context["page_branch_in_menu"] = True
105     # Backwards compatibility
106     context['page_branch_in_navigation'] = context["page_branch_in_menu"]
107     context['page_branch_in_footer'] = (context["page_branch_in_menu"] and
108                                     template_name == "pages/menu/footer.html")
109 
110     for i, page in enumerate(context["page_branch"]):
111         context["page_branch"][i].branch_level = context["branch_level"]
112         context["page_branch"][i].parent = parent_page
113     t = get_template(template_name)
114     return t.render(context)
115 
116 
117 @register.as_tag
118 def models_for_pages(*args):
119     """
120     Create a select list containing each of the models that subclass the
121     ``Page`` model.
122     """
123     page_models = []
124     for model in Page.get_content_models():
125         try:
126             admin_url(model, "add")
127         except NoReverseMatch:
128             continue
129         else:
130             setattr(model, "name", model._meta.verbose_name)
131             setattr(model, "add_url", admin_url(model, "add"))
132             page_models.append(model)
133     return page_models
134 
135 
136 @register.render_tag
137 def set_model_permissions(context, token):
138     """
139     Assigns a permissions dict to the given model, much like Django
140     does with its dashboard app list.
141 
142     Used within the change list for pages, to implement permission
143     checks for the navigation tree.
144     """
145     model = context[token.split_contents()[1]]
146     opts = model._meta
147     perm_name = opts.app_label + ".%s_" + opts.object_name.lower()
148     request = context["request"]
149     setattr(model, "perms", {})
150     for perm_type in ("add", "change", "delete"):
151         model.perms[perm_type] = request.user.has_perm(perm_name % perm_type)
152     return ""
153 
154 
155 @register.render_tag
156 def set_page_permissions(context, token):
157     """
158     Assigns a permissions dict to the given page instance, combining
159     Django's permission for the page's model and a permission check
160     against the instance itself calling the page's ``can_add``,
161     ``can_change`` and ``can_delete`` custom methods.
162 
163     Used within the change list for pages, to implement permission
164     checks for the navigation tree.
165     """
166     page = context[token.split_contents()[1]]
167     model = page.get_content_model()
168     try:
169         opts = model._meta
170     except AttributeError:
171         # A missing inner Meta class usually means the Page model
172         # hasn't been directly subclassed.
173         error = _("An error occured with the following class. Does "
174                   "it subclass Page directly?")
175         raise ImproperlyConfigured(error + " '%s'" % model.__class__.__name__)
176     perm_name = opts.app_label + ".%s_" + opts.object_name.lower()
177     request = context["request"]
178     setattr(page, "perms", {})
179     for perm_type in ("add", "change", "delete"):
180         perm = request.user.has_perm(perm_name % perm_type)
181         perm = perm and getattr(page, "can_%s" % perm_type)(request)
182         page.perms[perm_type] = perm
183     return ""
184
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/mezzanine/pages/templatetags/pages_tags.py b/mezzanine/pages/templatetags/pages_tags.py
--- a/mezzanine/pages/templatetags/pages_tags.py
+++ b/mezzanine/pages/templatetags/pages_tags.py
@@ -178,6 +178,6 @@
     setattr(page, "perms", {})
     for perm_type in ("add", "change", "delete"):
         perm = request.user.has_perm(perm_name % perm_type)
-        perm = perm and getattr(page, "can_%s" % perm_type)(request)
+        perm = perm and getattr(model, "can_%s" % perm_type)(request)
         page.perms[perm_type] = perm
     return ""

{"golden_diff": "diff --git a/mezzanine/pages/templatetags/pages_tags.py b/mezzanine/pages/templatetags/pages_tags.py\n--- a/mezzanine/pages/templatetags/pages_tags.py\n+++ b/mezzanine/pages/templatetags/pages_tags.py\n@@ -178,6 +178,6 @@\n     setattr(page, \"perms\", {})\n     for perm_type in (\"add\", \"change\", \"delete\"):\n         perm = request.user.has_perm(perm_name % perm_type)\n-        perm = perm and getattr(page, \"can_%s\" % perm_type)(request)\n+        perm = perm and getattr(model, \"can_%s\" % perm_type)(request)\n         page.perms[perm_type] = perm\n     return \"\"\n", "issue": "Dynamic page permissions aren't called on the content model\nThe documentation mentions a `can_add` method to define on a a custom page model. When this is called in `page_tags.set_page_permissions`, it only calls in on the `Page` instance, never using `Page.get_content_model()`.\n\nI will submit a pull request to fix this, but I'm not sure where the check should go -- is it better in the Page class, having the base `can_add` method delegate to `get_content_model().can_add`, or should it go in the template tag?\n\nDynamic page permissions aren't called on the content model\nThe documentation mentions a `can_add` method to define on a a custom page model. When this is called in `page_tags.set_page_permissions`, it only calls in on the `Page` instance, never using `Page.get_content_model()`.\n\nI will submit a pull request to fix this, but I'm not sure where the check should go -- is it better in the Page class, having the base `can_add` method delegate to `get_content_model().can_add`, or should it go in the template tag?\n\n", "before_files": [{"content": "\nfrom collections import defaultdict\n\nfrom django.core.exceptions import ImproperlyConfigured\nfrom django.core.urlresolvers import reverse, NoReverseMatch\nfrom django.template import TemplateSyntaxError, Variable\nfrom django.template.loader import get_template\nfrom django.utils.translation import ugettext_lazy as _\n\nfrom mezzanine.conf import settings\nfrom mezzanine.pages.models import Page\nfrom mezzanine.utils.urls import admin_url\nfrom mezzanine import template\n\n\nregister = template.Library()\n\n\n@register.render_tag\ndef page_menu(context, token):\n    \"\"\"\n    Return a list of child pages for the given parent, storing all\n    pages in a dict in the context when first called using parents as keys\n    for retrieval on subsequent recursive calls from the menu template.\n    \"\"\"\n    # First arg could be the menu template file name, or the parent page.\n    # Also allow for both to be used.\n    template_name = None\n    parent_page = None\n    parts = token.split_contents()[1:]\n    for part in parts:\n        part = Variable(part).resolve(context)\n        if isinstance(part, unicode):\n            template_name = part\n        elif isinstance(part, Page):\n            parent_page = part\n    if template_name is None:\n        try:\n            template_name = context[\"menu_template_name\"]\n        except KeyError:\n            error = \"No template found for page_menu in: %s\" % parts\n            raise TemplateSyntaxError(error)\n    context[\"menu_template_name\"] = template_name\n    if \"menu_pages\" not in context:\n        try:\n            user = context[\"request\"].user\n            slug = context[\"request\"].path\n        except KeyError:\n            user = None\n            slug = \"\"\n        num_children = lambda id: lambda: len(context[\"menu_pages\"][id])\n        has_children = lambda id: lambda: num_children(id)() > 0\n        published = Page.objects.published(for_user=user)\n        if slug == admin_url(Page, \"changelist\"):\n            related = [m.__name__.lower() for m in Page.get_content_models()]\n            published = published.select_related(*related)\n        else:\n            published = published.select_related(depth=2)\n        # Store the current page being viewed in the context. Used\n        # for comparisons in page.set_menu_helpers.\n        if \"page\" not in context:\n            try:\n                context[\"_current_page\"] = published.get(slug=slug)\n            except Page.DoesNotExist:\n                context[\"_current_page\"] = None\n        elif slug:\n            context[\"_current_page\"] = context[\"page\"]\n        # Maintain a dict of page IDs -> parent IDs for fast\n        # lookup in setting page.is_current_or_ascendant in\n        # page.set_menu_helpers.\n        context[\"_parent_page_ids\"] = {}\n        pages = defaultdict(list)\n        for page in published.order_by(\"_order\"):\n            page.set_helpers(context)\n            context[\"_parent_page_ids\"][page.id] = page.parent_id\n            setattr(page, \"num_children\", num_children(page.id))\n            setattr(page, \"has_children\", has_children(page.id))\n            pages[page.parent_id].append(page)\n        context[\"menu_pages\"] = pages\n        context[\"on_home\"] = slug == reverse(\"home\")\n    # ``branch_level`` must be stored against each page so that the\n    # calculation of it is correctly applied. This looks weird but if we do\n    # the ``branch_level`` as a separate arg to the template tag with the\n    # addition performed on it, the addition occurs each time the template\n    # tag is called rather than once per level.\n    context[\"branch_level\"] = 0\n    parent_page_id = None\n    if parent_page is not None:\n        context[\"branch_level\"] = getattr(parent_page, \"branch_level\", 0) + 1\n        parent_page_id = parent_page.id\n\n    context[\"page_branch\"] = context[\"menu_pages\"].get(parent_page_id, [])\n    context[\"page_branch_in_menu\"] = False\n    for page in context[\"page_branch\"]:\n        # footer/nav for backward compatibility.\n        page.in_footer = page.in_navigation = page.in_menu = True\n        for i, l, t in settings.PAGE_MENU_TEMPLATES:\n            if not unicode(i) in page.in_menus and t == template_name:\n                page.in_navigation = page.in_menu = False\n                if \"footer\" in template_name:\n                    page.in_footer = False\n                break\n        if page.in_menu:\n            context[\"page_branch_in_menu\"] = True\n    # Backwards compatibility\n    context['page_branch_in_navigation'] = context[\"page_branch_in_menu\"]\n    context['page_branch_in_footer'] = (context[\"page_branch_in_menu\"] and\n                                    template_name == \"pages/menu/footer.html\")\n\n    for i, page in enumerate(context[\"page_branch\"]):\n        context[\"page_branch\"][i].branch_level = context[\"branch_level\"]\n        context[\"page_branch\"][i].parent = parent_page\n    t = get_template(template_name)\n    return t.render(context)\n\n\n@register.as_tag\ndef models_for_pages(*args):\n    \"\"\"\n    Create a select list containing each of the models that subclass the\n    ``Page`` model.\n    \"\"\"\n    page_models = []\n    for model in Page.get_content_models():\n        try:\n            admin_url(model, \"add\")\n        except NoReverseMatch:\n            continue\n        else:\n            setattr(model, \"name\", model._meta.verbose_name)\n            setattr(model, \"add_url\", admin_url(model, \"add\"))\n            page_models.append(model)\n    return page_models\n\n\n@register.render_tag\ndef set_model_permissions(context, token):\n    \"\"\"\n    Assigns a permissions dict to the given model, much like Django\n    does with its dashboard app list.\n\n    Used within the change list for pages, to implement permission\n    checks for the navigation tree.\n    \"\"\"\n    model = context[token.split_contents()[1]]\n    opts = model._meta\n    perm_name = opts.app_label + \".%s_\" + opts.object_name.lower()\n    request = context[\"request\"]\n    setattr(model, \"perms\", {})\n    for perm_type in (\"add\", \"change\", \"delete\"):\n        model.perms[perm_type] = request.user.has_perm(perm_name % perm_type)\n    return \"\"\n\n\n@register.render_tag\ndef set_page_permissions(context, token):\n    \"\"\"\n    Assigns a permissions dict to the given page instance, combining\n    Django's permission for the page's model and a permission check\n    against the instance itself calling the page's ``can_add``,\n    ``can_change`` and ``can_delete`` custom methods.\n\n    Used within the change list for pages, to implement permission\n    checks for the navigation tree.\n    \"\"\"\n    page = context[token.split_contents()[1]]\n    model = page.get_content_model()\n    try:\n        opts = model._meta\n    except AttributeError:\n        # A missing inner Meta class usually means the Page model\n        # hasn't been directly subclassed.\n        error = _(\"An error occured with the following class. Does \"\n                  \"it subclass Page directly?\")\n        raise ImproperlyConfigured(error + \" '%s'\" % model.__class__.__name__)\n    perm_name = opts.app_label + \".%s_\" + opts.object_name.lower()\n    request = context[\"request\"]\n    setattr(page, \"perms\", {})\n    for perm_type in (\"add\", \"change\", \"delete\"):\n        perm = request.user.has_perm(perm_name % perm_type)\n        perm = perm and getattr(page, \"can_%s\" % perm_type)(request)\n        page.perms[perm_type] = perm\n    return \"\"\n", "path": "mezzanine/pages/templatetags/pages_tags.py"}], "after_files": [{"content": "\nfrom collections import defaultdict\n\nfrom django.core.exceptions import ImproperlyConfigured\nfrom django.core.urlresolvers import reverse, NoReverseMatch\nfrom django.template import TemplateSyntaxError, Variable\nfrom django.template.loader import get_template\nfrom django.utils.translation import ugettext_lazy as _\n\nfrom mezzanine.conf import settings\nfrom mezzanine.pages.models import Page\nfrom mezzanine.utils.urls import admin_url\nfrom mezzanine import template\n\n\nregister = template.Library()\n\n\n@register.render_tag\ndef page_menu(context, token):\n    \"\"\"\n    Return a list of child pages for the given parent, storing all\n    pages in a dict in the context when first called using parents as keys\n    for retrieval on subsequent recursive calls from the menu template.\n    \"\"\"\n    # First arg could be the menu template file name, or the parent page.\n    # Also allow for both to be used.\n    template_name = None\n    parent_page = None\n    parts = token.split_contents()[1:]\n    for part in parts:\n        part = Variable(part).resolve(context)\n        if isinstance(part, unicode):\n            template_name = part\n        elif isinstance(part, Page):\n            parent_page = part\n    if template_name is None:\n        try:\n            template_name = context[\"menu_template_name\"]\n        except KeyError:\n            error = \"No template found for page_menu in: %s\" % parts\n            raise TemplateSyntaxError(error)\n    context[\"menu_template_name\"] = template_name\n    if \"menu_pages\" not in context:\n        try:\n            user = context[\"request\"].user\n            slug = context[\"request\"].path\n        except KeyError:\n            user = None\n            slug = \"\"\n        num_children = lambda id: lambda: len(context[\"menu_pages\"][id])\n        has_children = lambda id: lambda: num_children(id)() > 0\n        published = Page.objects.published(for_user=user)\n        if slug == admin_url(Page, \"changelist\"):\n            related = [m.__name__.lower() for m in Page.get_content_models()]\n            published = published.select_related(*related)\n        else:\n            published = published.select_related(depth=2)\n        # Store the current page being viewed in the context. Used\n        # for comparisons in page.set_menu_helpers.\n        if \"page\" not in context:\n            try:\n                context[\"_current_page\"] = published.get(slug=slug)\n            except Page.DoesNotExist:\n                context[\"_current_page\"] = None\n        elif slug:\n            context[\"_current_page\"] = context[\"page\"]\n        # Maintain a dict of page IDs -> parent IDs for fast\n        # lookup in setting page.is_current_or_ascendant in\n        # page.set_menu_helpers.\n        context[\"_parent_page_ids\"] = {}\n        pages = defaultdict(list)\n        for page in published.order_by(\"_order\"):\n            page.set_helpers(context)\n            context[\"_parent_page_ids\"][page.id] = page.parent_id\n            setattr(page, \"num_children\", num_children(page.id))\n            setattr(page, \"has_children\", has_children(page.id))\n            pages[page.parent_id].append(page)\n        context[\"menu_pages\"] = pages\n        context[\"on_home\"] = slug == reverse(\"home\")\n    # ``branch_level`` must be stored against each page so that the\n    # calculation of it is correctly applied. This looks weird but if we do\n    # the ``branch_level`` as a separate arg to the template tag with the\n    # addition performed on it, the addition occurs each time the template\n    # tag is called rather than once per level.\n    context[\"branch_level\"] = 0\n    parent_page_id = None\n    if parent_page is not None:\n        context[\"branch_level\"] = getattr(parent_page, \"branch_level\", 0) + 1\n        parent_page_id = parent_page.id\n\n    context[\"page_branch\"] = context[\"menu_pages\"].get(parent_page_id, [])\n    context[\"page_branch_in_menu\"] = False\n    for page in context[\"page_branch\"]:\n        # footer/nav for backward compatibility.\n        page.in_footer = page.in_navigation = page.in_menu = True\n        for i, l, t in settings.PAGE_MENU_TEMPLATES:\n            if not unicode(i) in page.in_menus and t == template_name:\n                page.in_navigation = page.in_menu = False\n                if \"footer\" in template_name:\n                    page.in_footer = False\n                break\n        if page.in_menu:\n            context[\"page_branch_in_menu\"] = True\n    # Backwards compatibility\n    context['page_branch_in_navigation'] = context[\"page_branch_in_menu\"]\n    context['page_branch_in_footer'] = (context[\"page_branch_in_menu\"] and\n                                    template_name == \"pages/menu/footer.html\")\n\n    for i, page in enumerate(context[\"page_branch\"]):\n        context[\"page_branch\"][i].branch_level = context[\"branch_level\"]\n        context[\"page_branch\"][i].parent = parent_page\n    t = get_template(template_name)\n    return t.render(context)\n\n\n@register.as_tag\ndef models_for_pages(*args):\n    \"\"\"\n    Create a select list containing each of the models that subclass the\n    ``Page`` model.\n    \"\"\"\n    page_models = []\n    for model in Page.get_content_models():\n        try:\n            admin_url(model, \"add\")\n        except NoReverseMatch:\n            continue\n        else:\n            setattr(model, \"name\", model._meta.verbose_name)\n            setattr(model, \"add_url\", admin_url(model, \"add\"))\n            page_models.append(model)\n    return page_models\n\n\n@register.render_tag\ndef set_model_permissions(context, token):\n    \"\"\"\n    Assigns a permissions dict to the given model, much like Django\n    does with its dashboard app list.\n\n    Used within the change list for pages, to implement permission\n    checks for the navigation tree.\n    \"\"\"\n    model = context[token.split_contents()[1]]\n    opts = model._meta\n    perm_name = opts.app_label + \".%s_\" + opts.object_name.lower()\n    request = context[\"request\"]\n    setattr(model, \"perms\", {})\n    for perm_type in (\"add\", \"change\", \"delete\"):\n        model.perms[perm_type] = request.user.has_perm(perm_name % perm_type)\n    return \"\"\n\n\n@register.render_tag\ndef set_page_permissions(context, token):\n    \"\"\"\n    Assigns a permissions dict to the given page instance, combining\n    Django's permission for the page's model and a permission check\n    against the instance itself calling the page's ``can_add``,\n    ``can_change`` and ``can_delete`` custom methods.\n\n    Used within the change list for pages, to implement permission\n    checks for the navigation tree.\n    \"\"\"\n    page = context[token.split_contents()[1]]\n    model = page.get_content_model()\n    try:\n        opts = model._meta\n    except AttributeError:\n        # A missing inner Meta class usually means the Page model\n        # hasn't been directly subclassed.\n        error = _(\"An error occured with the following class. Does \"\n                  \"it subclass Page directly?\")\n        raise ImproperlyConfigured(error + \" '%s'\" % model.__class__.__name__)\n    perm_name = opts.app_label + \".%s_\" + opts.object_name.lower()\n    request = context[\"request\"]\n    setattr(page, \"perms\", {})\n    for perm_type in (\"add\", \"change\", \"delete\"):\n        perm = request.user.has_perm(perm_name % perm_type)\n        perm = perm and getattr(model, \"can_%s\" % perm_type)(request)\n        page.perms[perm_type] = perm\n    return \"\"\n", "path": "mezzanine/pages/templatetags/pages_tags.py"}]}