Skip to content

Commit c9d7f64

Browse files
committed
oops forgot to stage changes
1 parent b896be4 commit c9d7f64

5 files changed

Lines changed: 109 additions & 4 deletions

File tree

.devcontainer/devcontainer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"features": {
66
"ghcr.io/devcontainers/features/docker-in-docker:2": {},
77
"ghcr.io/devcontainers/features/python:1": {
8-
"version": "3.11"
8+
"version": "3.11.4"
99
},
1010
"ghcr.io/devcontainers/features/node:1": {},
1111
"ghcr.io/devcontainers/features/common-utils:2": {

backend/courses/admin.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,18 @@ class NGSSRestrictionAdmin(admin.ModelAdmin):
7373

7474
class CourseAdmin(admin.ModelAdmin):
7575
search_fields = ("full_code", "department__code", "code", "semester", "title")
76-
autocomplete_fields = ("department", "primary_listing", "parent_course")
77-
readonly_fields = ("topic", "crosslistings", "course_attributes")
76+
autocomplete_fields = (
77+
"department",
78+
"primary_listing",
79+
"parent_course",
80+
"prerequisite_courses",
81+
)
82+
readonly_fields = (
83+
"topic",
84+
"crosslistings",
85+
"course_attributes",
86+
"dependent_courses_links",
87+
)
7888
exclude = ("attributes",)
7989
list_filter = ("semester",)
8090
list_display = ("full_code", "semester", "title")
@@ -121,6 +131,21 @@ def course_attributes(self, instance):
121131
),
122132
)
123133

134+
def dependent_courses_links(self, instance):
135+
return format_html_join(
136+
"\n",
137+
'<li><a href="{}">{}</li>',
138+
(
139+
(
140+
reverse("admin:courses_course_change", args=[c.id]),
141+
str(c),
142+
)
143+
for c in instance.dependent_courses.all()
144+
),
145+
)
146+
147+
dependent_courses_links.short_description = "Dependent courses"
148+
124149

125150
class TopicAdmin(admin.ModelAdmin):
126151
readonly_fields = (
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Prerequisite Scraping Commands
2+
3+
Run all commands from `backend/`.
4+
5+
## Common command
6+
7+
```bash
8+
uv run manage.py scrape_prereqs --all-course-codes --semesters 2026C --max-requests 100 --sleep-seconds 0.1 --jitter-seconds 0.1
9+
```
10+
11+
What it does:
12+
- `--all-course-codes`: loads one course/CRN pair per course code from the DB.
13+
- `--semesters 2026C`: limits the DB query to semester `2026C`.
14+
- `--max-requests 100`: caps total requests after deduplication.
15+
- `--sleep-seconds 0.1`: fixed delay between requests.
16+
- `--jitter-seconds 0.1`: adds random delay in `[0, 0.1]` seconds per request.
17+
18+
## Other useful forms
19+
20+
```bash
21+
uv run manage.py scrape_prereqs --pair "CIS 1210:14309"
22+
uv run manage.py scrape_prereqs --input-file courses/data/prereq_scrapes/targets.sample.json
23+
uv run manage.py scrape_prereqs --all-course-codes --semesters all
24+
```
25+
26+
## Output location
27+
28+
By default, output JSON files are written in this directory:
29+
30+
- `courses/data/prereq_scrapes/`
31+
32+
## Populate structured prereqs into DB
33+
34+
After scraping, use the `populate_prereqs` command to parse the JSON files and write structured prereq links into the DB.
35+
36+
```bash
37+
# Dry-run first (no DB writes)
38+
uv run manage.py populate_prereqs --semesters 2026C --dry-run
39+
40+
# Apply writes
41+
uv run manage.py populate_prereqs --semesters 2026C
42+
```
43+
Use `--scrape-file <path>` to target a specific scrape JSON.
44+
Use `--clear-existing` only if you want to replace existing prereq links for matched courses.
45+
46+
## Notes
47+
48+
- If a semester value fails (for example typo or unavailable code), run with a known semester code, or use `--semesters all`.
49+
- To see all command options:
50+
51+
```bash
52+
uv run manage.py scrape_prereqs --help
53+
```

backend/courses/management/commands/populate_prereqs.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
COURSE_TOKEN_RE = re.compile(r"([A-Za-z]{2,4})\s*-?\s*(\d{3,4}[A-Za-z]?)|(\d{3,4}[A-Za-z]?)")
1515
HTML_TAG_RE = re.compile(r"<[^>]+>")
1616

17-
1817
def parse_prereq_pairs(prereq_text: str) -> set[tuple[str, str]]:
1918
if not prereq_text:
2019
return set()
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Generated by Django 5.0.2 on 2026-03-27 21:32
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("degree", "0004_merge_20260213_1825"),
10+
]
11+
12+
operations = [
13+
migrations.AlterField(
14+
model_name="degree",
15+
name="program",
16+
field=models.CharField(
17+
choices=[
18+
("EU_BSE", "Engineering BSE"),
19+
("EU_BAS", "Engineering BAS"),
20+
("AU_BA", "College BA"),
21+
("WU_BS", "Wharton BS"),
22+
("NU_BSN", "Nursing BSN"),
23+
],
24+
help_text="\nThe program code for this degree, e.g., EU_BSE\n",
25+
max_length=16,
26+
),
27+
),
28+
]

0 commit comments

Comments
 (0)