Change "ROOT_URLCONF" in Django depending on site - django

I just need some advice pointing me into the right direction using Django with multiple sites / clients.
Basically depending on the domain name I want to use multiple sites with only one Django instance.
For example a directory structure.
mysite/
manage.py
settings.py
client1/
url.py
client2/
url.py
So what I am thinking is, inside settings.py depending on the domain name I can change the
ROOT_URLCONF = 'mysite.clientx.urls'
The site will match about 95% so I don't see the point of changing all other settings as well.
How would I do this? I did go through site management in the Django documentation although it seems like an overkill for what I want to accomplish.
Also keep in mind I am using Apache with "django.wsgi".

Related

How many separate apps should I have with my Django app

How many apps should I have in my Django project. For instance, I am building a pet application where there can be owners, pets, veterinarians, etc.
For now sticking to only the 3 I mentioned should I have these as separate apps within my Django project or should I just create one app to handle everything. I will be adding more features as time goes on.
The idea I had was to create a project
django-admin startproject mypets
Then create an application for each:
python manage.py startapp pet
and
python manage.py startapp pet_owner
and
python manage.py startapp veterianarian
As I mentioned before, there are other features I will be adding to my application like photos todo like feature and so on. My concern is that my project is going to get big which is why I want to separate pet_owner and pet each as their own apps. I was thinking this is exactly what I should do but then realized that when I went to mypets.urls.py file and I was thinking about forwarding some requests to a path I quickly realized that I want my route to always have mypets/.
urlpatterns = [
path('admin/', admin.site.urls),
path('mypets/petowner/', include('petowner.urls')),
path('mypets/pet/', include('pet.urls')),
]
but they seem separate in a way that I do not want them to be. For instance. I care about having mypets/petowner/<petowner-id>/pets/ etc. They are going to be very closely related to each other and I will be using relationships in my models. The separation that I want is mostly for organization and readability. I do not want to have a file models.py with a huge amount of code - I think that is ugly and messy.
I plan in the future to use React for my frontend, but because I'm trying to learn Django well I'm going to stick to a full Django app and use django-templates. Not sure if this matters but thought I would mention it just in case.
that is good idea and make project more organized specially for you
if you want to develope your code in the future this works and good for you
if you have problem with urls, now i have a suggestion, you can make a file like url.py in your app which contains your apps urls and then you can back to your main url and give it to urls it seems you know this way
first run your app and make it
now got to app folde and make a file like urls.py
now into that you can write your urls and write your urls in urlpattern as you know
before finish make sure that in the main url.py you have to include other urls that made
urlpatterns = [
path('', include('petowner.urls')),
path('admin/', admin.site.urls),
]
maybe this is good to change your names if involve you too much and write your urls in that app by this way you can be more organized and give your prefix or anything just in your app/urls.py

Integrating Sphinx and Django in order to require users to log in to see the documentation

I am curious if it is possible to hide sphinx documentation inside a django app so that only people who log in can see it. It seems to me that since sphinx creates its own structure and that Django uses the urlconf to define which pages a user can see, that it wouldn't be possible to combine the two. Although there must be some combining since the Django website likely uses django and sphinx. I am wondering if anyone has any insight or if they can point me in the right direction.
Thank You in Advance!
Sphinx builds your docs into HTML files, so in most cases this docs should be served by your web server rather then Django. However Django is able to serve static files as well.
You can use the django.views.static.serve function to do this and wrap this function with login_required. E.g:
from django.views.static import serve
from django.contrib.auth.decorators import login_required
urlpatterns += patterns('',
url(r'^docs/(?P<path>.*)', login_required(serve), {'document_root': '/path/to/sphinx/build/html'}, 'docs'),
)
However this configuration will be considered a bad practice in production environment as in this case Django will serve both html and css/js files from your sphinx theme.
The first improvement you can do here is to serve /path/to/sphinx/build/html/_static/ with apache/nginx or whatever you use.
The more proper way is to serve docs with apache/nginx and make it handle the auth itself. Unfortunately I made a quick Google search but did not find a way to use Django's User model to handle http_auth in apache or other. Alternatively you can use something like mod_sendfile or X-Accel modules - http://www.wellfireinteractive.com/blog/nginx-django-x-accel-redirects/ In a nutshell - Django app checks permission if user can view the file and add special header to response containing file path. Webserver will serve this file instead of original message from django

simplest way to combine two Django projects

Best case scenario: Just modify the urlpatterns of one of them to include the urlpatterns of the other.
But as of now they both have seperate settings.py, seperate DB's, seperate directories. I assume I may have to somehow merge their two settings.py, include one of them in the other's INSTALLED_APPS, and resolve a bunch of directory issues. Can I somehow just have one invoke the other through urls.py and forego all the above. Any website documentation covering all this in detail, that's the main thing. Sorry if this has been asked. The problem is the existing Django project is running under one uwsgi process on the server, and adding another uwsgi process bumps it up to another account level.
Not sure if this is what you mean by "invoke the other through URLs.py", but you can include URLs from one app within another very easily. For example:
urlpatterns = patterns('', url(r'^polls/', include('polls.urls')))
That will include all the URLs in the polls app. You can read more on it here:
https://docs.djangoproject.com/en/dev/intro/tutorial03/#decoupling-the-urlconfs
This is state of my knowledge now. Something like uwsgi and I guess other server schemes ask for the specification of a single settings.py as a parameter. So as far as integrating multiple Django projects in a single uwsgi process, they will have to share a single settings.py. The only problem there is only one setting for MEDIA_URL and MEDIA_ROOT. And the only solution I see is putting the media from both projects in one folder - seems unreasonable. Am I missing something.

Changing Django settings variable dynamically based on request for multiple site

Please advice whether is it correct method to change the urlconf and templatedir variables of a django settings file dynamically within a custom middleware function based on the site requested.
No. I don't know why you would want to do this. If you have multiple sites, the correct way to serve them is with multiple WSGI instances, each pointing at separate settings.py and urls.py files.
Edit after comment: This has nothing to do with the sites framework, which is completely optional. As I say, if you want to serve multiple sites, use multiple .wsgi scripts each pointing to a separate urls.py and settings.py. All the rest of the code can be the same.

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.