Skip to content
This repository was archived by the owner on Oct 2, 2025. It is now read-only.

Commit d12e729

Browse files
Create setting_up_backend_debugger.md
1 parent a0f16c4 commit d12e729

1 file changed

Lines changed: 346 additions & 0 deletions

File tree

Lines changed: 346 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,346 @@
1+
#🐞 Setting Up Backend Debugger in VS Code for Specify 7
2+
This guide walks you through configuring VS Code to enable Django backend debugging in the Specify 7 codebase.
3+
4+
**Prerequisites**
5+
- VS Code installed
6+
- Docker and Docker Compose installed
7+
- Python extension installed in VS Code
8+
- Your development environment is cloned and running properly
9+
10+
🧰 ### 1. **VS Code Debug Configuration**
11+
- Open VS Code.
12+
- Click on the Run and Debug icon in the sidebar.
13+
- Click "Create a launch.json file".
14+
- Select Python.
15+
- Choose Django.
16+
- Choose manage.py.
17+
- Replace the content of .vscode/launch.json with:
18+
19+
```json
20+
{
21+
"version": "0.2.0",
22+
"configurations": [
23+
{
24+
"name": "Run Django",
25+
"type": "python",
26+
"request": "attach",
27+
"pathMappings": [
28+
{
29+
"localRoot": "${workspaceFolder}/specifyweb",
30+
"remoteRoot": "/opt/specify7/specifyweb"
31+
}
32+
],
33+
"port": 3000,
34+
"host": "127.0.0.1"
35+
}
36+
]
37+
}
38+
```
39+
40+
41+
🛠 ### 2. **Required Code & Config Changes**
42+
📁 Add .vscode/settings.json:
43+
```json
44+
[
45+
{
46+
"python.testing.unittestArgs": [
47+
"-v",
48+
"-s",
49+
"./specifyweb",
50+
"-p",
51+
"*test*.py"
52+
],
53+
"python.testing.pytestEnabled": false,
54+
"python.testing.unittestEnabled": true,
55+
"python.linting.mypyEnabled": true,
56+
"python.linting.enabled": true,
57+
"typescript.tsdk": "./specifyweb/frontend/js_src/node_modules/typescript/lib"
58+
},
59+
{
60+
"typescript.tsdk": "./specifyweb/frontend/js_src/node_modules/typescript/lib",
61+
"eslint.experimental.useFlatConfig": true,
62+
"eslint.workingDirectories": [
63+
{ "pattern": "./specifyweb/frontend/js_src/" }
64+
]
65+
}
66+
]
67+
```
68+
69+
⚙️ **Modify manage.py:**
70+
Insert this before execute_from_command_line(sys.argv):
71+
```python
72+
if settings.DEBUG:
73+
if os.environ.get('RUN_MAIN') or os.environ.get('WERKZEUG_RUN_MAIN'):
74+
import debugpy
75+
debugpy.listen(("0.0.0.0", 3000))
76+
print('Attached!')
77+
```
78+
79+
🐳 **In docker-compose.yml, under specify7 service:**
80+
Add the line under commands:
81+
```yaml
82+
specify7:
83+
...
84+
ports:
85+
- "3000:3000"
86+
```
87+
88+
🐳 **Update Dockerfile**
89+
Use the new Dockerfile provided in this documentation.
90+
91+
📦 **Add debugpy to requirements-testing.txt:**
92+
```txt
93+
debugpy==1.6.5
94+
django-stubs==1.12.0
95+
mypy==0.971
96+
hypothesis==6.4.0
97+
hypothesis-jsonschema==0.19.0
98+
types-requests==2.28.5
99+
pytest==7.2.1
100+
pytest-django==4.5.2
101+
```
102+
103+
🧪 **First-Time Setup Steps**
104+
Stop any running Docker containers:
105+
```bash
106+
docker compose down
107+
```
108+
109+
Rebuild the image (for first-time or after Dockerfile changes):
110+
```bash
111+
docker compose build
112+
```
113+
114+
Start your development server:


115+
```bash
116+
docker compose up
117+
```
118+
119+
🐞 ### 3. **Running the Debugger**
120+
- Put breakpoints in your Django code.
121+
- In VS Code, open the Run and Debug panel.
122+
- Select "Run Django" and press the ▶️ Play icon.
123+
- Open the app in your browser as usual (e.g. http://localhost:8000) and trigger code paths to hit breakpoints.
124+
125+
🔁 **When Changing Code**
126+
To reload the debugger:
127+
- Click the disconnect icon (next to Play) in the Debug bar.
128+
- Click Play again to reconnect.
129+
130+
🪟 **Windows-Specific Notes**
131+
If you're running on WSL / Ubuntu, modify the Dockerfile:
132+
Replace:
133+
```yaml
134+
FROM arm64v8/…
135+
```
136+
137+
With:
138+
Dockerfile
139+
140+
```yaml
141+
FROM ubuntu:24.04
142+
FROM node:18-alpine
143+
```
144+
New dockerfile:
145+
```bash
146+
# FROM ubuntu:18.04 AS common
147+
FROM arm64v8/ubuntu:18.04 AS common
148+
149+
LABEL maintainer="Specify Collections Consortium <github.com/specify>"
150+
151+
RUN apt-get update \
152+
&& apt-get -y install --no-install-recommends \
153+
gettext \
154+
python3.8 \
155+
libldap-2.4-2 \
156+
libmariadbclient18 \
157+
sudo \
158+
&& apt-get clean \
159+
&& rm -rf /var/lib/apt/lists/*
160+
161+
RUN groupadd -g 999 specify \
162+
&& useradd -r -u 999 -g specify specify
163+
164+
RUN mkdir -p /home/specify \
165+
&& chown specify.specify /home/specify
166+
RUN mkdir -p /opt/specify7 \
167+
&& chown specify.specify /opt/specify7
168+
169+
170+
#####################################################################
171+
172+
173+
# FROM node:18-alpine AS build-frontend
174+
FROM arm64v8/node:18-alpine AS build-frontend
175+
176+
LABEL maintainer="Specify Collections Consortium <github.com/specify>"
177+
178+
USER node
179+
WORKDIR /home/node
180+
181+
COPY --chown=node:node specifyweb/frontend/js_src/package*.json ./
182+
RUN npm ci
183+
RUN mkdir dist && chown node:node dist
184+
COPY --chown=node:node specifyweb/frontend/js_src .
185+
RUN npx webpack --mode production
186+
187+
188+
#####################################################################
189+
190+
FROM common AS build-backend
191+
192+
RUN apt-get update \
193+
&& apt-get -y install --no-install-recommends \
194+
build-essential \
195+
ca-certificates \
196+
curl \
197+
git \
198+
sudo \
199+
libldap2-dev \
200+
libmariadbclient-dev \
201+
libsasl2-dev \
202+
python3.8-venv \
203+
python3.8-distutils \
204+
python3.8-dev
205+
206+
USER specify
207+
COPY --chown=specify:specify requirements.txt /home/specify/
208+
209+
WORKDIR /opt/specify7
210+
# RUN python3.8 -m venv ve \
211+
# && ve/bin/pip install --no-cache-dir -r /home/specify/requirements.txt
212+
RUN python3.8 -m venv ve
213+
# RUN ve/bin/pip install --no-cache-dir backports.zoneinfo[tzdata]>=0.2.1
214+
RUN ve/bin/pip install --no-cache-dir -r /home/specify/requirements.txt
215+
RUN ve/bin/pip install --no-cache-dir gunicorn
216+
217+
COPY --from=build-frontend /home/node/dist specifyweb/frontend/static/js
218+
COPY --chown=specify:specify specifyweb /opt/specify7/specifyweb
219+
COPY --chown=specify:specify manage.py /opt/specify7/
220+
COPY --chown=specify:specify docker-entrypoint.sh /opt/specify7/
221+
COPY --chown=specify:specify Makefile /opt/specify7/
222+
COPY --chown=specify:specify specifyweb.wsgi /opt/specify7/
223+
224+
ARG BUILD_VERSION
225+
ARG GIT_SHA
226+
ENV BUILD_VERSION=$BUILD_VERSION
227+
RUN make specifyweb/settings/build_version.py
228+
RUN echo $BUILD_VERSION > specifyweb/frontend/static/build_version.txt
229+
RUN echo $GIT_SHA > specifyweb/frontend/static/git_sha.txt
230+
RUN date > specifyweb/frontend/static/build_date.txt
231+
232+
# The following is needed to run manage.py compilemessages:
233+
# The secret key file needs to exist so it can be imported.
234+
# The INSTALLED_APPS needs to be cleared out so Django doesn't
235+
# try to import the Specify datamodel which isn't defined yet.
236+
RUN echo "SECRET_KEY = 'bogus'" > specifyweb/settings/secret_key.py
237+
RUN echo "INSTALLED_APPS = ['specifyweb.frontend']" >> specifyweb/settings/__init__.py
238+
# RUN (cd specifyweb && ../ve/bin/python ../manage.py compilemessages)
239+
RUN ve/bin/python manage.py compilemessages
240+
241+
# Now put things back the way they were.
242+
RUN rm specifyweb/settings/secret_key.py
243+
COPY --chown=specify:specify specifyweb/settings/__init__.py /opt/specify7/specifyweb/settings/__init__.py
244+
245+
######################################################################
246+
247+
FROM common AS run-common
248+
249+
RUN apt-get update \
250+
&& apt-get -y install --no-install-recommends \
251+
rsync \
252+
&& apt-get clean \
253+
&& rm -rf /var/lib/apt/lists/*
254+
255+
RUN mkdir -p /volumes/static-files/depository \
256+
&& chown -R specify.specify /volumes/static-files
257+
258+
USER specify
259+
COPY --from=build-backend /opt/specify7 /opt/specify7
260+
261+
WORKDIR /opt/specify7
262+
RUN cp -r specifyweb/settings .
263+
264+
RUN echo \
265+
"import os" \
266+
"\nDATABASE_NAME = os.environ['DATABASE_NAME']" \
267+
"\nDATABASE_HOST = os.environ['DATABASE_HOST']" \
268+
"\nDATABASE_PORT = os.environ.get('DATABASE_PORT', '')" \
269+
"\nMASTER_NAME = os.environ['MASTER_NAME']" \
270+
"\nMASTER_PASSWORD = os.environ['MASTER_PASSWORD']" \
271+
"\nDEPOSITORY_DIR = '/volumes/static-files/depository'" \
272+
"\nREPORT_RUNNER_HOST = os.getenv('REPORT_RUNNER_HOST', '')" \
273+
"\nREPORT_RUNNER_PORT = os.getenv('REPORT_RUNNER_PORT', '')" \
274+
"\nWEB_ATTACHMENT_URL = os.getenv('ASSET_SERVER_URL', None)" \
275+
"\nWEB_ATTACHMENT_KEY = os.getenv('ASSET_SERVER_KEY', None)" \
276+
"\nWEB_ATTACHMENT_COLLECTION = os.getenv('ASSET_SERVER_COLLECTION', None)" \
277+
"\nSEPARATE_WEB_ATTACHMENT_FOLDERS = os.getenv('SEPARATE_WEB_ATTACHMENT_FOLDERS', None)" \
278+
"\nCELERY_BROKER_URL = os.getenv('CELERY_BROKER_URL', None)" \
279+
"\nCELERY_RESULT_BACKEND = os.getenv('CELERY_RESULT_BACKEND', None)" \
280+
"\nCELERY_TASK_DEFAULT_QUEUE = os.getenv('CELERY_TASK_QUEUE', DATABASE_NAME)" \
281+
"\nANONYMOUS_USER = os.getenv('ANONYMOUS_USER', None)" \
282+
> settings/local_specify_settings.py
283+
284+
RUN echo "import os \nDEBUG = os.getenv('SP7_DEBUG', '').lower() == 'true'\n" \
285+
> settings/debug.py
286+
287+
RUN echo "import os \nSECRET_KEY = os.environ['SECRET_KEY']\n" \
288+
> settings/secret_key.py
289+
290+
ENV LC_ALL=C.UTF-8
291+
ENV LANG=C.UTF-8
292+
ENV DJANGO_SETTINGS_MODULE='settings'
293+
294+
ENTRYPOINT ["/opt/specify7/docker-entrypoint.sh"]
295+
296+
EXPOSE 8000
297+
298+
299+
######################################################################
300+
301+
FROM run-common AS run-development
302+
303+
USER root
304+
305+
RUN apt-get update \
306+
&& apt-get -y install --no-install-recommends \
307+
python3.8-distutils \
308+
ca-certificates \
309+
make
310+
311+
USER specify
312+
313+
COPY requirements-testing.txt /home/specify/
314+
315+
COPY --chown=specify:specify requirements-testing.txt /home/specify/
316+
COPY --chown=specify:specify requirements.txt /home/specify/
317+
318+
COPY --chown=specify:specify .vscode/launch.json /opt/specify/
319+
COPY --chown=specify:specify .vscode/settings.json /opt/specify/
320+
321+
RUN ve/bin/pip install --no-cache-dir -r /home/specify/requirements-testing.txt
322+
RUN ve/bin/pip install --no-cache-dir -r /home/specify/requirements.txt
323+
324+
# RUN python3.8 -m venv ve \
325+
# && ve/bin/pip install --no-cache-dir -r /home/specify/requirements-testing.txt \
326+
# && ve/bin/pip install --no-cache-dir -r /home/specify/requirements.txt
327+
328+
# RUN mkdir /opt/specify7/.vscode
329+
# RUN echo "[pytest]\nDJANGO_SETTINGS_MODULE=specifyweb.settings\npython_files=*test*.py testparsing.py\naddopts = --ignore=specifyweb/specify/selenium_tests.py" > /opt/specify7/specifyweb/pytest.ini
330+
# RUN echo "{\n\t\"python.pythonPath\": \"ve/bin/python/\",\n\t\"python.testing.pytestArgs\": [\n\t\t\"specifyweb\",\n\t\t\"-s\",\n\t\t\"-vv\"\n\t],\n\t\"python.testing.pytestEnabled\": true,\n\t\"python.testing.nosetestsEnabled\": false,\n\t\"python.testing.unittestEnabled\": false\n}" > /opt/specify7/.vscode/settings.json
331+
332+
# COPY mypy.ini ./
333+
334+
335+
######################################################################
336+
337+
FROM run-common AS run
338+
339+
RUN mv specifyweb.wsgi specifyweb_wsgi.py
340+
341+
CMD ["ve/bin/gunicorn", "-w", "3", "-b", "0.0.0.0:8000", "-t", "300", "specifyweb_wsgi"]
342+
343+
344+
```
345+
346+

0 commit comments

Comments
 (0)