Hierarchical URLs in Django - django

Is there a way to implement hierarchical query pattern in Django? As far as I know, the framework only allows to route to views by parsing URLs of a specific format, like:
/customers/{order} -> customer.views.show_orders(order)
But what if I need something like this:
/book1/chapter1/section1/paragraph1/note5 -> notes.view.show(note_id)
where note_id is the id of the last part of the URL, but the URL could have different number of components:
/book1/chapter1
/book1/chapter1/section1
etc.
Each time, it would point to the relevant part of the book depth depending on the depth. Is this doable?
I know there is this: https://github.com/MrKesn/django-mptt-urls, but I am wondering if there is another solution. This isn't ideal for me.

Django URLs are just regular expressions, so the simplest way would be to just ignore everything prior to the "note" section of the URL. For example:
url(r'^.*/note(?P<note_id>[0-9]+)$', 'notes.view.show'),
However, this would ignore the book, chapter, paragraph components. Which would mean your notes would need unique ids across the system, not just within the book. If you needed to capture any number of the interim parts it would be more complicated.
I can't confirm this will work right now, but using non-capture groups in regular expressions, you should be able to capture an optional book and chapter like so:
url(r'^(?:book(?P<book_id>[0-9]+)/)?(?:chapter(?P<chapter_id>[0-9]+)/)?note(?P<note_id>[0-9]+)$', 'notes.view.show'),

Use named groups to accomplish this: https://docs.djangoproject.com/en/dev/topics/http/urls/#named-groups
url(r'^book(?P<book_id>\d+)/chapter(?P<chapter_id>\d+)/section(?P<section_id>\d+)/paragraph(?P<paragraph_id>\d+)/note(?P<note_id>\d+)$', notes.view.show(book_id, chapter_id, section_id, paragraph_id, note_id)

For those who really need a variable-depth URL structure and need the URL to consist strictly of slugs, not IDs, knowing all the components of the URL is critical to retrieve the correct record from the database. Then, the only solution I can think of is using:
url(r'^.*/$', notes.views.show, name='show')
and then parsing the content of the URL to get the individual components after retrieving the URL in the view using the request.path call. This doesn't sound ideal, but it is a way to accomplish it.

Related

Google Analytics Filter Set of Pages

I need to create a filter on Google Analytics to include only a set of pages, for example, the view will have a filter to collect data only from
www.example.com/page1.html
www.example.com/page2.html
www.example.com/page3.html
I am trying to achieve this by using a Custom Filter to Include - > Request URI and using a Regex on the Filter Pattern.
My problem is that the Regex exceeds the 255 character limitation, even after I tried to optimice the regex to be a small as possible.
Creating more than one Include Filter does not work because this way no data would be collected, so I am wondering how could I achieve this? Thank you
This is the original regex
/es/investigacion/lace\.html|/en/research/lace\.html|/es/investigacion/lace/programa-maestrias\.html|/es/investigacion/lace/alumni/latin-american-forum-entrepreneurs\.html|/es/investigacion/lace/alumni/fondo-angel-investment\.html|/es/investigacion/lace/alumni\.html|/es/investigacion/lace/fondo-inversion\.html|/es/investigacion/lace/investigacion\.html|/es/investigacion/lace/acerca-del-centro\.html|/es/investigacion/lace/alumni/estudiantes-del-pais\.html|/en/research/investigation\.html|/en/research/about-the-center\.html|/es/investigacion/lace/alumni/mentoring\.html|/es/investigacion/lace/alumni/reatu-entrepreneur-award\.html|/en/research/lace/master-program\.html|/en/research/lace/alumni\.html|/en/research/investment-fund\.html
Edit: first try to compress the regex
/es/investigacion/lace/(programa-maestrias|alumni|investigacion|programa-maestrias|alumni/latin-american-forum-entrepreneurs|alumni/fondo-angel-investment|fondo-inversion|investigacion|acerca-del-centro|alumni/estudiantes-del-pais|alumni/mentoring|alumni/incae-entrepreneur-award)\.html|
Edit: the reason for this is because I need to create a new user profile on GA, and this new profile will have access to the information of a set of URLs only; so what occurred to me is create a new View that only captures the information of this set of URLs, and then assign the profile to this view with "Read/Analyze" permissons.
There are definitely more ways to optimise the regex. For example, since all string options end with .html, you could do something like this:
/(es/investigacion/lace|en/research/lace)\.html
by taking the .html out.
You could also take out
/es/investigacion/lace
and weave in the variable part of that using |'s, eg.
/es/investigacion/lace/(programa-maestrias|alumni|investigacion)\.html
But try a few of those optimisation techniques and you should be able to fit more in.

Google Analytics: View Filter by Request URI - does this work?

I think this should be pretty straight forward but if I have a url(s) with a request URIs such as:
/en/my-hometown/92-winston
/en/my-hometown/92-winston/backyard
and I want to set up a GA view which only includes this page and any subpages, then does the following Filter work in Analytics?
Will that basically filter against and URI which specifically contains 92-winston or do I need to wrap it in a fancy regex? I'm not that great with RegEx.
Thanks! Apologies in advance if this is ridiculously easy.
You may want to try this regex, if you know exactly that the URI will start with "/en/my-hometown/92-winston":
^\/en\/my\-hometown\/92\-winston.*
This captures URI strings that start exactly with "/en/my-hometown/92-winston" and also include anything that may come after that, for example
/en/my-hometown/92-winston
/en/my-hometown/92-winston/backyard
/en/my-hometown/92-winston/some_other_page
Just beware that if you have more than one "Include" filter in GA, then you need to make sure you aren't actually excluding more data, as multiple include filters are "and"ed. Always test your new filters in your test view as well.

Django documentation, part3 understanding problems

I read the documentation of Django but now I am at a point where I need some explanation. It is on this site and I understand the views but I really don't get how the urls work. It looks pretty cryptic and confusing to me. Can anybody explain to me how the urls work and what their purpose is?
Your urls.py file is virtual. They do it this way so you don't need to worry about a static url to http://yoursite.com/polls/34. By using this number as a regular expression /(d+) you can keep it dynamic so one url with this regular expression can be millions of different polls.
when the url is requested that regular expression number (whether it's 1 or 13352) is sent to the view which then says, I need to query the database for a Poll that has a PrimaryKey (PK) of whatever this number is. If it's found the Poll object is sent to the template by the view. The template then displays all the data in the poll object.
The bottom line is using something like this you can have one line for a url which is essentially millions of different urls. I use this same format for a movies website I'm creating www.noobmovies.com. I follow the same structure for Stars, Movies and blogs. Essentially three lines of code has created urls for 10,000 pages or so.
There is a dedicated Django documentation page for that: https://docs.djangoproject.com/en/1.6/topics/http/urls/
Maybe it will help you?

Match all characters in group except for first and last occurrence

Say I request
parent/child/child/page-name
in my browser. I want to extract the parent, children as well as page name. Here are the regular expressions I am currently using. There should be no limit as to how many children there are in the url request. For the time being, the page name will always be at the end and never be omitted.
^([\w-]{1,}){1} -> Match parent (returns 'parent')
(/(?:(?!/).)*[a-z]){1,}/ -> Match children (returns /child/child/)
[\w-]{1,}(?!.*[\w-]{1,}) -> Match page name (returns 'page-name')
The more I play with this, the more I feel how clunky this solution is. This is for a small CMS I am developing in ASP Classic (:(). It is sort of like the MVC routing paths. But instead of calling controllers and functions based on the URL request. I would be travelling down the hierarchy and finding the appropriate page in the database. The database is using the nested set model and is linked by a unique page name for each child.
I have tried using the split function to split with a / delimiter however I found I was nested so many split statements together it became very unreadable.
All said, I need an efficient way to parse out the parent, children as well as page name from a string. Could someone please provide an alternative solution?
To be honest, I'm not even sure if a regular expression is the best solution to my problem.
Thank you.
You could try using:
^([\w-]+)(/.*/)([\w-]+)$
And then access the three matching groups created using Match.SubMatches. See here for more details.
EDIT
Actually, assuming that you know that [\w-] is all that is used in the names of the parts, you can use ^([\w-]+)(.*)([\w-]+)$ instead and it will handle the no-child case fine by itself as well.

Recursive URL Patterns CMS Style

Whenever I learn a new language/framework, I always make a content management system...
I'm learning Python & Django and I'm stuck with making a URL pattern that will pick the right page.
For example, for a single-level URL pattern, I have:
url(r'^(?P<segment>[-\w]+)/$', views.page_by_slug, name='pg_slug'),
Which works great for urls like:
http://localhost:8000/page/
Now, I'm not sure if I can get Django's URL system to bring back a list of slugs ala:
http://localhost:8000/parent/child/grandchild/
would return parent, child, grandchild.
So is this something that Django does already? Or do I modify my original URL pattern to allow slashes and extract the URL data there?
Thanks for the help in advance.
That's because your regular expression does not allow middle '/' characters. Recursive definition of url segments pattern may be possible, but anyway it would be passed as a chunk to your view function.
Try this
url(r'^(?P<segments>[-/\w]+)/$', views.page_by_slug, name='pg_slug'),
and split segments argument passed to page_by_slug() by '/', then you will get ['parent', 'child', 'grandchild']. I'm not sure how you've organized the page model, but if it is not much sophiscated, consider using or improving flatpages package that is already included in Django.
Note that if you have other kind of urls that does not indicate user-generated pages but system's own pages, you should put them before the pattern you listed because Django's url matching mechanism follows the given order.