How can create subdomains in Wagtail?
I was looking at https://github.com/tkaemming/django-subdomains, but this uses the Django Site framework.
I have tried replacing
from django.contrib.sites.models import Site
with
from wagtail.wagtailcore.models import Site
However wagtail has no attribute 'get_current'
What can I do? Is there a solution here?
i found answer, I use django 1.11 and wagtail 1.10
and django-subdomain 2.1.0
At this time django-subdomain not support django 1.10>= so we need to
Update the middleware to be compatible with Django 1.10
i just change
class SubdomainMiddleware(MiddlewareMixin):
in middleware.py to
try:
from django.utils.deprecation import MiddlewareMixin
except ImportError:
MiddlewareMixin = object
class SubdomainMiddleware(MiddlewareMixin):
django-subdomain use django-site but wagtail use wagtail-site
so i change utils.py file
from
def current_site_domain():
from django.contrib.sites.models import Site
domain = Site.objects.get_current().domain
to
def current_site_domain():
try :
from wagtail.wagtailcore.models import Site
domain = Site.objects.get(is_default_site=True).hostname
except:
domain = "127.0.0.1"
you can get site domain with many way
now django-subdomain work with wagtail
just use http://django-subdomains.readthedocs.io/en/latest/ for Configuration
sry for my very bad english
For wildcard subdomains you have to configure your web server (nginx, apache, etc). For NGINX you have to add
server {
....
server_name *.mydomain.com;
....
}
For Apache
ServerAlias *.example.com
in your your-site.com.conf file.
Related
In the standard setup, Django applications are called by a WSGI server (like gunicorn and mod_wsgi) to answer HTTP requests, the entrypoint at user-level is the django View.
Can I make a custom entrypoint to call Django apps? If so, How I properly load a Django app?
Edit: Looking at the entrypoint in the wsgi.py file made by the startproject command, I see that 1) it sets the DJANGO_SETTINGS_MODULE var and calls get_wsgi_application which 2) calls django.setup() and 3) returns a WSGI application that will be called by the WSGI Server. 1 and 2 also happens when django's admin commands are ran. Is it enough to do 1 and 2 and have a properly loaded Django app? At 3 the django's middlewares are loaded, but they are not compatible, since I will not be doing HTTP calls (but the Django app will, of course, answer HTTP requests coming from other clients).
Is it enough to do 1 and 2 and have a properly loaded Django app?
Looking at Django's source code and this documentation, I figured out how to load a Django app. Taking as example the Django's intro tutorial, I could load the polls app and call its index view this way:
# Let Django knows where the project's settings is.
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
from django.apps import apps
# Load the needed apps
apps.populate(installed_apps=['polls.apps.PollsConfig'])
# Make sure the above apps were loaded
apps.check_apps_ready()
apps.check_models_ready()
# Call it
from polls.views import index
# Here index view is decoupled from Django's HTTP interface, so in polls/views.py you have:
# def index():
# return Question.objects.order_by('-pub_date')[:5]
print('index view: ' + str(index()))
It does not load any of the Django middlewares (they are coupled to the HTTP interface). The polls app does not depends on other installed apps, otherwise all dependencies should be loaded too.
I'm making a project in django. The aplication have to show diferent images and languages depending on the subdomain. For example: www.mysite.com will be the default page in english, but if the subdomain is mx.mysite.com the language must be spanish.
Whith django-hosts I can make that each subdomain redirect to a diferent django-app and I works well. The problem is that I want to make only one app to all diferent subdomains, only changing the language.
I think that is possible get the subdomain in a view and render the template with the language depending on the subdomain. But I don't know how to do it, please help.
THIS IS MY DJANGO HOSTS.PY where the host 'www' and 'mx' redirect to the same app 'mysite' but must be in diferent languages.
from django.conf import settings
from django_hosts import patterns, host
host_patterns = patterns('',
host(r'www', 'mysite.urls', name='www'),
host(r'help', 'help.urls', name='help'),
host(r'mx', 'mysite.urls', name='mx'),
)
General solution
Here's a general solution, which works with any supported language code and without the django-hosts package.
Write a custom middleware, which checks the subdomain, and then sets the session variable LANGUAGE_SESSION_KEY (or the cookie defined by LANGUAGE_COOKIE_NAME in settings.py. The default name is django_language.) with the language from the subdomain.
The custom middleware: (you can save it as middleware.py in the same folder as settings.py)
from django.conf import settings
from django.utils.translation import LANGUAGE_SESSION_KEY
class SetLanguageFromSubdomain:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
host = request.get_host()
# Parse language code from the host
lang = host.split('.')[0]
if lang == 'www':
lang = 'en'
# If requested language is in the languages supported by django,
# language_session_key session variable is populated with the
# supported language code.
for django_language in settings.LANGUAGES:
if django_language[0] == lang or django_language[0].endswith('-%s' % lang):
request.session[LANGUAGE_SESSION_KEY] = django_language[0]
break
response = self.get_response(request)
return response
Install this middleware between session and locale middlewares in settings.py
'django.contrib.sessions.middleware.SessionMiddleware',
#...
# put the middleware here (change projectname to your project's name)
'projectname.middleware.SetLanguageFromSubdomain',
#...
'django.middleware.locale.LocaleMiddleware',
More information about how django discovers language preference: https://docs.djangoproject.com/en/2.2/topics/i18n/translation/#how-django-discovers-language-preference
Languages supported by django: https://github.com/django/django/blob/master/django/conf/global_settings.py
More information about how to make a Django project translatable: https://docs.djangoproject.com/en/2.2/topics/i18n/translation/
More information about writing a custom middleware: https://docs.djangoproject.com/en/2.2/topics/http/middleware/
I want to get the server url in django. So I went through stackoverflow and found out that in order to do this I will have to do the following:
>>> from django.contrib.sites.models import Site
>>> mysite = Site.objects.get_current()
I tried the above inside python manage.py shell in the production server and expected mysite to give me the production server's url but it gives example.com
>>> mysite
<Site: example.com>
Am I missing some configuration or something?
The Site object is stored in the database. Change it there, and you're done.
from django.contrib.sites.models import Site
mysite = Site.objects.get_current()
mysite.domain = 'mysite.com'
mysite.name = 'My Site'
mysite.save()
Alternatively, you can change it in the /admin/ section of your site at /admin/sites/site/1/.
This allows you to run multiple sites from the same code-base.
You could try build_absolute_uri - see How can I get the full/absolute URL (with domain) in Django?
I have python/django app on Heroku (Cedar stack) and would like to make it accessible over https only. I have enabled the "ssl piggyback"-option, and can connect to it via https.
But what is the best way to disable http access, or redirect to https?
Combining the answer from #CraigKerstiens and #allanlei into something I have tested, and verified to work. Heroku sets the HTTP_X_FORWARDED_PROTO to https when request is ssl, and we can use this to check:
from django.conf import settings
from django.http import HttpResponseRedirect
class SSLMiddleware(object):
def process_request(self, request):
if not any([settings.DEBUG, request.is_secure(), request.META.get("HTTP_X_FORWARDED_PROTO", "") == 'https']):
url = request.build_absolute_uri(request.get_full_path())
secure_url = url.replace("http://", "https://")
return HttpResponseRedirect(secure_url)
Django 1.8 will have core support for non-HTTPS redirect (integrated from django-secure):
SECURE_SSL_REDIRECT = True # [1]
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
In order for SECURE_SSL_REDIRECT to be handled you have to use the SecurityMiddleware:
MIDDLEWARE = [
...
'django.middleware.security.SecurityMiddleware',
]
[1] https://docs.djangoproject.com/en/1.8/ref/settings/#secure-ssl-redirect
Not sure if #CraigKerstiens's answer takes into account that request.is_secure() always returns False if behind Heroku's reverse proxy and not "fixed". If I remember correctly, this will cause a HTTP redirect loop.
If you are running Django with gunicorn, another way to do it is to add the following to gunicorn's config
secure_scheme_headers = {
'X-FORWARDED-PROTO': 'https'
}
Run with some like this in your Procfile
web: python manage.py run_gunicorn -b 0.0.0.0:$PORT -c config/gunicorn.conf
By setting gunicorn's secure-scheme-header, request.is_secure() will properly return True on https requests. See Gunicorn Config.
Now #CraigKerstiens's middleware will work properly, including any calls to request.is_secure() in your app.
Note: Django also has the same config setting call SECURE_PROXY_SSL_HEADER, buts in the dev version.
What framework are you using for your application? If you're using Django you could simple use some middleware similar to:
import re
from django.conf import settings
from django.core import urlresolvers
from django.http import HttpResponse, HttpResponseRedirect
class SSLMiddleware(object):
def process_request(self, request):
if not any([settings.DEBUG, request.is_secure()]):
url = request.build_absolute_uri(request.get_full_path())
secure_url = url.replace("http://", "https://")
return HttpResponseRedirect(secure_url)
2020 update:
If you are using Flask, I would recommend the following:
#app.before_request
def before_request():
if 'DYNO' in os.environ:
if request.url.startswith('http://'):
url = request.url.replace('http://', 'https://', 1)
code = 301
return redirect(url, code=code)
The above works excellent on Heroku and allows you to use http in local development with heroku local.
Flask-SSLify is no longer maintained and no longer officially supported by the Flask community.
2014 original answer:
If you're using Flask, this works quite well:
Do "pip install flask-sslify"
(github is here: https://github.com/kennethreitz/flask-sslify)
Include the following lines:
from flask_sslify import SSLify
if 'DYNO' in os.environ: # only trigger SSLify if the app is running
on Heroku
sslify = SSLify(app)
For Flask use Talisman. Flask, Heroku and SSLify documentations favor the use of Talisman over SSLify because the later is no longer maintained.
From SSLify:
The extension is no longer maintained, prefer using Flask-Talisman as
it is encouraged by the Flask Security Guide.
Install via pip:
$ pip install flask-talisman
Instatiate the extension (example):
from flask import Flask
from flask_talisman import Talisman
app = Flask(__name__)
if 'DYNO' in os.environ:
Talisman(app)
Talisman enables CSP (Content Security Policy) by default only allowing resources from the same domain to be loaded. If you want to disable it and deal with the implications:
Talisman(app, content_security_policy=None)
If you don't want to disable it you have to set the content_security_policy argument to allow resources from external domains, like CDNs, for instance. For that refer to the documentation.
I'm using Django 1.1 on Google App Engine through use_library. No Django GAE helper, Django non-rel or similar tools are used here. Django handles URLs routing, forms validation etc., but I'm using pure App Engine models.
In one of my Django forms there is a FileField, which from time to time, seems to call django.core.files.uploadedfile.TemporaryUploadedFile. This class then uses tempfile.NamedTemporaryFile and this results in App Engine raising:
File "/base/python_runtime/python_dist/lib/python2.5/tempfile.py", line 45, in PlaceHolder
raise NotImplementedError("Only tempfile.TemporaryFile is available for use")
Trying to solve this problem I took uploadedfile module from Google App Engine Helper for Django (which doesn't use NamedTemporaryFile) saved it as gae_uploadedfile.py in application directory and in my _djangomain.py_ file I added:
from google.appengine.dist import use_library
use_library('django', '1.1')
(...)
import gae_uploadedfile
django.core.files.uploadedfile = gae_uploadedfile
djangomain.py is a file where i redirect all urls - in app.yaml I have:
- url: /.*
script: djangomain.py
But it didn't help, I still get this exception. What am I doing wrong, is there other solution to avoid this error while using FileField from django.forms?
You need to update the settings.py file with the following to change the default Django behaviour:
# only use the memory file uploader, do not use the file system - not able to do so on
# google app engine
FILE_UPLOAD_HANDLERS = ('django.core.files.uploadhandler.MemoryFileUploadHandler',)
FILE_UPLOAD_MAX_MEMORY_SIZE = 2621440 # the django default: 2.5MB
More info here:FILE_UPLOAD_MAX_MEMORY_SIZE and
upload-handlers
If you are uploading images you will be restricted by the 1MB quotas for image transformation etc.. Quotas_and_Limits