1. Introduction
I was working on ~/django_projects/mysite/ and the Web setting on my PythonAnywhere is:
Now I am working on ~/django_business/proj01/ and I am using venv/. Apparently, I need to change Web settings on my PythonAnywhere.
2. How should I change Web settings
In the blog of August 07, 2025 Django: urls.py, You said:
After That:
Visit:
http://127.0.0.1:8000/client_portal/
You should see:
Hello from Client Portal!
However, I am working on the console of PythonAnywhere. Its Web tubs reads:
Code:
What your site is running.
Source code:
/home/myid/django_projects/mysite
Working directory:
/home/myid/django_projects/mysite
WSGI configuration file:/var/www/myid_pythonanywhere_com_wsgi.py
Python version:
3.13
Do I have to change /django_projects/mysite into /django_business/proj01?
Yes — if you want your PythonAnywhere web app to run your new ~/django_business/proj01 project instead of
the old ~/django_projects/mysite, you’ll need to update the Web tab settings to point to the new
project’s files.
Here’s what you need to change in PythonAnywhere’s Web tab:
1️⃣ Source code
-
Change from:
to:
This should be the folder containing manage.py.
2️⃣ Working directory
-
Also change from:
to:
3️⃣ WSGI file update
Open:
and find the section where it says:
Change it to:
Also update the DJANGO_SETTINGS_MODULE line if needed:
(not mysite.settings).
4️⃣ Virtualenv
In the Web tab, under Virtualenv, make sure you point it to your new ~/django_business/venv (if that’s
the one you created for proj01):
5️⃣ Reload
Click Reload in the Web tab to apply changes.
If you don’t change these, PythonAnywhere will keep running your old mysite project, so visiting /client_portal/ will never hit your new code in proj01.
I can give you the exact before/after WSGI file edits so you don’t accidentally break it. Do you want me to prepare that?
[MY NOTE]
This is the primitive way to switch projects. I did in accordance with the explanation.
My modified wsgi file is:
import os
import sys
#path = os.path.expanduser('~/django_projects/mysite') # old path
path = os.path.expanduser('~/django_business/proj01') # new path
if path not in sys.path:
sys.path.insert(0, path)
#os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings' # old path
os.environ['DJANGO_SETTINGS_MODULE'] = 'proj01.settings' # new path
from django.core.wsgi import get_wsgi_application
from django.contrib.staticfiles.handlers import StaticFilesHandler
application = StaticFilesHandler(get_wsgi_application())
I successfully got the right result:
3. A simpler way
Do I always have to do these changes whenever I switch projects? Is there any simpler way?
Yes — on PythonAnywhere free accounts, you can only have one web app per domain, and that web app is always tied to a single project path, so if you want to switch between projects you have to edit the Web tab + WSGI file (and maybe the virtualenv) each time.
That’s why it feels a bit tedious — because there’s no built-in “project switcher” on the free plan.
Your options to make it simpler:
1️⃣ Keep one “active” project folder
-
Decide on a single folder that your web app points to, e.g.:
-
Whenever you want to switch projects, just copy or symlink the project you want to test into that folder:
That way, the Web tab settings never change — you only swap the contents of django_active.
[MY NOTE] If you want to go back to the original project, run:
rm -rf ~/django_active
cp -r ~/django_projects/mysite ~/django_active
2️⃣ Use multiple web apps (paid plan)
-
On the $5/month plan or higher, you can have multiple web apps:
-
One at
myid.pythonanywhere.comformysite -
One at
proj01.myid.pythonanywhere.comforproj01
-
-
This way you don’t touch settings to switch.
3️⃣ Keep development local and only deploy the final project
-
Use your computer for development/testing with
runserver. -
Deploy to PythonAnywhere only when ready.
-
This avoids frequent switching.
If you plan on doing this often, I’d recommend Option 1 (single “active” project folder) — it’s the easiest workaround for free accounts and doesn’t require touching the Web tab every time.
I can walk you through setting up the symlink approach, so you can switch projects in seconds without touching PythonAnywhere settings. Would you like me to show that?
4. WSGI file
You said:
I can give you the exact before/after WSGI file edits so you don’t accidentally break it. Do you want me to prepare that?
Yes. Can you prepare it for me?
Alright — I’ll prepare a before/after guide for the WSGI file so you can easily switch from your current project (mysite) to your new one (proj01 in ~/django_business/).
On PythonAnywhere, your WSGI file is here:
Before (current mysite setup)
It probably looks something like this (key part shown, yours may have comments too):
After (switch to proj01)
You’d change it to:
Steps to switch projects
-
Go to the Web tab in PythonAnywhere.
-
Open your WSGI file (
/var/www/myid_pythonanywhere_com_wsgi.py). -
Edit the two things:
-
The
pathvariable to point to your new project folder -
The
DJANGO_SETTINGS_MODULEto match your new project name
-
-
Save.
-
Reload your web app.
💡 Pro tip for faster switching:
Instead of editing this file every time, you could:
-
Keep a single folder like
~/django_active/ -
Point the WSGI file once to
django_active -
Then, when you want to switch projects:
-
Reload web app → Done.
If you want, I can prepare the symlink-based WSGI file so that you never edit the WSGI again when switching projects — just run one terminal command. That will make switching nearly instant.
5. Symlink-based WSGI file (this is the best way)
(1) What is the symlink-based WSGI file?
A symlink-based WSGI file is a small trick so that your PythonAnywhere web app always looks at a single folder name, but you can switch that folder to point to any project you want — without touching the WSGI file again.
Here’s the idea:
1️⃣ How it normally works
Right now, your WSGI file points directly to your project folder:
If you switch to a new project (say proj02), you must edit the WSGI file to change both the path and
the settings module.
2️⃣ The symlink approach
Instead, we make the WSGI file point to a fixed directory name like:
But django_active is not a real folder — it’s a symbolic link (shortcut) that points to whichever project you want active.
So your WSGI file stays like this forever:
import os
import sys
path = '/home/myid/django_active'
if path not in sys.path:
sys.path.append(path)
os.environ['DJANGO_SETTINGS_MODULE'] = 'proj01.settings' # Or 'proj02.settings' if both use same name
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
[MY NOTE]
The problem of this approach is that you have to manually modify 'proj01.settings' to a different one each time you switch projects. Therefore, you still have to edit the WSGI file. As shown below, I solved this problem using .env and the dotenv module. With these, you don't have to edit this line anymore.
3️⃣ How you switch projects
Let’s say you now want to switch from proj01 to proj02:
Then reload your web app — done ✅
4️⃣ The main benefits
-
You never edit the WSGI file again.
-
Switching projects is one or two terminal commands.
-
No risk of typos breaking your WSGI settings.
Since your proj01 and proj02 might have different settings.py module names, we can also make the WSGI file read the settings module
name from an .env file, so you don’t have to edit Python code even for that.
If you want, I can make you a ready-to-use WSGI file that:
-
Uses
django_activesymlink -
Reads the correct
settingsmodule from.env
That way, switching projects would take you 5 seconds.
Do you want me to prepare that?
(2) You said:
If you want, I can make you a ready-to-use WSGI file that:
- Uses django_active symlink
- Reads the correct settings module from .env
That way, switching projects would take you 5 seconds.
Do you want me to prepare that?
Yes. Can you prepare it?
Alright — here’s the ready-to-use WSGI file that works with your django_active symlink
and reads the correct DJANGO_SETTINGS_MODULE from a .env
file inside your active project.
myid_pythonanywhere_com_wsgi.py
import os
import sys
from pathlib import Path
from dotenv import load_dotenv
# Path to the active project (symlink)
project_path = Path(os.path.expanduser('~/django_active'))
# Add project root to sys.path
if str(project_path) not in sys.path:
sys.path.insert(0, str(project_path))
# Load .env from the project root (if it exists)
env_path = project_path / ".env"
if env_path.exists():
load_dotenv(env_path)
# If DJANGO_SETTINGS_MODULE is set in .env, use it
settings_module = os.getenv("DJANGO_SETTINGS_MODULE")
# Otherwise, auto-detect settings.py
if not settings_module:
for item in project_path.iterdir():
if (item / 'settings.py').exists():
settings_module = f"{item.name}.settings"
break
else:
raise RuntimeError("Could not find a Django settings.py in ~/django_active")
os.environ['DJANGO_SETTINGS_MODULE'] = settings_module
# Standard WSGI application setup
from django.core.wsgi import get_wsgi_application
from django.contrib.staticfiles.handlers import StaticFilesHandler
application = StaticFilesHandler(get_wsgi_application())
[MY NOTE]
The above code is too lengthy and I modified it to a simpler code. It automatically sets os.environ['DJANGO_SETTINGS_MODULE'] with the value written in the .env file. Here is my new WSGI file:
/var/www/myid_pythonanywhere_com_wsgi.py
import os
import sys
from pathlib import Path
from dotenv import load_dotenv
#path = os.path.expanduser('~/django_projects/mysite')
#path = os.path.expanduser('~/django_business/proj01')
path = os.path.expanduser('~/django_active')
if path not in sys.path:
sys.path.insert(0, path)
#os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'
#os.environ['DJANGO_SETTINGS_MODULE'] = 'proj01.settings'
load_dotenv(Path(path) / ".env")
os.environ['DJANGO_SETTINGS_MODULE'] = os.getenv("DJANGO_SETTINGS_MODULE")
from django.core.wsgi import get_wsgi_application
from django.contrib.staticfiles.handlers import StaticFilesHandler
application = StaticFilesHandler(get_wsgi_application())
My .env files include:
~/django_business/proj01/.env
# This is used in /var/www/myid_pythonanywhere_com_wsgi.py
DJANGO_SETTINGS_MODULE=proj01.settings
~/django_projects/mysite/.env
# This is used in /var/www/myid_pythonanywhere_com_wsgi.py
DJANGO_SETTINGS_MODULE=mysite.settings
With this symlink approach, I don't need to modify the Code section on the Web tub and the WSGI file. However, I still need to modify the Virtualenv section when I switch projects.
Why this is nice
-
Works with
django_activesymlink → No hardcoding project paths. -
Reads
.env→ You can explicitly set:…or leave it blank to let WSGI auto-detect.
-
No edits when switching projects → Just change the symlink and reload.
Example .env in project root
Switching projects
If you want, I can now make you the switch_django shell
script so this whole symlink + reload step becomes a single command. That would make switching truly painless.
6. ln -s path1 path2
(1) Is this a copying command?
ln -s ~/django_business/proj01 ~/django_active
Nope —
ln -s ~/django_business/proj01 ~/django_active does not copy anything.
It creates a symbolic link (think of it like a shortcut on your desktop) called django_active that
points to the folder ~/django_business/proj01.
So:
-
No files are duplicated.
-
The
django_active“folder” is just a reference. -
If you go into
django_active, you’re actually looking insideproj01.
If later you want to switch to proj02, you just delete the link and make a new one:
That’s why this trick is nice — the WSGI file always points to django_active, but you can swap which real project it’s linked to.
I can show you a before/after diagram of your current setup vs. the symlink setup if you want so you see exactly how it fits together.
(2) Okay, I understand `ln` means symbolic link. What does -s mean?
The -s in ln -s means "symbolic" (or "soft") link, as opposed to
a hard link.
Here’s the quick difference:
| Type | What it does | Can link to a directory? | Breaks if target is deleted? |
|---|---|---|---|
Hard link (ln file linkname)
|
Creates a second name for the same file’s data on disk. Both are equal. | ❌ No (for directories) | ❌ No (data stays until all links are gone) |
Symbolic link (ln -s target linkname)
|
Creates a shortcut pointer to the original file/directory path. | ✅ Yes | ✅ Yes (link becomes "broken" if target is removed/moved) |
So in your case:
-
-s→ make it a symbolic link (so it can point to a directory like your project folder). -
~/django_business/proj01→ target (the real folder). -
~/django_active→ link name (the shortcut you’ll use in WSGI).
Without -s, the ln command would try to make a hard
link, which isn’t allowed for directories in most systems.
If you like, I can show you how to check that your link is working correctly before changing your WSGI.
7. Don't create the folder ~/django_active/
To use simlink, first I am going to create ~/django_active/ by:
cd ~
mkdir django_active
Is it okay ~/django_active/ empty?
If you’re going to use a symlink, you actually don’t need to create ~/django_active/ first.
Here’s why:
When you run:
ln -s will create django_active as a link pointing to ~/django_business/proj01.
If you already make a real directory called ~/django_active/, the ln -s command will instead try to
create the link inside that directory, which is not what you want.
So the correct steps are:
After that:
You should see something like:
Do you want me to explain how this symlink trick will let you switch Django projects on PythonAnywhere without touching the WSGI file every time?
8. -rf
What does -rf mean in this?
rm -rf ~/django_active
rm -rf is the nuclear option for deleting things in Linux.
Let’s break it down:
-
r→ recursive — removes directories and their contents (subfolders/files). -
f→ force — ignores warnings/errors (e.g., “are you sure?”, “file not found”).
So:
means:
“Delete
django_active(whether it’s a file, directory, or symlink), don’t ask questions, and keep going even if there are errors.”
If django_active is a symlink, this command removes only the link — it does not delete the original folder (proj01 in your case).
⚠️ Caution:
If you run rm -rf on the real folder instead of the symlink, the entire project will be gone with no
recovery.
If you want, I can give you a safe version of the command that only removes the symlink and refuses to delete a real directory by accident.
9. What about the virtualenv?
My current Web settings are:
Code:
Source code:
/home/myid/django_business/proj01
Working directory:
/home/myid/django_business/proj01
WSGI configuration file:/var/www/myid_pythonanywhere_com_wsgi.py
Python version:
3.13
Virtualenv:
/home/myid/django_business/venv
To use simlink, I am going to make these into this:
Code:
Source code:
/home/myid/django_active
Working directory:
/home/myid/django_active
WSGI configuration file:/var/www/myid_pythonanywhere_com_wsgi.py
Python version:
3.13
Virtualenv:
However, how can I deal with the Virtualenv?
Gotcha — if you’re switching to the symlink-based project structure (~/django_active → points to
whichever project you’re currently working on), your Virtualenv setup in the Web tab will stay the same.
Here’s how it works:
1️⃣ The virtualenv path in the Web tab
The Virtualenv setting in PythonAnywhere’s Web tab should point to the actual environment folder
(e.g., ~/django_business/venv), not to your symlink.
So in your case, keep this as:
That way, no matter which project django_active points to, you’ll still be using the same Python environment.
2️⃣ Why not put the venv inside django_active?
If you put the virtualenv inside the project folder and switch symlinks, the Web tab would need updating every time — defeating the whole point of
the symlink trick.
By keeping venv outside, it’s shared and doesn’t require changes when you switch projects.
3️⃣ Your final Web tab settings after switching
After creating the symlink:
Web tab will be:
Source code:
Working directory:
Virtualenv:
Python version:
If you like, I can write out the full step-by-step sequence for switching projects with symlinks in PythonAnywhere so you never have to reconfigure the Web tab again. That would make this totally smooth.
10. How to use symlinks
Can you write out the full step-by-step sequence for switching projects with symlinks in PythonAnywhere?
Alright — here’s your full, safe, repeatable sequence for setting up and switching Django projects on PythonAnywhere using a symlink so you don’t touch the Web tab again.
1️⃣ Initial Setup (done once)
We’re going to make ~/django_active a “pointer” to whichever project you’re currently working on.
1.1 Create the symlink target folder
This means ~/django_active now points to ~/django_business/proj01.
1.2 Web tab configuration (done once)
In the PythonAnywhere Web tab, set:
-
Source code:
-
Working directory:
-
Virtualenv:
-
Python version:
Then click Reload.
✅ Now, your web app will always run the project that django_active points to.
2️⃣ Switching to a Different Project (repeat as needed)
Say you have another project here:
To switch:
Then:
Finally:
(This tells PythonAnywhere “something changed” so it reloads.)
Then click Reload in the Web tab.
3️⃣ Rules for this setup
-
Keep venv outside of any project folder (like you did in
~/django_business/venv). -
Put each Django project in its own folder (e.g.,
proj01,proj02, …). -
Always update your
requirements.txtfor each project, so the sharedvenvcan install what’s needed before switching.
If you follow this, you’ll never have to change the Web tab’s Source code, Working directory, or Virtualenv again — you’ll just flip the symlink.
If you want, I can also give you a "switch_project" shell script so switching is just one command like:
Would you like me to prepare that script?
11. symlink for venv
What if proj02 use /home/myid/.virtualenv/django52 as a virtualenv? Do I have to rewrite the Web settings?
Yes — if proj02 uses a completely different virtualenv like:
then you must update the Web tab’s Virtualenv setting, because the symlink trick only works for the source code and working directory.
The Web tab doesn’t “follow” the symlink for the virtualenv — it just uses the path you give it.
Your choices are:
Option 1 — Keep one shared venv for all projects
-
Put the virtualenv outside your project folders (like
~/django_business/venv). -
Install each project’s dependencies into it before switching.
-
Pros: No Web tab changes.
-
Cons: venv can get messy if projects have different dependency versions.
Option 2 — One venv per project
-
proj01→~/django_business/venv_proj01 -
proj02→/home/myid/.virtualenvs/django52 -
You’d have to manually change the Web tab Virtualenv path each time you switch.
-
Pros: Keeps dependencies clean.
-
Cons: Web tab change required when switching.
Option 3 — One venv per project, but use a symlink for venv too
You can do the same symlink trick for your virtualenv:
Then set the Web tab’s Virtualenv to:
Now switching projects means:
-
Point
django_activeto the project folder. -
Point
django_active_venvto the project’s venv.
If you want switching to be one command no matter which venv the project uses, Option 3 is the cleanest.
Do you want me to write you a switch_project script that updates both the project folder and the venv symlink at once? That way, you never touch the Web tab again.
[MY NOTE]
Option 3 didn't work, somehow. In the Virtualenv section, I wrote:
/home/myid/django_active_venv
But Pythonanywhere didn't recognize the path as a virtualenv. So, I decided to stick to Option 2. I am going to write virtualenvs manually each time I switch projects.
