From 6a87ed03b05fd36a9dcc79f5fbf423aaff8c5f35 Mon Sep 17 00:00:00 2001 From: Utkarsh Kumar Upadhyay Date: Sun, 5 Jan 2025 16:48:21 +0530 Subject: [PATCH] my task done --- PythonTask.pdf | Bin 0 -> 19882 bytes README.md | 55 +++ __pycache__/database.cpython-311.pyc | Bin 0 -> 681 bytes __pycache__/main.cpython-311.pyc | Bin 0 -> 8732 bytes __pycache__/models.cpython-311.pyc | Bin 0 -> 1783 bytes __pycache__/schemas.cpython-311.pyc | Bin 0 -> 2046 bytes database.py | 22 + dummy_users.json | 637 +++++++++++++++++++++++++++ main.py | 142 ++++++ models.py | 28 ++ requirements.txt | 8 + schemas.py | 27 ++ users.db | 0 13 files changed, 919 insertions(+) create mode 100644 PythonTask.pdf create mode 100644 README.md create mode 100644 __pycache__/database.cpython-311.pyc create mode 100644 __pycache__/main.cpython-311.pyc create mode 100644 __pycache__/models.cpython-311.pyc create mode 100644 __pycache__/schemas.cpython-311.pyc create mode 100644 database.py create mode 100644 dummy_users.json create mode 100644 main.py create mode 100644 models.py create mode 100644 requirements.txt create mode 100644 schemas.py create mode 100644 users.db diff --git a/PythonTask.pdf b/PythonTask.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7e6a76af9b450b9ab08d3d636f8be2faddf9554c GIT binary patch literal 19882 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 Cf7l)X literal 0 HcmV?d00001 diff --git a/README.md b/README.md new file mode 100644 index 0000000..7432a62 --- /dev/null +++ b/README.md @@ -0,0 +1,55 @@ +# Marriage Matchmaking App + +## Brief Description +The Marriage Matchmaking App is a simple backend application designed to help users find potential matches based on their profile information. The app allows users to create, read, update, and delete profiles with details such as name, age, gender, email, city, and interests. + +## What is Provided? +This project provides a basic skeleton for a FastAPI-based backend application. +#### Github repo: **https://github.com/abhishek-UM/UrbanMatch-PythonTask/tree/master** + +The provided code includes: + +### Basic Project Structure: + +- **main.py** : The main application file with basic CRUD operations for user profiles. +- **models.py**: SQLAlchemy models defining the User schema. +- **database.py**: Database configuration and setup. +- **schemas.py**: Pydantic schemas for data validation and serialization. + +### Functionality: + +- Create User Endpoint: Create a new user profile. +- Read Users Endpoint: Retrieve a list of user profiles. +- Read User by ID Endpoint: Retrieve a user profile by ID. +- SQLite Database: The application uses SQLite as the database to store user profiles. + +## What is Required? +### Tasks: +1. Add User Update Endpoint: + - Implement an endpoint to update user details by ID in the main.py file. +2. Add User Deletion Endpoint: + - Implement an endpoint to delete a user profile by ID. +3. Find Matches for a User: + - Implement an endpoint to find potential matches for a user based on their profile information. +4. Add Email Validation: + - Add validation to ensure the email field in user profiles contains valid email addresses. + +## Instructions: +Implement the required endpoints and email validation: + +1. Add the necessary code for the update, delete, match and validation endpoints +2. Test Your Implementation: + 1. Verify that users can be updated and deleted correctly. + 2. Check that matches are correctly retrieved for a given user. + 3. Ensure email validation is working as expected. + +## Submit Your Work: +Provide the updated code files (main.py, models.py, database.py, and schemas.py). +Include a brief report explaining your approach and any assumptions made. + + +### Prerequisites +- Python 3.7+ +- FastAPI +- SQLAlchemy +- SQLite diff --git a/__pycache__/database.cpython-311.pyc b/__pycache__/database.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a7934de6ae4e712732c29c68ef040336c713f3c6 GIT binary patch literal 681 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 K{54d3o-YBs@U%bx literal 0 HcmV?d00001 diff --git a/__pycache__/schemas.cpython-311.pyc b/__pycache__/schemas.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..95271ffd7ffee5d4d5d06f1730b2d84bd9849f57 GIT binary patch literal 2046 zcmZuxOK;mo5Z)!16!nVSx^3*VHq_Jsq5#RIJp@Hipp_HJa4i>b1O$Qrf)%&25Q$Qk zG+OmU0X^v8gHBBjJ*O!02l_K4AP0iCqKBe48S=@e&Ma-ydaRb8hWpJ7XJ=;jk8CzY zVEk?U(tM^6@(;dT4ee5x{RYA-ViTLTNr%>GN2w_k-<7u7VKvs#Y8oX9DG^)!mDr5a zH!2}-;fY2~mz)Ni&h-T@A-M!_#*&>Oxg>C@CA*}ZJ|cz8fB1=l5+=W~Tz=5Cc{?CPX#IDygDJ8hNdF>l`9arrHL}-LY)#U=i3z=hec&J)U9_mf**j$7f$6!O&XnFlG z*>XHCxa+wUv@=cAH_b3*nw_qF(ndLBnm?Xc?Mp^=JrU+i({h}yXW=GY&{4sUU=V@8 z8vaRU7}~|x#V_j^id#Qr<&?f>qcMk#l8^0ix_4oX}!CsKe_+`I5C2ED2n zXzjq9u$`3-?-l&L;m@zx>!aV3?{as?tN?Q&5rn7@FvPh&z`fy^eF1Q@58_)x-dYOW zTIw6PQ{Tc9jhbdNsDTzTY}im~*>j$+n;erHdxpBJwgPtQMH=lM6}!$4t>*Jefi2W0 zG`gaLHw9nFcBn@-A`hPLz~f@+;)Dn5w}%G)qCMXQvQp3&ybD=mS#wla_=MQPH3U3m zZV4dv4+S;Se#tKlN>fI)jVW1%Gh91gK}0d3=Sm?J8oj=4IbN$F@IcB-F4Vn#ujMqO zK9lV!??Mj@rkFnoN5tLG~ynbiLQ DH@>Cg literal 0 HcmV?d00001 diff --git a/database.py b/database.py new file mode 100644 index 0000000..4afcd21 --- /dev/null +++ b/database.py @@ -0,0 +1,22 @@ +# from sqlalchemy import create_engine +# from sqlalchemy.ext.declarative import declarative_base +# from sqlalchemy.orm import sessionmaker + +# // Free to use remote db or create a local database. Modify the URl appropriately +# SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db" + +# engine = create_engine(SQLALCHEMY_DATABASE_URL) +# SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) +# Base = declarative_base() + + +from sqlalchemy import create_engine +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import sessionmaker + +SQLALCHEMY_DATABASE_URL = "sqlite:///./users.db" + +engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}) +SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) + +Base = declarative_base() diff --git a/dummy_users.json b/dummy_users.json new file mode 100644 index 0000000..eeda130 --- /dev/null +++ b/dummy_users.json @@ -0,0 +1,637 @@ +[ + { + "id": 1, + "email": "user1@example.com", + "age": 34, + "city": "Chicago", + "latitude": -8.938253951768402, + "longitude": 169.5155598534227, + "interests": [ + "music" + ] + }, + { + "id": 2, + "email": "user2@example.com", + "age": 20, + "city": "Chicago", + "latitude": -21.998551862688558, + "longitude": -57.99493964085448, + "interests": [ + "photography", + "music", + "reading" + ] + }, + { + "id": 3, + "email": "user3@example.com", + "age": 50, + "city": "Houston", + "latitude": -72.91182416711094, + "longitude": 130.87756201032983, + "interests": [ + "gaming", + "cooking", + "reading", + "photography", + "music" + ] + }, + { + "id": 4, + "email": "user4@example.com", + "age": 31, + "city": "Los Angeles", + "latitude": -64.81866248948127, + "longitude": -69.8437067216783, + "interests": [ + "movies" + ] + }, + { + "id": 5, + "email": "user5@example.com", + "age": 34, + "city": "Chicago", + "latitude": 47.11224632987796, + "longitude": 53.64576637852841, + "interests": [ + "traveling", + "photography", + "art" + ] + }, + { + "id": 6, + "email": "user6@example.com", + "age": 19, + "city": "New York", + "latitude": 71.00263080734328, + "longitude": 118.22855370877085, + "interests": [ + "sports", + "photography" + ] + }, + { + "id": 7, + "email": "user7@example.com", + "age": 47, + "city": "Houston", + "latitude": -76.84824967467102, + "longitude": -157.74833617904366, + "interests": [ + "art", + "sports" + ] + }, + { + "id": 8, + "email": "user8@example.com", + "age": 46, + "city": "Chicago", + "latitude": 74.79032635225573, + "longitude": -12.367754819178998, + "interests": [ + "coding", + "movies", + "photography", + "music" + ] + }, + { + "id": 9, + "email": "user9@example.com", + "age": 19, + "city": "Phoenix", + "latitude": 65.39832171209432, + "longitude": -96.89038911962722, + "interests": [ + "coding", + "gaming" + ] + }, + { + "id": 10, + "email": "user10@example.com", + "age": 41, + "city": "Los Angeles", + "latitude": 48.01143908126923, + "longitude": 45.46924527509, + "interests": [ + "cooking" + ] + }, + { + "id": 11, + "email": "user11@example.com", + "age": 36, + "city": "Phoenix", + "latitude": -72.29179210239344, + "longitude": -55.12938586733806, + "interests": [ + "cooking", + "reading" + ] + }, + { + "id": 12, + "email": "user12@example.com", + "age": 36, + "city": "Chicago", + "latitude": -5.857935225891097, + "longitude": -63.06538668750126, + "interests": [ + "movies", + "reading", + "art", + "photography" + ] + }, + { + "id": 13, + "email": "user13@example.com", + "age": 46, + "city": "Chicago", + "latitude": -16.2848180455493, + "longitude": -73.61991132773603, + "interests": [ + "art", + "traveling" + ] + }, + { + "id": 14, + "email": "user14@example.com", + "age": 18, + "city": "Houston", + "latitude": 24.504345175073425, + "longitude": 1.0638629999226623, + "interests": [ + "photography", + "cooking", + "sports" + ] + }, + { + "id": 15, + "email": "user15@example.com", + "age": 34, + "city": "Los Angeles", + "latitude": 67.50052348980282, + "longitude": -140.1856881087762, + "interests": [ + "movies" + ] + }, + { + "id": 16, + "email": "user16@example.com", + "age": 30, + "city": "Houston", + "latitude": 70.62994357601644, + "longitude": -33.9311240618716, + "interests": [ + "photography", + "traveling", + "cooking", + "reading" + ] + }, + { + "id": 17, + "email": "user17@example.com", + "age": 45, + "city": "Chicago", + "latitude": -28.488929050276766, + "longitude": -26.854241020627484, + "interests": [ + "coding", + "sports", + "gaming" + ] + }, + { + "id": 18, + "email": "user18@example.com", + "age": 27, + "city": "Houston", + "latitude": 33.610727454087495, + "longitude": 18.81482427071171, + "interests": [ + "photography", + "traveling" + ] + }, + { + "id": 19, + "email": "user19@example.com", + "age": 34, + "city": "Houston", + "latitude": -68.41792696878676, + "longitude": 40.65697438859809, + "interests": [ + "traveling" + ] + }, + { + "id": 20, + "email": "user20@example.com", + "age": 24, + "city": "Houston", + "latitude": 18.735924643849884, + "longitude": -103.68767067134463, + "interests": [ + "gaming", + "art", + "traveling" + ] + }, + { + "id": 21, + "email": "user21@example.com", + "age": 21, + "city": "New York", + "latitude": -41.203570218479996, + "longitude": 147.82299790478186, + "interests": [ + "reading", + "cooking", + "traveling" + ] + }, + { + "id": 22, + "email": "user22@example.com", + "age": 50, + "city": "New York", + "latitude": 81.28738509312419, + "longitude": 173.750760428008, + "interests": [ + "reading", + "coding", + "cooking", + "photography" + ] + }, + { + "id": 23, + "email": "user23@example.com", + "age": 24, + "city": "New York", + "latitude": -21.681639398402737, + "longitude": 56.192148476201, + "interests": [ + "sports", + "movies", + "traveling", + "coding", + "music" + ] + }, + { + "id": 24, + "email": "user24@example.com", + "age": 35, + "city": "Los Angeles", + "latitude": 2.735950187793577, + "longitude": -165.37114481396603, + "interests": [ + "coding", + "traveling", + "sports" + ] + }, + { + "id": 25, + "email": "user25@example.com", + "age": 34, + "city": "New York", + "latitude": -24.57585654248996, + "longitude": 16.57145203726222, + "interests": [ + "movies", + "coding", + "gaming" + ] + }, + { + "id": 26, + "email": "user26@example.com", + "age": 39, + "city": "Chicago", + "latitude": 3.1588207678372413, + "longitude": -93.71184895715994, + "interests": [ + "coding", + "music", + "traveling", + "reading", + "photography" + ] + }, + { + "id": 27, + "email": "user27@example.com", + "age": 32, + "city": "Los Angeles", + "latitude": -10.727021688065918, + "longitude": 24.807702016113836, + "interests": [ + "sports", + "music", + "traveling", + "reading", + "coding" + ] + }, + { + "id": 28, + "email": "user28@example.com", + "age": 48, + "city": "Chicago", + "latitude": 72.61372848683067, + "longitude": 38.35638205033467, + "interests": [ + "music", + "traveling" + ] + }, + { + "id": 29, + "email": "user29@example.com", + "age": 28, + "city": "Los Angeles", + "latitude": -49.976585682724945, + "longitude": -88.40157443159492, + "interests": [ + "movies", + "coding", + "reading", + "cooking" + ] + }, + { + "id": 30, + "email": "user30@example.com", + "age": 40, + "city": "Los Angeles", + "latitude": -71.28412711212815, + "longitude": 163.47292302215027, + "interests": [ + "gaming", + "reading" + ] + }, + { + "id": 31, + "email": "user31@example.com", + "age": 34, + "city": "Los Angeles", + "latitude": -0.9880343238885558, + "longitude": 103.61972423067118, + "interests": [ + "reading" + ] + }, + { + "id": 32, + "email": "user32@example.com", + "age": 50, + "city": "Chicago", + "latitude": -75.42966852890183, + "longitude": -14.801119103178848, + "interests": [ + "cooking" + ] + }, + { + "id": 33, + "email": "user33@example.com", + "age": 50, + "city": "Phoenix", + "latitude": 32.09617515020345, + "longitude": 177.10053618641308, + "interests": [ + "traveling" + ] + }, + { + "id": 34, + "email": "user34@example.com", + "age": 28, + "city": "New York", + "latitude": -25.537632208165405, + "longitude": 80.45241453218159, + "interests": [ + "sports" + ] + }, + { + "id": 35, + "email": "user35@example.com", + "age": 45, + "city": "Phoenix", + "latitude": -0.047071864959406184, + "longitude": 167.06844555209193, + "interests": [ + "cooking", + "reading", + "coding", + "sports", + "traveling" + ] + }, + { + "id": 36, + "email": "user36@example.com", + "age": 47, + "city": "Chicago", + "latitude": 18.449664781187863, + "longitude": 5.5861265661746415, + "interests": [ + "coding", + "music", + "art", + "photography" + ] + }, + { + "id": 37, + "email": "user37@example.com", + "age": 39, + "city": "Los Angeles", + "latitude": 15.921991203541609, + "longitude": -83.12877041512355, + "interests": [ + "gaming", + "cooking", + "traveling" + ] + }, + { + "id": 38, + "email": "user38@example.com", + "age": 35, + "city": "New York", + "latitude": 36.245254116387954, + "longitude": 24.520665472967295, + "interests": [ + "cooking", + "music" + ] + }, + { + "id": 39, + "email": "user39@example.com", + "age": 34, + "city": "Los Angeles", + "latitude": -78.17869787924394, + "longitude": 102.41173913720729, + "interests": [ + "reading" + ] + }, + { + "id": 40, + "email": "user40@example.com", + "age": 50, + "city": "Phoenix", + "latitude": -13.540781260896964, + "longitude": -4.671048286858138, + "interests": [ + "coding", + "sports", + "gaming", + "cooking" + ] + }, + { + "id": 41, + "email": "user41@example.com", + "age": 45, + "city": "Phoenix", + "latitude": -69.12590493129613, + "longitude": 102.79447636229185, + "interests": [ + "sports", + "music", + "movies" + ] + }, + { + "id": 42, + "email": "user42@example.com", + "age": 46, + "city": "Houston", + "latitude": 71.05772077010076, + "longitude": -164.03390084513708, + "interests": [ + "sports", + "gaming", + "music", + "coding" + ] + }, + { + "id": 43, + "email": "user43@example.com", + "age": 35, + "city": "Chicago", + "latitude": -59.08937284302297, + "longitude": 175.06195515021784, + "interests": [ + "traveling", + "gaming", + "art" + ] + }, + { + "id": 44, + "email": "user44@example.com", + "age": 34, + "city": "Houston", + "latitude": -89.69092619960747, + "longitude": -6.94362855851557, + "interests": [ + "traveling" + ] + }, + { + "id": 45, + "email": "user45@example.com", + "age": 25, + "city": "Houston", + "latitude": 49.994739257502204, + "longitude": 7.028394349063717, + "interests": [ + "music", + "art" + ] + }, + { + "id": 46, + "email": "user46@example.com", + "age": 29, + "city": "Houston", + "latitude": 62.58045595011788, + "longitude": 168.20847125748338, + "interests": [ + "art", + "movies", + "cooking", + "sports", + "coding" + ] + }, + { + "id": 47, + "email": "user47@example.com", + "age": 23, + "city": "New York", + "latitude": -13.081112244113683, + "longitude": 95.87675588664632, + "interests": [ + "coding", + "art", + "reading", + "sports" + ] + }, + { + "id": 48, + "email": "user48@example.com", + "age": 48, + "city": "Chicago", + "latitude": 60.357374145005, + "longitude": -151.36049016800908, + "interests": [ + "photography", + "coding", + "art" + ] + }, + { + "id": 49, + "email": "user49@example.com", + "age": 44, + "city": "Houston", + "latitude": -77.37251169028163, + "longitude": 69.80932679910583, + "interests": [ + "coding" + ] + }, + { + "id": 50, + "email": "user50@example.com", + "age": 19, + "city": "Chicago", + "latitude": 67.13767055910952, + "longitude": -2.7342001127698836, + "interests": [ + "gaming" + ] + } +] \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..3c1e785 --- /dev/null +++ b/main.py @@ -0,0 +1,142 @@ +from fastapi import FastAPI, HTTPException, Depends +from sqlalchemy.orm import Session +from database import SessionLocal, engine +import models, schemas +from models import Base +from typing import List +import re +from geopy.distance import geodesic +from typing import List + +app = FastAPI() + +Base.metadata.create_all(bind=engine) + +# Dependency +def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close() + +# Endpoint to create a new user + +@app.post("/users/", response_model=schemas.User) +def create_user(user: schemas.UserCreate, db: Session = Depends(get_db)): + # Regular expression for validating an email address + email_regex = r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)" + + if not re.match(email_regex, user.email): + raise HTTPException(status_code=400, detail="Invalid email address") + + db_user = models.User(**user.dict()) + db.add(db_user) + db.commit() + db.refresh(db_user) + return db_user + +# Endpoint to get all users (with pagination support) + +@app.get("/users/", response_model=List[schemas.User]) +def read_users(skip: int = 0, limit: int = 10, db: Session = Depends(get_db)): + # Query the database for users with pagination + users = db.query(models.User).offset(skip).limit(limit).all() + return users + + + +# Endpoint to get a specific user by their ID + + +@app.get("/users/{user_id}", response_model=schemas.User) +def read_user(user_id: int, db: Session = Depends(get_db)): + user = db.query(models.User).filter(models.User.id == user_id).first() + if user is None: + raise HTTPException(status_code=404, detail="User not found") + return user + +# Endpoint to update user details (partial update) + +@app.put("/users/{user_id}", response_model=schemas.User) +def update_user(user_id: int, updated_user: schemas.UserUpdate, db: Session = Depends(get_db)): + user = db.query(models.User).filter(models.User.id == user_id).first() + if not user: + raise HTTPException(status_code=404, detail="User not found") + for key, value in updated_user.dict(exclude_unset=True).items(): + setattr(user, key, value) + db.commit() + db.refresh(user) + return user + +# Endpoint to delete a user by ID + +@app.delete("/users/{user_id}") +def delete_user(user_id: int, db: Session = Depends(get_db)): + user = db.query(models.User).filter(models.User.id == user_id).first() + if not user: + raise HTTPException(status_code=404, detail="User not found") + db.delete(user) + db.commit() + return {"detail": "User deleted successfully"} + + +# Endpoint to find matches for a user based on shared interests and city + +@app.get("/users/{user_id}/matches", response_model=List[schemas.UserWithScore]) +def find_matches(user_id: int, db: Session = Depends(get_db)): + user = db.query(models.User).filter(models.User.id == user_id).first() + if not user: + raise HTTPException(status_code=404, detail="User not found") + + # Filter potential matches by age difference ±3 + potential_matches = db.query(models.User).filter( + models.User.id != user_id, + abs(models.User.age - user.age) <= 3 # Only matches with age difference within ±3 + ).all() + + def calculate_match_score(other_user: models.User) -> float: + # intrest similarity + shared_interests = len(set(user.interests) & set(other_user.interests)) + total_interests = len(set(user.interests) | set(other_user.interests)) + interest_similarity = shared_interests / total_interests if total_interests > 0 else 0 + + # city score + user_coords = (user.latitude, user.longitude) + other_coords = (other_user.latitude, other_user.longitude) + city_proximity_score = max(1 - geodesic(user_coords, other_coords).km / 100, 0) # close city score higher + + #age difference calculation + age_score = 1 + + score = ( + 50 * interest_similarity + # Interest similarity (max 50) + 30 * city_proximity_score + # City proximity (max 30) + 20 * age_score # Age similarity (max 20) + ) + return score + + # score calculation + matches_with_scores = [ + {"user": match, "score": calculate_match_score(match)} + for match in potential_matches + ] + matches_with_scores.sort(key=lambda x: x["score"], reverse=True) + + #response + result = [ + schemas.UserWithScore( + id=match["user"].id, + email=match["user"].email, + city=match["user"].city, + interests=match["user"].interests, + latitude=match["user"].latitude, + longitude=match["user"].longitude, + score=match["score"] + ) + for match in matches_with_scores + ] + + return result + + diff --git a/models.py b/models.py new file mode 100644 index 0000000..7edc970 --- /dev/null +++ b/models.py @@ -0,0 +1,28 @@ +from sqlalchemy import Column, Integer, String, ARRAY, ForeignKey +from sqlalchemy.orm import relationship +from database import Base + +class User(Base): + __tablename__ = "users" + + id = Column(Integer, primary_key=True, index=True) + name = Column(String, index=True) + age = Column(Integer) + gender = Column(String) + email = Column(String, unique=True, index=True) + city = Column(String, index=True) + interests = Column(ARRAY(String)) + + # Establishing relationship to Post (one-to-many) + posts = relationship("Post", back_populates="owner") + +class Post(Base): + __tablename__ = "posts" + + id = Column(Integer, primary_key=True, index=True) + title = Column(String, index=True) + content = Column(String) + user_id = Column(Integer, ForeignKey("users.id")) + + # Establishing relationship back to User + owner = relationship("User", back_populates="posts") diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..873219e --- /dev/null +++ b/requirements.txt @@ -0,0 +1,8 @@ +fastapi +sqlalchemy +uvicorn +databases +geopy +pydantic +pydantic[email] + diff --git a/schemas.py b/schemas.py new file mode 100644 index 0000000..3d8e335 --- /dev/null +++ b/schemas.py @@ -0,0 +1,27 @@ +from pydantic import BaseModel, EmailStr +from typing import List, Optional + +class UserBase(BaseModel): + name: str + age: int + gender: str + email: EmailStr + city: str + interests: List[str] + +class UserCreate(UserBase): + pass + +class UserUpdate(BaseModel): + name: Optional[str] = None + age: Optional[int] = None + gender: Optional[str] = None + email: Optional[EmailStr] = None + city: Optional[str] = None + interests: Optional[List[str]] = None + +class User(UserBase): + id: int + + class Config: + orm_mode = True diff --git a/users.db b/users.db new file mode 100644 index 0000000..e69de29