15 : Post Request for Job Creation

Now, we have a record in the user table so we have the owner_id field for creating a new job. Let's create a new job using a post request. It would be very similar to the previous post, Wanna give it a try? Feel free to try it on your own.

We need 3 new files:

│ ├─base.py
│ └─version1/
│   ├─route_general_pages.py
│   ├─route_jobs.py              #new
│   └─route_users.py
│ ├─base.py
│ ├─base_class.py
│ ├─models/
│ │ ├─jobs.py
│ │ └─users.py
│ ├─repository/
│ │ ├─jobs.py        #new
│ │ └─users.py
│ └─session.py
│ ├─jobs.py
│ └─users.py
│ ├─conftest.py
│ └─test_routes/
│   ├─test_jobs.py   #new
│   └─test_users.py

Type the following code in route_jobs.py:

from fastapi import APIRouter
from sqlalchemy.orm import Session
from fastapi import Depends,HTTPException,status

from db.session import get_db
from db.models.jobs import Job
from schemas.jobs import JobCreate,ShowJob
from db.repository.jobs import create_new_job

router = APIRouter()

def create_job(job: JobCreate,db: Session = Depends(get_db)):
    current_user = 1
    job = create_new_job(job=job,db=db,owner_id=current_user)
    return job

We are doing the same thing, we are creating a route that will receive data for job creation by POST method. It will validate the data received used a schema named JobCreate. So, let's create the schemas required. Type the following in schemas > jobs.py.

from typing import Optional
from pydantic import BaseModel
from datetime import date,datetime

#shared properties
class JobBase(BaseModel):
    title : Optional[str] = None
    company : Optional[str] = None
    company_url : Optional[str] = None
    location : Optional[str] = "Remote"
    description : Optional[str] = None
    date_posted : Optional[date] = datetime.now().date()

#this will be used to validate data while creating a Job
class JobCreate(JobBase):
    title : str
    company : str 
    location : str
    description : str 
#this will be used to format the response to not to have id,owner_id etc
class ShowJob(JobBase):
    title : str 
    company: str 
    company_url : Optional[str]
    location : str 
    date_posted : date
    description : Optional[str]

    class Config():  #to convert non dict obj to json
        orm_mode = True

Since we are using repository pattern and we want to keep the database orm logic completely separated from that of fastapi routes we need to create a make a new function named 'create_new_job' for creation logic. Lets create this file db > repository > jobs.py

from sqlalchemy.orm import Session

from schemas.jobs import JobCreate
from db.models.jobs import Job

def create_new_job(job: JobCreate,db: Session,owner_id:int):
    job_object = Job(**job.dict(),owner_id=owner_id)
    return job_object

This is yet another example of sqlalchemy orm. We are creating a new record in the database using orm. Still, our fastapi app does not know about this new feature. So, we need to import create_user route in apis > base.py

from apis.version1 import route_general_pages
from apis.version1 import route_users
from apis.version1 import route_jobs

api_router = APIRouter()

Time to test our functionality, By the end of this course I would try to follow real TDD. I would make the test fail and then write sufficient code to make it pass and then the test should pass. For now, we are just documenting our work.
Type this code in tests > test_routes > test_jobs.py

import json

def test_create_job(client):
    data = {
        "title": "SDE super",
        "company": "doogle",
        "company_url": "www.doogle.com",
        "location": "USA,NY",
        "description": "python",
        "date_posted": "2022-03-20"
    response = client.post("/jobs/create-job/",json.dumps(data))
    assert response.status_code == 200 
    assert response.json()["company"] == "doogle"
    assert response.json()["description"] == "python"

and now we will run our test by typing pytest in the terminal.

All Done, over and out !
Final git commit : create job using post request · nofoobar/JobBoard-Fastapi@c2e1eb9 (github.com)

Prev: 14 : Unit … Next: 16 : Get …