Adding domain path to django html templates - django

I am serving a django app with a combination of nginx reverse proxy and waitress. In the nginx configuration the app is linked via a location:
location /app/ {
proxy_pass http://localhost:8686/;
}
While the app runs on via waitress on port 8686.
Now, if I go to the domain.com/app, I the index page is served correctly. Though, my django html template contains the following link:
<p> You are not logged in.</p> <button>Login</button>
When I press that button I get to
domain.com/accounts/login
but it should be
domain.com/app/accounts/login
I wonder how to change the code so that it works independently of where the app is linked.
In urls.py the urls are included like this:
urlpatterns: = [...,
path('accounts/', include('django.contrib.auth.urls'))]

Define the url in urls.py (most probably you've already done this) and then use reverse in templates:
<button>Login</button>
Then rewrite URLs in nginx to make your app think that you're accessing /accounts/login instead of /app/accounts/login:
location /app/ {
rewrite ^/app(.*)$ $1 last;
proxy_pass http://localhost:8686/;
}
Docs:
https://docs.djangoproject.com/en/2.2/ref/templates/builtins/#std:templatetag-url
https://www.nginx.com/blog/creating-nginx-rewrite-rules/

Related

Redirecting old PHP links to Django urls

I am getting a lot of search engine referral links for my previous PHP developed site that has now been migrated over to Django. I made a url redirect for the old php links like search.php?name=john+smith to the same view for my django search url as shown here:
urls.py
url(r'^search.php/$', profile_search, name='search'),
url(r'^search/$', profile_search, name='search'),
Will Google eventually update those old links if I redirect through urls.py or do I need to make a 301 redirect? If so how would I do this with django and nginx?
I would do this at nginx level - this is much more efficient than having Django handle it. Assuming the Django view expects the same query arguments, you can do this in your nginx server block:
location = /search.php {
return 301 http://$server_name/search/$is_args$args;
}
This will redirect all requests for search.php to /search/, preserving any query arguments.
A 301 response is definitely the correct approach - you don't want to serve duplicate content on different URLs.
Unless you have HttpResponseRedirect in your profile_search method, you don't actually have any sort of redirect here at. But what you really want to use is HttpResponsePermanentRedirect
def profile_search(request):
return HttpResponsePermanentRedirect('/somether/url/?based_on_request_params')

Django root site in virtual directory

The following is the setup:
I have a virtual directory in IIS 6 in which my Django app lives, IIS is configured to pass every request on that virtual directory to the Django WSGI handler
Let's say this is domain.com/virtual/
In my Django dev URL CONF I had urls configured like this: url( r'^home$, 'project.views.home' )
Question:
Is there an easy way (through Django settings OR server settings) to set some kind of ROOT_URL for the django app? (Without manually prepending as this is incompatbile with i18n_patterns)
Django should treat all patterns as rooted in the ROOT_URL and redirect - again - relative to that same ROOT URL.
Thank you in advance
I have done this in the past.
In your settings file add a setting called something like:
VIRTUAL_DIRECTORY = "your_virtual_directory/"
If you are doing dev or have this behind it's own site domain you can keep it blank.
Then in your site's urls.py file add this to all of your top level url patterns:
from django.conf import settings
urlpatterns = patterns('',
url(r'%sadmin' % settings.VIRTUAL_DIRECTORY),
)
Do the string pattern for all of your url patterns. You will only need to do this at the site level urls.py not for every app. This way if you have a non blank VIRTUAL_DIRECTORY then it will prefix it to all of your top level url patterns.

Django redirects missing out WSGIScriptAlias part of url

I have a django application set up using mainly the admin interface with a few of my own views. Everything is working corrctly on the devlopment server on my local machine.
However on the production server, using Apache, and mod_wsgi, it is messing up the URLs when I issue a redirect statement in one of my views. Instead of going to
www.hostname.com/wsgi/django/admin/myapp/myform.html
it goes to
www.hostname.com/admin/myapp/myform.html
Apache doesn't recognise anything under an admin folder, so I get an error.
So in my apache configuration I have the following, so that anything under wsgi/django gets sent to my app:
WSGIScriptAlias /wsgi/django /project/production/public/wsgi/django_eclipse/myapp.wsgi
In my problematic view I have the following:
return redirect('/admin/sequencing/load_flowcell?' + params )
I can make this work, if I change the redirect to include the '/wsgi/django' part, but this means I can't keep the one on my development server the same. Is there a way in Django settings, or http.conf to set this so that my redirect automatically includes this part of the URL?
Django can use the sites framework to generate correct urls when reversing -- if you change the domain field in the Site row associated with your site (as indicated by SITE_ID in your settings.py) to http://www.hostname.com/wsgi/admin, then everything should work fine.
(There may also be a few places where you have plain urls, e.g. the LOGIN_URL or LOGIN_REDIRECT_URL settings that you should make sure include the /wsgi/admin part.)
Well, it's redirecting to exactly the URL that you told it to.
This is why you should never hard-code URLs anywhere in Django. If you used the URL-reversing functionality, it would automatically add the WSGI prefix - it knows about it already, and takes it into account when you use the {% url %} tag or the reverse() function.
Give the URL a name in your urls.py, and use that in the call to redirect rather than the URL, and all should work fine. No need for more settings.
EDIT: REAL FIX
from django.core.urlresolvers import reverse, get_script_prefix
....
#only of you absolutely HAVE to have a hardcoded url
return redirect(get_script_prefix()+'admin/sequencing/load_flowcell?'+params )
#better!
return redirect(reverse('admin:index')+sequencing/load_flowcell?'+params )
CAVEAT:
https://docs.djangoproject.com/en/dev/howto/deployment/modpython/#basic-configuration
<Location "/mysite/">
SetHandler python-program
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
PythonOption django.root /mysite <---- Make sure you have this
PythonDebug On
</Location>

Django/Apache address problem

I have a django app running on http://djangohost/appaddress. I'd like the project to be available at http://differentaddress/app . Currently I'm able to run app at the desired address but using {% url %} templatetags gives me improper address in the form http://differentaddress/app/appaddress. Also when I go to django app address directly all {% url %} links are in the form http://djangohost/app/appadress How can I change this ? I have these entrances in apache conf :
ProxyPass /app/ http://djangohost/appaddress/
ProxyPassReverse /app/ http://djangohost/appaddress/
You'll probably have to tell Django where it is running by manipulating SCRIPT_NAME
http://docs.djangoproject.com/en/dev/ref/settings/?from=olddocs#force-script-name
Or, if you want to keep things within Apache, you may give a try to mod_proxy_html - disclaimer: haven't used it myself, but it does claim to rewrite links in HTML pages
Maybe not a proper solution but still some workaround for the problem without interfering with apache's settings. Tested with mod_msgi and it works like a charm. Here's the link :
http://fromzerotocodehero.blogspot.com/2011/01/using-proxypass-with-django-project.html . Basically I've overriden built in url function here creating custom urlc temlpatetag. In tag's code I've added line replacing first occurence of unwanted app name with empty sign.
So you want to "mount" a Django site on a sub URL path? I already tried this with Apache and mod_proxy, and it was kind of a nightmare to find out. Here's what I have come up with (probably not complete or perfect):
# In your scenario
FORCE_SCRIPT_NAME = "/app/"
# End of settings
_prefix = (FORCE_SCRIPT_NAME or "")
LOGIN_URL = _prefix + LOGIN_URL
LOGIN_REDIRECT_URL = _prefix + LOGIN_REDIRECT_URL
LOGOUT_URL = _prefix + LOGOUT_URL
ADMIN_MEDIA_PREFIX = _prefix + ADMIN_MEDIA_PREFIX
Obviously, this prepends "/app/" to the most important hardcoded site URLs, plus it sets FORCE_SCRIPT_NAME to ensure that {% url something %} will result in an absolute URL of "/app/something", for instance.
This worked for me using mod_wsgi for the Django site and ProxyPass/ProxyPassReverse for the "mounting". Try it out and give me feedback, I'm interested whether this is a general solution.

Unable to make a domain redirection in Django from example.com to www.example.com

I get the following message when I browse to example.com
500 - Internal Server Error
I get my 404 error message when I browse to www.example.com which indicates my site is alive.
How can you make a domain redirection without .htaccess by Django from example.com to www.example.com?
My urls.py
from django.conf.urls.defaults import *
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
# Example:
# (r'^{{ project_name }}/', include('{{ project_name }}.foo.urls')),
(r'^home/', include('index.html')),
# Uncomment the admin/doc line below and add 'django.contrib.admindocs'
# to INSTALLED_APPS to enable admin documentation:
(r'^admin/doc/', include('django.contrib.admindocs.urls')),
(r'^admin/(.*)', admin.site.root),
)
[edit]
I have the following answer from Djangohosting:
Remove the website proxy for [example.com] and add [example.com] in the aliases section of the [www.example.com] website.
I am not completely sure what it means.
How can you remove the website proxy for example.com?
Where can you find the aliases section of the website www.example.com?
I don't know if it solves all your problems but if you want to do it via django, try a middleware
from django.http import HttpResponseRedirect
class WWWRedirectMiddleware(object):
def process_request(self, request):
if not request.META['HTTP_HOST'].startswith('www.'):
return HttpResponseRedirect('http://www.example.com')
Remember that it must be executed before any other middleware.
Based on this one, didn't test it.
Checking out PREPEND_WWW setting might help.
The 500 Internal Server error is likely caused by this line:
(r'^home/', include('index.html')),
The include() function is a way to include other URL config files, not static HTML files. You'd have to either serve index.html as a static file at the given URL (/home), or write a view that simply renders the file.
I get the following message when I browse to example.com
500 - Internal Server Error
I get my 404 error message when I browse to www.example.com which indicates my site is alive.
It is likely the other way around. The 500 message means that your site is active, but giving an error. What you have to understand is that the example.com/www.example.com part of the url serves to find which server to connect to. By the time your Django application gets called, this part has already been completed, so there os no way to do this from Django.
Instead, you want to set up www as a subdomain of example.com and make them point the same place. See the first example here: virtualhosts examples
UPDATE I just noticed that you stated that your 404 was showing up, so ignore the first two sentences. Either way, the solution would likely be the same. :-)