I have been researching the various (and there are many) ways to have multiple sites under a single Django framework.
I still don't see a solution that fits well for my use case. The use case being:
A single database, as the majority of data (95%+) will be shared between two
apps
Two distinct user types, that each login via different domains,
and in fact interact with the same raw data, differently
What I want to achieve is this:
When a visitor comes to example.com, the settings for SITE_ID = 1 are in effect.
When a visitor comes to training.example.com, the settings for SITE_ID = 2 are in effect.
I want to do this because:
I want to use explicitly different UserProfile objects for the different users
I want to mix and match views and apps at my will between the different domains
Django docs on the Sites framework don't seem to help me, even though with this and some other articles around, I can see a few possibilities.
My current thinking is to actually solve it using the wsgi server (uWSGI in my case), where I'd take Django's default wsgi.py, duplicate it, and each wsgi conf wiill have its own Django settings.py.
Then the server will in fact be serving two distinct wsgi apps, even though they use much of the same code.
So, in this scenario, my Django project will have:
example.com.settings.py (SITE_ID = 1)
training.example.com.settings.py (SITE_ID = 2)
example.com.wsgi.py (uses example.com.settings.py)
training.example.com.wsgi.py (uses training.example.com.settings.py)
My scenario here should work but it will be twice the memory of solving this within the same Django instance.
Any better implementation for what I need to achieve?
For what I know settings.py is unique for every django project, and the SITE_ID is defined at this level. IMHO the best approach is to use many django projects with database routers. In each project you can define the SITE_ID for use with the django sites framework.
https://docs.djangoproject.com/en/dev/topics/db/multi-db/#database-routers
Related
Let's say I have 1 Django project where I want host multiple websites on with different domains. I managed to set it up but progressing further is where I get confused.
We'll call them store1.com, store2.com
I can route to both sites through a custom middleware that checks the url where the request comes from and that is working fine.
Both stores have it's own apps like cart, category, product, account and so forth.
What would be the best practice to structure this?
Do I put everything from a store inside 1 app or is it better to have all these models and views in a separate app and keep checking the request so that the app knows which URL to serve?
IMHO the best way is to create an app for all the different functionalities and then use Django Sites framework to manage multiple sites.
You can read more on the Django documentation
Consider a Django app built to serve multiple sites with slightly differing content using the standard Django sitesframework.
The traditional way to host this would be to configure multiple Site objects and setup the app in multiple Django projects with each project pointing to a different SITE_ID in their respective settings.py:s.
For various reasons I'd like to avoid having to create a new project for each new site. I want to be able to setup one project and have Django figure out which Site object to use based on the hostname referenced in the incoming HTTP request.
What is the recommended way to achieve this functionality?
Clarification: I want the site framework to ignore settings.SITE_ID (which is hard-coded in settings.py) and instead dynamically fetch Site objects based on what is in the Host header. Why this requirement? I'll be adding and removing sites multiple times per hour and the total amount of sites will exceed 10,000, so setting up a Django project for each site is not an option. Is this a problem that is solvable in Django? If so, what is the best way to achieve it?
The recommended way is to not attempt it at all, since settings should never change at runtime. Instead, set a variable in your virtual host configuration and have the WSGI adapter script or settings module pick one of the sites based on that.
I maintain a Django webapp for a client of mine. We built it out in Django and for computer users, it's great. We now want to cater to mobile device users.
On top of a template switch, we also need things to work differently. The application will have views that work in a subtly different way but also the URL structure needs to be simplified.
I realise what I'm about to ask for violates the DRY ethos but is there a good way to split the urls.py so that half of it is for ourdomain.com and the other half is for m.ourdomain.com? If I can do that, I can add a mobile_views.py and write the new views.
Django's Sites is enabled in the project but I'm happy to use a hard-coded request.domain.startswith('m.')-style hack. Seems like that might perform better - but I've no idea how one gets the request from the URLs file.
Use middleware to detect the access to the other site and set request.urlconf to the other urlconf that you want to use.
I am new to django and python and am trying to figure out how to modify an existing app to run multiple shops through a single domain.
Django's sites middleware seems inappropriate in this particular case because it manages different domains, not sites run through the same domain, e.g. : domain.com/uk domain.com/us domain.com/es etc.
Each site will need translated content - and minor template changes. The solution needs to be flexible enough to allow for easy modification of templates.
The forms will also need to vary a bit, e.g minor variances in fields and validation for each country specific shop.
I am thinking along the lines of the following as a solution and would love some feedback from experienced django-ers:
In short: same codebase, but separate country specific urls files, separate templates and separate database
Create a middleware class that does IP localisation, determines the country based on the URL and creates a database connection, e.g. /au/ will point to the au specific database and so on.
in root urls.py have routes that point to a separate country specific routing file, e..g
(r'^au/',include('urls_au')),
(r'^es/',include('urls_es')),
use a single template directory but in that directory have a localised directory structure, e.g. /base.html and /uk/base.html and write a custom template loader that looks for local templates first. (or have a separate directory for each shop and set the template directory path in middleware)
use the django internationalisation to manage translation strings throughout
slight variances in forms and models (e.g. ZA has an ID field, France has 'door code' and 'floor' etc.) I am unsure how to handle these variations but I suspect the tables will contain all fields but allowing nulls and the model will have all fields but allowing nulls. The forms will to be modified slightly for each shop.
Anyway, I am keen to get feedback on the best way to go about achieving this multi site solution. It seems like it would work, but feels a bit "hackish" and I wonder if there's a more elegant way of getting this solution to work.
Thanks,
imanc
There's no reason you can't the sites framework with multiple Django installations served from different subdirectories under the same domain.
OK I have done some further digging and it seems that the Django sites framework is not suitable for the same domain but with different paths:
www.mydomain.com/uk
www.mydomain.com/au
etc.
The two other options are an apache/wsgi set up where a separate wsgi and settings.py is referenced for each subdirectory. This seems a bit cumbersome; I don't really want to have to be reconfiguring apache each time I deploy a new shop. Also it'd make maintaining the local dev, online dev, staging and live versions of the site more hassle.
I think given this situation the best solution is to look at a middleware class that keeps track of country code and somehow changes database settings and root urls.py. Then each app is going to have to be aware of its current base url for things like form actions and links and so on.
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.