Django - Request resolution - django

I would like to know how Django is resolving request urls urlpatterns in general.
My theory:
Django at some point turns all its urlpatterns into list of regexes, and then tries to match them against incoming Request's url.
Question:
Am I correct? If yes, can somebody point me out where in source code is this happening?
Looks like there is nothing about this mentioned in django docs, and I feel like I am doing a blind search in source code. Any insights appreciated.

The process is described here. In short:
Django determines the root URLconf module to use....
Django loads that Python module and looks for the variable urlpatterns. This should be a Python list of django.urls.path() and/or django.urls.re_path() instances.
Django runs through each URL pattern, in order, and stops at the first one that matches the requested URL.
Once one of the URL patterns matches, Django imports and calls the given view, which is a simple Python function (or a class-based view)....
If no URL pattern matches, or if an exception is raised during any point in this process, Django invokes an appropriate error-handling view....

Related

Function of defining an absolute URL in a model in Django

I am currently completing the final capstone project for Django on Codecademy, and I've come across a comprehension issue.
On Codecademy, they state that it's used to redirect to the homepage when a user submits data, while the Django documentation for get_absolute_url seems to make no reference to redirects.
I currently have no absolute urls defined for any of my models, and these are my url patterns and views.
At this stage, I'm just trying to understand the purpose of defining an absolute URL in a model, and where the appropriate places to utilize it are. I'm very confused about it's function currently, and would appreciate a simplified explanation with examples.

django-comments-xtd not accessible with wagtail? How to troubleshoot?

I have installed django-comments-xtd following the quick start guide in the documentation here.
When I go to access the /comments URL, I only get a 404 error, and the message 'Raised by: wagtail.wagtailcore.views.serve'.
I followed the documentation without issue, and have installed other apps that work fine such as django-machina.
I am using django 1.11.13, python 2.7 and django-comments-xtd 2.1.0.
Why would this particular URL not be accessible? Templates exist in the correct location.
My files are setup exactly the same as in the documentation, happy to provide more info but not sure what to provide right now.
What can I do to try and troubleshoot the problem?
I think you are misreading the documentation and you do not actually have a problem. It just says:
mount the URL patterns of django_comments_xtd in the path /comments/
It does not say that you should access this URL. The fact that, as per your comment, you are not getting a 404 when you are accessing /comments/sent/ indicates that you have set up django-comments-xtd correctly.
For /comments/ to be a valid URL, the django_comments_xtd.urls you included would have to contain an empty URL pattern, like this:
url('', some_view)
If you look at the urls.py of django-comments-xtd, you will see that it does indeed include the urls.py from django-contrib-comments, but this doesn't define an empty URL pattern. So there is no URL pattern that would match /comments/.
The urls definition from django-comments-xtd will have to come before Wagtail's one (i.e. url(r'', include(wagtail_urls))) as it acts as a catch all and will therefore render other urls unreachable.
just food for thought. The email confirmation template uses
http://{{ site.domain }}{{ confirmation_url|slice:":40" }}...
You want to make sure your site.domain matches whatever your are using for development. This just fixed this error for me. I had a different domain setup in Django Admin

Moving the API Root of Default Router in Django

I'm using Django 1.8 and Django REST Framework. I want the API Root functionality of using a Default Router, but I want to move it to another url, like /apiroot/ or something like that.
I found this post, but it doesn't really answer my question. I don't want to rewrite the API, I basically just want the functionality of the ^$ route to be a standard template page (home page) for the site, and have site.com/apiroot to be the new API root url.
In the process of writing up this question, I looked at the DRF source code, and found my answer. Instead of deleting the question, I figured I'd go ahead and post it, since someone else may be wondering the same thing, and a search hasn't turned up any answers to this already.
The solution to this was to add the following lines to my urls.py:
url(r'^$', media_views.index, name='index'),
url(r'^apiroot/', router.get_api_root_view()),
The first line will replace the ^$ url entry with a pointer to my index method in media_views. The second will mimic the DefaultRouter functionality from / to /apiroot/ and show the API root page there instead.

Reversing urls in Django / Celery

I have been asked to send an email on friday with a list of projects matching a set of conditions. The database front end is written in Django and its an in house application. I would like to link to the admin page of the project in the email.
On my development machine I am trying
reverse("admin:index")
and I notice that it is only returning
admin
from the Celery task, whereas in standard Django views this would return
127.0.0.1:8000/admin/
Is there a way around this? I would prefer not to hard code the start of the urls.
I have set up Celery as described in the "first steps with Django" tutorial, and have a
myproject/myproject/celery.py
file defining the app (alongside settings.py and urls.py) and
project/myapp/tasks.py
file with the actual tasks.
reverse() always returns a domain-relative url, i.e. /admin/. One option to increase portability is to use the sites framework.
As you don't have a request object in your Celery task, you have to explicitly set the SITE_ID in your settings and set the site's name and domain in your database. Then you can do:
from django.contrib.sites.models import Site
url = "%s%s" % (Site.objects.get_current().domain, reverse('admin:index'))
Usually URLs in django are relative - i.e. the "127.0.0.1:8000" part you see when you hover the link comes from the fact that you are browsing the site from that location. Try looking at the href value of the URLs generated.
A simple solution to your problem is to concatenate the reverse output with the domain, i.e.
'http://example.com/'+reverse('admin:index')

How to make Django url dispatcher use subdomain?

I have a vague idea on how to solve this, but really need a push :)
I have a Django app running with apache (mod_wsgi). Today urls look like this:
http://site.com/category/A/product/B/
What I would like to do is this:
http://A.site.com/product/B
This means that the url dispatcher some how needs to pick up the value found in the subdomain and understand the context of this instead of only looking at the path. I see two approaches:
Use .htaccess and rewrites so that a.site.com is a rewrite. Not sure if this does the trick since I don't fully understand what the django url dispatcher framework will see in that case?
Understanding how the url dispatcher DO work I could write a filter that looks at valid sub domains and provides this in a rewritten format to the url dispatcher code.
Any hints or solutions are very much appreciated! Thanks.
Have you looked at django.contrib.sites? I think a combination of that, setting SITE_ID in your settings.py, and having one WSGI file per "site" can take care of things.
EDIT: -v set.
django.contrib.sites is meant to let you run multiple sites from the same Django project and database. It adds a table (django.contrib.sites.models.Site) that has domain and name fields. From what I can tell, the name can mean whatever you want it to, but it's usually the English name for the site. The domain is what should show up in the host part of the URL.
SITE_ID is set in settings.py to the id of the site being served. In the initial settings.py file, it is set to 1 (with no comments). You can replace this with whatever code you need to set it to the right value.
The obvious thing to do would be to check an environment variable, and look up that in the name or domain field in the Site table, but I'm not sure that will work from within the settings.py file, since that file sets up the database connection parameters (circular dependency?). So you'll probably have to settle for something like:
SITE_ID = int(os.environ.get('SITE_ID', 1)
Then in your WSGI file, you do something like:
os.environ['SITE_ID'] = 2
and set that last number to the appropriate value. You'll need one WSGI file per site, or maybe there's a way to set SITE_ID from within the Apache setup. Which path to choose depends on the site setup in question.
The sites framework is most powerful where you use Site as the target of a ForeignKey or ManyToManyField so that you can link your model instances (i.e. records) to specific sites.
Mikes solution is correct if you want to have multiple sites with same apps with different content (sites module) on multiple domains or subdomains, but it has a drawback that you need to be running multiple instances of the Django process.
A better solution for the main problem about multiple domains or subdomains is to use a simple middleware that handles incoming requests with the process_request() function and changing the documented urlconf attribute (link) of the request object to the URLconf you want to use.
More details and an example of the per-request or per-domain URL dispatcher can be found at:
http://gw.tnode.com/0483-Django/
Try adding a wildcard subdomain: usually *.