Best practices for path-agnostic links in Django? - django

What is the best way to code html links in a Django application
which is intended to be distributed to other users and
where it cannot be known in advance what the final
URL path to the application will be?
Here are some links I am currently using:
<li>By Date</li>
<li>Trends</li>
This works fine when the app is configured like this in mysite/urls.py to
be in the root path.
url(r'^', include('myapp.urls')),
But if you change mysite/urls.py to run the app in a different path:
url(r'^myapp/', include('myapp.urls')),
then the links break. This seems like it ought to be a common scenario but I have been unable to discover how to solve it cleanly.

You want url tag:
Returns an absolute path reference (a URL without the domain name) matching a given view function and optional parameters. This is a way to output links without violating the DRY principle by having to hard-code URLs in your templates

Related

Django URL to Template View Preventing Media Folder from Displaying

I have been working on a Django DRF/Vue project and ran into issues with being able to download or view files from the media folder. I have this set up as a media root and directory in the settings and included the following in my url.py file:
if settings.DEBUG:
urlpatterns += static(
settings.STATIC_URL,
document_root = settings.STATIC_ROOT
)
urlpatterns += static(
settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT
)
The issue is happening from my path to the template views.
re_path(r"^.*$", IndexTemplateView.as_view(), name="entry-point")
If I comment this line out, the media directory works as I want but this causes my application to no longer direct users to my frontend and Django template files. I am fairly new to Django and am not sure exactly how to resolve this, or if it is possible to create a condition within the path to exclude /media from being triggered?
Edit: I was able to make this somewhat work by changing re_path(r"^.*$", IndexTemplateView.as_view(), name="entry-point") to path('', IndexTemplateView.as_view(), name="entry-point"). My app currently runs Django on port 8000 and Vue app on port 8080. I access the app front end from 8080, which allows it to re-direct to the login page if necessary. If I try to refresh any page with this updated config, I am faced with the error, "Using the URLconf defined in app.urls, Django tried these URL patterns, in this order:"... and it shows a list of my api URLs. I find URL patterns with Django one of the most confusing things about trying to learn this framework. Can someone please explain to me what is causing this?
I was stuck on this for a long time and finally figured it out. Of course it was a really simple fix. All I had to do, after changing the 're_path' to 'path' was change the Vue route type to hash instead of history.

How to limit catch all urls in django

I have a django project with specific urls, setup by a 'catchall' URL.
This is so I can go to mysite/living, and have it pass living as a parameter and pull up the appropriate details from my db.
My urls.py:
url(r'^$', views.index, name='index'),
url('about/', views.about_view, name='about_view'),
url('contact/', views.contact_view, name='contact_view'),
url('(?P<colcat>[\w\-]+)/collection/(?P<name>[\w\-]+)$', views.collection_detail, name='collection_detail'),
url('(?P<colcat>[\w\-]+)/$', views.collection_view, name='collection_view'),
I am running into the problem where, anything can be passed as a parameter. This is particularly notable with search engines, where mysite/index.html/index.html returns a valid page.
Is there a way to limit the urls that are 'allowed' to be matched?
It is very unlikely for a user to enter/modify URLs manually while browsing. Everyone just googles and clicks whatever link is shown by the search engine. So, You just need to restrict what the search engine indexes.
This can be done by adding a sitemap.xml file to the root of your website.
sitemap.xml specifies all the urls of your website along with some additional information inorder to make it easier for search engines to crawl. If you don't add a sitemap.xml, search engines try to crawl through every possible url. If added they wont.
There is already a sitemap generating framework provided by django: https://docs.djangoproject.com/en/2.1/ref/contrib/sitemaps/

How are Django page templates assigned to each page?

I couldn't find this info in the Django docs, but I'm sure it is there, I'm just very new and don't know what terms/etc to search on.
How are Django page templates assigned to each page?
I have a login to a Django site, and also SFTP access to the site. I don't think my Django login is a superuser/full-admin though because the interface seems pretty limited compared to other CMS systems. I can edit pages, posts and the media library, but I don't see anything that says how each page is assigned a template.
For example, I have this file /mysite/templates/pages/index.html
I know that template is being used for the home page because it has all of the content that is specific to the home page on it, and changes I make show up on the home page.
I tried copying that file to test.html, but when I browse to test.html in my browser, I get a 404 error (I also get that error if I go to index.html). So there must be something else that maps a template to a page, but I'll be dambed if I can find it. Will I need more access to the admin area, or can I do something with SFTP? I also have SSH access but wasn't able to follow any of the steps online to create a new superuser account for me, for Django.
Edit: Thanks for both answers, after I work through this I'll accept whichever helped the most. I do not have a views.py file, but I think it might be using an extra module for this routing, I have this in my urls.py file:
urlpatterns = patterns("",
("^admin/", include(admin.site.urls)),
url("^$", "mezzanine.pages.views.page", {"slug": "/"}, name="home"),
("^", include("mezzanine.urls")),
)
Is this "mezzanine" something different which changes the answer (location of views.py or list of views)?
url.py is the file that maps the urls to methods that return rendered templates. In essence you define the url and a method and when someone goes to that url, that method gets called which returns a HTTP response with the rendered template. This map is called urlpatterns. In the following example when someone goes to yourwebsite/blog then in the blog apps, view.py, page method is called, which will use a template and render that with specific information.
urlpatterns = patterns('',
url(r'^blog/$', 'blog.views.page'),
url(r'^blog/page(?P<num>\d+)/$', 'blog.views.page'),
)
Have a look at this link.
https://docs.djangoproject.com/en/dev/topics/http/urls/
Django uses urls.py files to map paths to views. This match is resolved using regular expressions. When a match is found, Django executes the associated view (usually inside views.py). The view is in charge to render the template required for the path (by finding it on the server's hard disk and loading it).
All aforementioned means that there's no direct association between a url path (i.e www.example.com/path/to/page) and a file on the server's hard disk (i.e /server/path/to/page). It's all performed dynamically by Django's engine when a request comes in.
If you want to know which view is gonna be generated for a specific path, follow the regexs at urls.py until you find the path you're looking for. Then open the view for that url and see inside which template it is rendering.
Reading doc's URL Dispatcher is a good point to start learning about this.
Hope this helps!

Apache | Django: How to run websites on the back of a base URL?

I've got a base url. http://baseurl.com/
I'm trying to run projects on the back of it. For example
http://baseurl.com/mongoose/
The projects run but the URL don't work properly because they all
reference the base url. So for 'About Me' page it points to
http://baseurl.com/about instead of http://baseurl.com/mongoose/about
Is this something i need to change in django or apache? Is what I'm
trying to do even possible?
Coming from an IIS .net background I know that in IIS you can "Create and application" within a site which essentially does what I'm trying to achieve now with Apache and Django.
Thanks
You shouldn't need to do anything. Apache is supposed to be setting a request header called SCRIPT_NAME, which is your base URL, and all URL reversing takes that into account.
How are you creating these URLs in your templates?
Update
So your problem is with getting the URLs of Flatpages. The issue is that the normal way of calculating URLs dynamically, so that they do take SCRIPT_NAME into account - using the reverse() function or the {% url %} tag - doesn't work with Flatpages, because they are not dispatched via urls.py but via a custom middleware which fires on a 404.
So instead of using that middleware, I would use the urls.py mechanism to dispatch to flatpages. Remove the flatpagemiddleware from your settings.py, and in urls.py at the end of your patterns add this:
url(r'^(?P<url>.*)$', 'django.contrib.flatpages.views.flatpage', name='flatpage'),
Now, in your templates, you can do:
<a href="{% url flatpage page.url %}">
and it should work correctly.
Check any urls.py in the project(s) to see if they expect to be top-level. But if the application outputs links like /something then it's going to mean the root directory. The application should be reversing a view/parameter into a URL, which would allow you to move it around. If you wrote the apps, check out reverse in django.core.urlresolvers

Django: Site-Wide URL Prefix

I've built a Django site that will live at the root when it's live. Right now it's functioning perfectly at the IP address. For testing purposes, the client has pointed a proxy url at it, but the url has /folder/path in it, so none of the URL patterns match. I put (/folder/path)? into all the url patterns so they now respond, but all of the links are broken because I'm using the {% url %} tag and while the url patterns will match the optional path, they don't include it in that tag.
Clearly I can just hard-code /folder/path into all of my urls (well, into all of the url includes) until testing is complete, but is there a better way to do this?
You manage this when you deploy your application, by correctly setting the WSGIScriptAlias in your Apache configuration (assuming you're using mod_wsgi, which you should be doing). This is passed on to Django, which then automatically prefixes all URL reverse lookups with the correct value. You shouldn't need to do any manual mucking about with prefixes.
For this purpouse I use URL_PREFIX in settings.py and add it in each include in urls.py. I also add it at the beginning of MEDIA_URL, for all images/css/js links to work. But I would also like to hear about some more tricky solution?
if WSGIScriptAlias doesn't work or you can't set it up for some reason, remember that the include() function in a urlconf adds the prefix to all URLs. you can create an urlconf which includes your current root urlconf and mount it at the prefix, and then point your settings.py file to that urlconf.
Disclaimer: haven't tried this myself, but it should work.