· 

Production: Changing projects on PythonAnywhere

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:

swift
/home/myid/django_projects/mysite

to:

swift
/home/myid/django_business/proj01

This should be the folder containing manage.py.


2️⃣ Working directory

  • Also change from:

swift
/home/myid/django_projects/mysite

to:

swift
/home/myid/django_business/proj01

3️⃣ WSGI file update

Open:

bash
/var/www/myid_pythonanywhere_com_wsgi.py

and find the section where it says:

python
path = '/home/myid/django_projects/mysite'

Change it to:

python
path = '/home/myid/django_business/proj01'

Also update the DJANGO_SETTINGS_MODULE line if needed:

python
os.environ['DJANGO_SETTINGS_MODULE'] = 'proj01.settings'

(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):

swift
/home/myid/django_business/venv

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.:

bash
~/django_active
  • Whenever you want to switch projects, just copy or symlink the project you want to test into that folder:

bash
rm -rf ~/django_active
cp -r ~/django_business/proj01 ~/django_active

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.com for mysite

    • One at proj01.myid.pythonanywhere.com for proj01

  • 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:

bash
/var/www/myid_pythonanywhere_com_wsgi.py

Before (current mysite setup)

It probably looks something like this (key part shown, yours may have comments too):

python
import os
import sys
# The directory containing your Django project
path = '/home/myid/django_projects/mysite'
if path not in sys.path:
sys.path.append(path)
os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

After (switch to proj01)

You’d change it to:

python
import os
import sys
# The directory containing your Django project
path = '/home/myid/django_business/proj01'
if path not in sys.path:
sys.path.append(path)
# Change to your new settings module
os.environ['DJANGO_SETTINGS_MODULE'] = 'proj01.settings'
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

Steps to switch projects

  1. Go to the Web tab in PythonAnywhere.

  2. Open your WSGI file (/var/www/myid_pythonanywhere_com_wsgi.py).

  3. Edit the two things:

    • The path variable to point to your new project folder

    • The DJANGO_SETTINGS_MODULE to match your new project name

  4. Save.

  5. 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:

bash
rm -rf ~/django_active
ln -s ~/django_business/proj01 ~/django_active
  • 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:

python
path = '/home/myid/django_business/proj01'
os.environ['DJANGO_SETTINGS_MODULE'] = 'proj01.settings'

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:

arduino
/home/myid/django_active

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:

python

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:

bash
cd ~
rm django_active # Remove the old symlink
ln -s ~/django_business/proj02 django_active # Point to new project

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_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?

 

(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

python

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

  1. Works with django_active symlink → No hardcoding project paths.

  2. Reads .env → You can explicitly set:

    ini
    DJANGO_SETTINGS_MODULE=proj02.settings

    …or leave it blank to let WSGI auto-detect.

  3. No edits when switching projects → Just change the symlink and reload.


Example .env in project root

ini
SECRET_KEY=my-super-secret-key
DEBUG=True
ALLOWED_HOSTS=localhost,127.0.0.1,myid.pythonanywhere.com
DJANGO_SETTINGS_MODULE=proj02.settings

Switching projects

bash
# Remove old symlink
rm ~/django_active
# Link to new project
ln -s ~/django_business/proj02 ~/django_active
# Reload your PythonAnywhere web app

 

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 inside proj01.

If later you want to switch to proj02, you just delete the link and make a new one:

bash
rm django_active
ln -s ~/django_business/proj02 ~/django_active

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:

bash
ln -s ~/django_business/proj01 ~/django_active
  • -s → make it a symbolic link (so it can point to a directory like your project folder).

  • ~/django_business/proj01target (the real folder).

  • ~/django_activelink 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:

bash
ln -s ~/django_business/proj01 ~/django_active

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:

bash
cd ~
ln -s ~/django_business/proj01 django_active

After that:

bash
ls -l

You should see something like:

ruby
django_active -> /home/yourname/django_business/proj01

 

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:

bash
rm -rf ~/django_active

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:

swift
/home/myid/django_business/venv

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:

bash
ln -s ~/django_business/proj01 ~/django_active

Web tab will be:

Source code:

arduino
/home/myid/django_active

Working directory:

arduino
/home/myid/django_active

Virtualenv:

swift
/home/myid/django_business/venv

Python version:

3.13

 

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

bash
cd ~
rm -rf django_active # Remove if it already exists (careful: -rf is irreversible)
ln -s ~/django_business/proj01 ~/django_active

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:

    arduino
    /home/myid/django_active
  • Working directory:

    arduino
    /home/myid/django_active
  • Virtualenv:

    swift
    /home/myid/django_business/venv
  • Python version:

    3.13

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:

bash
~/django_business/proj02

To switch:

bash
cd ~
rm django_active
ln -s ~/django_business/proj02 ~/django_active

Then:

bash
workon django_business/venv # or source ~/django_business/venv/bin/activate
pip install -r ~/django_active/requirements.txt

Finally:

bash
touch /var/www/myid_pythonanywhere_com_wsgi.py

(This tells PythonAnywhere “something changed” so it reloads.)

Then click Reload in the Web tab.


3️⃣ Rules for this setup

  1. Keep venv outside of any project folder (like you did in ~/django_business/venv).

  2. Put each Django project in its own folder (e.g., proj01, proj02, …).

  3. Always update your requirements.txt for each project, so the shared venv can 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:

bash
switch_project proj02

 

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:

swift
/home/myid/.virtualenvs/django52

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:

bash
rm -rf ~/django_active_venv
ln -s /home/myid/.virtualenvs/django52 ~/django_active_venv

Then set the Web tab’s Virtualenv to:

arduino
/home/myid/django_active_venv

Now switching projects means:

  • Point django_active to the project folder.

  • Point django_active_venv to 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.