The internship listing system is the core of the portal. Companies create and manage listings, students browse and apply to them, and unauthenticated visitors can still view active openings. Every listing carries a status —Documentation Index
Fetch the complete documentation index at: https://mintlify.com/unesexact/internship-portal-django/llms.txt
Use this file to discover all available pages before exploring further.
active or closed — that controls visibility for non-company viewers. The service layer cleanly separates query logic from view logic, making each behaviour easy to understand and test independently.
Internship Model
Each internship is stored as a singleInternship record. The company field is a foreign key to Django’s built-in User model, meaning the owning company is always a registered user with user_type = "company".
Auto-incrementing primary key assigned by the database on creation.
Job title or name of the internship position. Max 200 characters.
The company user who owns this listing. Deleting the user cascades and removes all their listings. Accessible in reverse as
user.internships.all().Physical location or “Remote”. Max 100 characters.
Full description of the role, responsibilities, and requirements. Rendered as-is in the detail template.
Visibility status. One of
"active" or "closed". Defaults to "active" on creation. Toggle between the two values via the toggle endpoint.Timestamp set automatically when the record is first saved (
auto_now_add=True). Read-only after creation.URL Routes
All internship routes are mounted under the/internships/ prefix in the main URL configuration.
| Method | Path | View | Description |
|---|---|---|---|
GET | /internships/ | internship_list | Role-aware listing page |
GET | /internships/<id>/ | internship_detail | Full detail for one listing |
GET / POST | /internships/create/ | create_internship | Create a new listing (company only) |
GET / POST | /internships/<id>/edit/ | edit_internship | Edit an existing listing (owner only) |
POST | /internships/<id>/delete/ | delete_internship | Permanently delete a listing (owner only) |
POST | /internships/<id>/toggle/ | toggle_status | Flip status between active and closed (owner only) |
Role-Aware Listing
Theinternship_list view at GET /internships/ returns a different queryset depending on who is viewing the page. The decision logic lives in the view and delegates the actual database query to the service layer:
- Students → all active listings across every company
- Companies → all of their own listings (active and closed)
- Guests / unauthenticated → all active listings (same as students)
Service Layer
Theinternships/services.py module provides the following functions. Note that while create_internship exists in the service layer, the create_internship view calls Internship.objects.create() directly rather than delegating to this function. All other mutating views (edit_internship, delete_internship, toggle_status) do use the service layer.
Status Toggle
A company can flip a listing betweenactive and closed at any time without editing the listing’s content. The toggle is handled by toggle_internship_status() in the service layer, which reads the current status and sets the opposite value before saving:
Access Control
The portal enforces two layers of access control on mutating routes:- Authentication —
create,edit,delete, andtoggleviews are all decorated with@login_required. Unauthenticated requests are redirected to the login page. - Ownership —
edit,delete, andtoggleviews verify thatinternship.company == request.user. If the logged-in user does not own the listing, they are silently redirected to the home page.
create_internship checks user_type before rendering the form:
/internships/create/ are redirected away without seeing the form.