How I'm Implementing Dynamic Job Application Forms in My Placement Portal
After my stakeholder meeting, I had a much clearer understanding of what the Placement Officer needs from my Placement Portal.
One of the most important requirements was the ability to create dynamic application forms for individual job postings.
Different companies can ask students for different information.
One company might require CGPA and backlogs.
Another might ask for a portfolio URL or a certification.
I don't want to create a new database field or modify application logic every time a company needs a new question.
So, after deciding how I want the dynamic form system to work, I started implementing it step by step.
This is Part 1 of that implementation.
Step 1: Creating the Attribute Table
The first step was to create an Attribute table.
The purpose of this table is to define what an attribute actually is.
At the moment, the important pieces of information are:
- Attribute name
- Data type
The attribute name represents what information is being collected.
The data type tells the application how that information should be treated.
For example, an attribute could represent something like:
- CGPA
- Passing Year
- Portfolio URL
- Certification
- Preferred Location
The data type becomes particularly important because dynamic forms aren't just about displaying fields.
The system also needs to understand what kind of value each field is supposed to contain.
Step 2: Connecting Attributes to Job Applications
After creating the Attribute table, the next step was connecting it with the models responsible for jobs and applications.
This is where I introduced two important concepts:
Job Attribute
and
Application Attribute Value
The Job Attribute represents an attribute selected for a particular job posting.
It also contains additional configuration such as whether the field is required.
For example, a Placement Officer might configure:
CGPA → Required
while another field could be:
Portfolio URL → Optional
This allows the same attribute definition to be reused across different job postings while still allowing each job to configure how that field behaves.
Why Application Attribute Value Snapshots the Attribute
There is an important database design decision here.
For Job Attribute, the Attribute is connected using a foreign key.
But for Application Attribute Value, I decided to snapshot the attribute instead of keeping a foreign key relationship to the current Attribute definition.
Why?
Because an application represents what the student submitted at a particular point in time.
Imagine a student applies for a job today.
The application contains:
CGPA → 8.2
Later, the global definition of that attribute changes.
I don't want an old application to suddenly depend on whatever the current Attribute definition happens to look like.
The application should preserve the information that existed when the student applied.
This is the same principle behind preserving historical application data rather than relying entirely on the current state of related records.
The application becomes a record of what actually happened.
Step 3: Connecting Everything Through Django Admin
Once the models were structured, the next step was connecting them inside Django Admin.
I connected:
Job Attribute → Job
as an inline.
And similarly:
Application Attribute Value → Application
as an inline.
This gives me a practical way to test the complete backend workflow before building the frontend.
The relationship now becomes conceptually:
Attribute → Job Attribute → Job
and:
Application → Application Attribute Value
This lets me create job-specific fields and inspect how those values are stored when working with applications.
Step 4: Testing the Workflow Before Building the Frontend
My Django Admin panel is now ready for testing.
This is an important part of my development process.
Before spending time building the frontend experience, I want to verify that the backend data model actually supports the workflow I have designed.
Through Django Admin, I can test things such as:
- Creating attributes.
- Assigning attributes to jobs.
- Marking fields as required.
- Creating applications.
- Storing application attribute values.
- Inspecting how the relationships behave.
If the underlying model design doesn't work correctly, building a polished frontend on top of it won't solve the problem.
It will only make the problem more expensive to fix.
So for this phase, Django Admin acts as my testing interface.
Step 5: Building the Placement Officer Experience
Once the backend workflow is working correctly, the next step is the frontend.
This is where the technical implementation needs to disappear behind a simple user experience.
The Placement Officer shouldn't have to think about:
- Attribute tables.
- Foreign keys.
- Application snapshots.
- Database relationships.
- Django models.
They should simply be able to:
- Create a job posting.
- Select the information required from students.
- Mark fields as required when necessary.
- Save the job.
- Publish it.
The complexity should remain inside the system.
The interface should feel effortless.
Backend Complexity, Simple User Experience
This is one of the things I am beginning to appreciate while building this Placement Portal.
A feature can have a relatively complicated backend design while providing a very simple experience to the user.
For the dynamic form system, I currently have to think about:
- Attribute definitions.
- Data types.
- Job-specific attributes.
- Required fields.
- Application values.
- Snapshotting historical information.
- Database relationships.
But the Placement Officer shouldn't need to understand any of that.
They should just see a form builder that makes sense.
That's the real goal of this implementation.
What Comes Next?
This is only Part 1 of the dynamic form implementation.
The backend structure and Django Admin workflow are the first pieces.
The next major step is building the frontend experience for the Placement Officer.
That's where I'll turn the underlying database and API design into an interface that allows a Placement Officer to create a job and configure its application form without needing to understand how the system works internally.
And that is where I expect the next set of design problems to appear.
Final Thoughts
The stakeholder meeting gave me the requirements.
Now I'm translating those requirements into actual system design.
My current implementation path is:
Attribute → Job Attribute → Job → Application → Application Attribute Value
Then:
Django Admin → Backend validation → Frontend experience
I'm deliberately building this in stages.
First, make the data model work.
Then, test the workflow.
Then, build the experience around it.
Because a good dynamic form isn't just about making fields configurable.
It's about building a system flexible enough for different requirements while keeping the experience simple for the person creating the job.