Skip to main content

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.

The Internship Portal is built around two distinct user roles: students and companies. Every registered account belongs to one of these roles, and the role determines which views, actions, and data are available to that user. The role is set at registration time and stored on the user’s Profile record, which is auto-created alongside each new Django User.

Student Profile

A student account is designed for individuals who want to browse open internship listings and submit applications. After registering, a student can fill out their profile with academic and personal details that help companies evaluate their applications.Profile fields available to students:
FieldDescription
full_nameThe student’s full display name
universityName of the student’s university or college
degreeDegree programme or field of study
skillsFree-text list of relevant technical skills
bioShort personal statement or introduction
cvUploaded CV file (stored under cvs/)
profile_pictureAvatar image (stored under profile_pictures/)
What students can do:
  • Browse all active internship listings at GET /internships/
  • View full internship details at GET /internships/<id>/
  • Submit an application with one click from the detail page
  • Track submitted applications and their statuses at GET /applications/my/
  • Edit their profile (including uploading a CV and profile picture) at POST /users/edit-profile/
  • Receive in-app notifications when a company accepts or rejects their application

Registration

New users register through a single form that extends Django’s built-in UserCreationForm. The extra user_type field is what separates a student account from a company account — it is a required ChoiceField with the two allowed values. The username, password1, and password2 fields each carry a custom widget with Bootstrap classes; user_type uses a Select widget:
# users/forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User


class RegisterForm(UserCreationForm):
    username = forms.CharField(
        widget=forms.TextInput(
            attrs={"class": "form-control", "placeholder": "Username"}
        )
    )

    password1 = forms.CharField(
        widget=forms.PasswordInput(
            attrs={"class": "form-control", "placeholder": "Password"}
        )
    )

    password2 = forms.CharField(
        widget=forms.PasswordInput(
            attrs={"class": "form-control", "placeholder": "Confirm Password"}
        )
    )

    user_type = forms.ChoiceField(
        choices=[("student", "Student"), ("company", "Company")],
        widget=forms.Select(attrs={"class": "form-select"}),
    )

    class Meta:
        model = User
        fields = ["username", "password1", "password2", "user_type"]
When the form is submitted and validated, the view saves the new User, reads user_type from cleaned_data, sets it on the already-created Profile, and immediately logs the user in:
# users/views.py  —  register()
if form.is_valid():
    user = form.save()
    user_type = form.cleaned_data["user_type"]
    user.profile.user_type = user_type
    user.profile.save()
    login(request, user)
    return redirect("/users/profile/")
Registration endpoint:
POST /users/register/

Profile Auto-Creation

Every time a new User is saved to the database for the first time, Django fires a post_save signal. The Internship Portal connects a receiver to this signal that automatically creates a blank Profile record linked to the new user. This means there is no risk of a user existing without a profile, and no manual step is required.
# users/signals.py
from django.db.models.signals import post_save
from django.contrib.auth.models import User
from django.dispatch import receiver
from .models import Profile


@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)
The created guard ensures the receiver only runs on INSERT, not on every subsequent UPDATE to the User record.

Profile Model Fields

The Profile model uses a single flat table for both roles. Student-specific and company-specific fields live side by side; whichever set is irrelevant for a given user is simply left blank.
user
OneToOneField → User
required
The Django auth.User this profile belongs to. Deleted when the user is deleted (CASCADE). Accessible as user.profile.
user_type
string
required
Role of the account. Must be one of "student" or "company". Set during registration via RegisterForm.
full_name
string
(Student) The student’s full display name. Max 100 characters.
university
string
(Student) Name of the student’s university or college. Max 100 characters.
degree
string
(Student) Degree programme or field of study. Max 100 characters.
skills
text
(Student) Free-text description of the student’s technical and soft skills.
bio
text
(Student) Short personal statement or introduction shown on the public profile page.
company_name
string
(Company) Official name of the organisation. Max 100 characters.
industry
string
(Company) Business sector or industry (e.g. Software, Finance, Healthcare). Max 100 characters.
website
URL
(Company) Full URL of the company’s website.
location
string
(Company) Primary office location (city, country, or remote). Max 100 characters.
cv
file
(Student) Uploaded CV or résumé file. Stored under media/cvs/. Optional — blank=True, null=True.
profile_picture
image
Uploaded avatar or company logo. Stored under media/profile_pictures/. Optional for both roles. Can be removed by posting remove_picture=1 on the edit-profile form.
Student fields (full_name, university, degree, skills, bio, cv) and company fields (company_name, industry, website, location) all live on the same Profile model. The fields that do not apply to a given role are simply left blank — there is no separate table per role. Filter on user_type to determine which set of fields to display or validate.

URL Routes

All user-related routes are mounted under the /users/ prefix in the main URL configuration.
MethodPathViewDescription
GET / POST/users/register/registerCreate a new student or company account
GET / POST/users/login/user_loginAuthenticate an existing user
GET/users/logout/user_logoutLog out and redirect to login page
GET/users/profile/profileView the logged-in user’s own profile
GET / POST/users/edit-profile/edit_profileEdit profile fields and upload files
GET/users/profile/<user_id>/public_profileView a student’s public profile (student accounts only)
GET/users/dashboard/dashboardRole-aware dashboard for the logged-in user
# users/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path("register/", views.register, name="register"),
    path("login/", views.user_login, name="login"),
    path("logout/", views.user_logout, name="logout"),
    path("profile/", views.profile, name="profile"),
    path("edit-profile/", views.edit_profile, name="edit_profile"),
    path("profile/<int:user_id>/", views.public_profile, name="public_profile"),
    path("dashboard/", views.dashboard, name="dashboard"),
]

Build docs developers (and LLMs) love