How to locally test Django's Sites Framework - django

Django has the sites framework to support multiple web site hosting from a single Django installation.
EDIT (below is an incorrect assumption of the system)
I understand that middleware sets the settings.SITE_ID value based on a lookup/cache of the request domain.
ENDEDIT
But when testing locally, I'm at http://127.0.0.1:8000/, not http://my-actual-domain.com/
How do I locally view my different sites during development?

Create a separate settings.py file for every site, including an appropriate SITE_ID setting. Of course you can use the import statement to share common setting between files.
From now on, when running Django development server specify the --settings option to tell Django which site to run.
For example (assuming you've got two setting files - settings_first.py and settings_second.py):
manage.py runserver --settings settings_first
will run the first site, and
manage.py runserver --settings settings_second
will give you an access to the second site.
You can also run them simultaneously, specifying different ports:
manage.py runserver 8001 --settings settings_first
manage.py runserver 8002 --settings settings_second
The above commands (run on two different consoles) will make the first website accesible under http://127.0.0.1:8001/, and the second one under http://127.0.0.1:8002/

Maybe you are mislead by the documentation. You wrote:
I understand that middleware sets the settings.SITE_ID value based on a lookup/cache of the request domain.
This is not the case. It works exactly the other way around. Django uses the settings.SITE_ID value to look up the correct Site object in the database. This returns your prefered domain and site name.
The sites application was designed to fill the (in my opinion) rare usecase that you want to have multiple sites with the same database in the background. This allows you to publish the same articles on different sites but still have the flexibility that some models are available just for a single site.
For developing multiple projects (that doesn't actually make use of the sites framework) you don't have to specify anything special. You can use the default SITE_ID set to 1. For utilizing the admin's view on website links you can set in your development database the Site's domain to localhost:8000.
If you want to develop multiple sites using the same database (and make use of the sites framework) you must have each project with a distinct SITE_ID but the same database settings. The values for SITE_ID in each project on your development machine are in most cases the same as for your production servers.

FYI - I released django-dynamicsites today which has facilities to solve this issue - https://bitbucket.org/uysrc/django-dynamicsites/src

Related

Self-hosting multiple sites via one Django project + apache - Django Sites framework

I have a self-hosted (raspberry pi) website running on Django - one project with several apps all serving on one domain name. I'm more of a programmer than a server admin, but it works! Now, I'd like to break one of those apps out onto a second domain name, but still hosting from my pi.
--I've looked into a lot of tutorials on how to do this as well as checked out answers like this one but the server-related instructions on everything I've found so far all go a bit over my head or don't seem to match up with my setup.
--I've tried the Django Sites framework and I've also followed this tutorial. While I was able to get my site objects in the db, all requests seem just to go to SITE_ID=1, regardless of domain name. I've seen conflicting information here about whether or not SITE_ID should be present in settings.py, but whenever I remove it, I just get errors about it (even though I do have the CurrentSiteMiddleware installed as well as a custom middleware like indicated in that tutorial).
Here's what I've got for Django (3.2.14, and py3.7.3), essentially:
DjangoApps
-mysite
--settings.py (allowed_hosts includes mydomain)
--urls.py (imports from app urls files)
--(etc)
-app1
--urls.py
--(etc)
-app2
--urls.py
--(etc)
-app3
--urls.py
--(etc)
and then the server confs:
/etc/apache2/sites-available/
-000-default.conf
-default-ssl.conf
-mydomain.com.conf [which points to the DjangoApps directory]
-mydomain.com-le-ssl.conf
I do not have an http.conf as mentioned in many of the tutorials/answers I've read through. I've seen some notes about using virtualenv and/or wsgi but I don't understand them, and I am requesting a more handholding step-by-step explanation of what to do here.
I assume this isn't the most optimal/modern way of doing this, but the key point here is that this main site is already live and working as-is so I'm really not looking to redo the whole thing. All I want to do is make it so that myseconddomain.com serves app3 only, and mydomain.com keeps serving everything (or, everything but app3, if that's easier).
Please help! And please let me know what other info is required.

How to do site specific configuration with Python Django

At the moment i run some django sites with site specific config by using multiple settings.py with different SITE_ID in it and application specifig APP_OPTION="foo" settings.
Now i would like to run the sites from one process selecting the site by domain (which is done by get_current_site). But in this case they share the global settings.
One option would be of course to patch the applications to use APP_OPTION[site_id]="foo", another option would be to place the settings in the database. Both seem not to be the best solutions to the problem.
Which is the most elegant way to have such site specific config values?

Django on Twisted with multiple virtual hosts?

I have a django website that I am hosting on twisted via the django WSGIHandler as described here - http://www.clemesha.org/blog/Django-on-Twisted-using-latest-twisted-web-wsgi
All seems OK up to the point where I want to add an extra "site" configuration to my django site using the django Sites framework. Doing so, I add an extra settings.py file for the new site and that seems to work.
What I then want to do is use the twisted NameVirtualHost class to be able to direct one domain (say site1.example.com) to the first settings file, then use another domain (say site2.example.com) to use the second settings file. This works with Apache & mod_wsgi.
The problem I face is that the twisted code can only access one django environment at a time. If I call setup_environ with the first settings file and setup a host for the first domain, a subsequent call to setup_environ will replace the settings file in use so therefore only one set of settings can be used at one time.
Any ideas how to proceed?
Gave up on this in the end. Looks like you cannot easily access 2 Django environments within the same twisted instance. I think it would require multiple instances of twisted with a reverse proxy or some sort of multiprocess hacking - either way its not worth the effort for me so I'm going to try something else...

Use Django flatpages without sites

Is there any that I can have a catch all site with flatpage framework in Django?
I have one site but you can get to it through a few DNS names that change constantly. I need to map these all to a single site and flatpages seems bent on me pre-specifying my domain entries.
You need to configure your webserver correctly so that the requests from all domains get forwarded to your only django instance! You cannot run flatpages without having django.contrib.sites in your INSTALLED_APPS, but that is no problem for your case, the actual site will always be determined with the SITE_ID defined in your settings.py. The sites framework does not check the request to check which is the actual site. If you run multiple sites, you have to run multiple django instances that use different settings, which define different SITE_IDs!
So just check your webserver to have everything directed to your django instance!

How do you setup a Django project with different sites using the same data?

I'm currently looking at the the documentation for Django sites:
http://docs.djangoproject.com/en/dev/ref/contrib/sites/#ref-contrib-sites
which explains how to associate content with multiple sites. The example used is LJWorld.com and Lawrence.com.
What does the Django project structure look like for the above? Is each site an app on its own, for instance:
project/
manage.py
settings.py
urls.py
ljworld/
models.py
views.py
lawrence/
models.py
views.py
If ljworld has SITE_ID=1 and lawrence has SITE_ID=2, does the SITE_ID variable has to be explicitly set in ljworld/settings.py and lawrence/settings.py?
How do you run the dev server of either ljworld or lawrence?
Update:
I used two sites with shared content in the above. What should be done if there are n different sites who are sharing the same content? Do I really need n different Django projects on n different servers, all connected to the same database server?
Moreover, if I need to make a change in settings.py which should affect all those web sites, it will be very tedious to change each of those files manually.
No, each site is not an app on its own; each site is a project on its own. The whole idea is to have different projects with a (fully or partially) shared content. So you might have a structure such as:
ljworld/
manage.py
settings.py
urls.py
ljworld_specific_app1/
...
lawrence/
manage.py
settings.py
urls.py
lawrence_specific_app1/
You would normally use two Web servers to serve the projects - though normally both would refer to the same DB server. Naturally you can also have apps which are shared between the two projects - just keep them somewhere in the server's PYTHONPATH.
Edit:
"Two Web servers" of course doesn't necessarily mean two physically different servers. They could well be two virtual hosts running under the same Web server instance - heck, you could even map the two projects to two different directories under the same virtual host.
For shared settings, you could use the same technique as for shared apps. Have a global_settings module which contains the shared settings available somewhere on the PYTHONPATH and import it from each of the settings.py.
And if you wanted something really hackish, you could probably even drop all the different projects, use just one and create a middleware that changes settings on the fly. But I would advise against it.