Ablivion Ablivion - 10 months ago 58
Python Question

How to recursively get absolute url from parent instance(s)?

I have a page model that contains instance of itself as possible parent page. So every page can be child of another page. What I would like to do is get the absolute url to give me link that is structured according to its parent architecture. So let's say I have a Page AAA with child BBB, which itself has a child CCC. The url of last child would be mysite.com/AAA/BBB/CCC. I've played around and figured a recursive method that would work for me, however I hit a brick wall on resolving the urls.


class Page {
parent = models.ForeignKey('self', null=True, blank=True, unique=False)

def get_parent_path(self, list=None):

parenturl = []

if list is not None:
parenturl = list

if self.parent is not None:
return self.parent.get_parent_path(parenturl)

return parenturl

def get_absolute_url(self):

path = ''

if self.parent is not None:
parentlisting = self.get_parent_path()
for parent in parentlisting:
path = path + parent + '/'

path = path + self.slug;

return reverse("pages:details", kwargs={"path": path, "slug": self.slug})


url(r'^(?P<path>.+)(?P<slug>[\w-]+)/$', views.page, name='details'),

Testing it, showed me that path I get gives the correct parental part of the path. But resolving urls doesn't seem to work and I'm thinking it has something to do with reverse and/or regex. Using any page link, even where 404 should be, will now give me type error.

TypeError at /###/###/

page() got an unexpected keyword argument 'path'

What am I doing wrong?



def page(request, slug):

instance = get_object_or_404(Page, slug=slug)

context = {
"title": instance.title,
"page": instance,

return render(request, "page.html", context)

Answer Source

So first of all your page view is not accepting path argument.

You need to change def page(request, slug): to def page(request, slug, path):. Also you need to rethink if you need that param in your url and in your view, because you don't use it.

Further part might not be relevant

And one more thing, you forgot to put / between params in url

url(r'^(?P<path>.+)(?P<slug>[\w-]+)/$', views.page, name='details'),

should be

url(r'^(?P<path>.+)/(?P<slug>[\w-]+)/$', views.page, name='details')