Categorized question bank with detailed answers — covering backend, frontend, UI/UX, and ML tracks.
AI · Network · API · Data Structures · Database · Python · FastAPI · Testing · OOP · Docker · Behavioral
pip install openai), store API key in env vars, create a service layer to wrap calls. Use openai.chat.completions.create() with model, messages, and temperature.httpx to avoid blocking, structured outputs via function calling or JSON mode, and logging every request/response with a correlation ID.tiktoken to count tokens programmatically before building features.@app.post("/summarize")
async def summarize(text: str):
response = await openai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "Summarize concisely."},
{"role": "user", "content": text}
],
max_tokens=300
)
return {"summary": response.choices[0].message.content}
Add in production: input length validation, rate limiting per user, cost tracking, error handling for RateLimitError and APIConnectionError.EXPLAIN ANALYZE), use APM (Sentry, Datadog).joinedload; missing indexes → add them; slow external calls → cache or make async; sync code blocking event loop → switch to async httpx.AsyncClient; high traffic → add Redis caching + rate limiting.min_length, ge=0, regex). FastAPI validates automatically, returning 422 on failure. Custom validators via @field_validator. Business logic validation in the service layer, not the router.GROUP BY + HAVING COUNT(*) > 1. For data beyond memory: hash partitioning.EXPLAIN ANALYZE to verify index usage.id, created_at, updated_at. JSONB for flexible metadata. Alembic for migrations.asyncio for I/O-bound, multiprocessing for CPU-bound.SELECT FOR UPDATE SKIP LOCKED for queues.COUNT, SUM, AVG, MAX, MIN with GROUP BY. Use HAVING to filter after aggregation.-- Schema users(id, username, email, created_at) posts(id, user_id FK, content, like_count, created_at) comments(id, post_id FK, user_id FK, parent_comment_id FK, content, created_at) likes(user_id FK, post_id FK, created_at) -- composite PK -- Query SELECT category, AVG(confidence_score) AS avg_score FROM predictions GROUP BY category HAVING COUNT(*) >= 50 ORDER BY avg_score DESC LIMIT 1;Key:
HAVING filters after aggregation (vs WHERE before). Self-referencing parent_comment_id enables nested replies.[]): mutable, can add/remove items.()): immutable, hashable, ~10-15% faster. Use for fixed data, dict keys, multi-return values.yield values lazily — only the current item in memory. Critical for large files, streaming, infinite sequences.def large_range(n):
i = 0
while i < n:
yield i; i += 1
Use (x*2 for x in range(1_000_000)) instead of a list when you don't need all values at once.# WRONG
def append_to(item, lst=[]):
lst.append(item); return lst
# CORRECT: use None as default, create inside
Decorator: a function that wraps another to add behavior without modifying it.from functools import wraps
def timer(func):
@wraps(func)
def wrapper(*args, **kwargs):
import time; start = time.time()
result = func(*args, **kwargs)
print(f"{func.__name__}: {time.time()-start:.3f}s")
return result
return wrapper
FastAPI uses decorators for all route registration.Depends() is literally the D in SOLID..pyc). Then the CPython interpreter executes that bytecode line by line — you don't compile manually, this is automatic.if True # SyntaxError: missing colonRuntime error: code is syntactically valid but fails during execution.
name = None print(name.upper()) # AttributeError at runtime x = 1 / 0 # ZeroDivisionError at runtimeKey fact: Python is dynamically typed — type errors only surface at runtime, not before execution like in Java or TypeScript.
app/ ├── main.py # include routers ├── core/config.py # BaseSettings ├── routers/ # APIRouter per domain ├── schemas/ # Pydantic models ├── models/ # SQLAlchemy models ├── services/ # Business logic ├── db/session.py # Engine + SessionLocal └── tests/
Depends() declares reusable dependencies injected into routes — DB sessions, auth, rate limiting.async def get_db():
db = SessionLocal()
try: yield db
finally: db.close()
async def get_current_user(
token: str = Depends(oauth2_scheme),
db: Session = Depends(get_db)
):
return verify_token(token, db)
@app.get("/me")
async def read_me(user = Depends(get_current_user)):
return user
Benefits: testable (swap real DB for test DB), composable, automatic cleanup with yield.async def routes run on the event loop — never block with sync calls inside them (use run_in_executor).@app.post("/notify")
async def notify(bg: BackgroundTasks, email: str):
bg.add_task(send_email, email)
return {"status": "queued"}
For heavy jobs (ML inference): Celery + Redis broker.from fastapi.testclient import TestClient
from app.main import app
client = TestClient(app)
def test_create_property_requires_auth():
r = client.post("/v1/properties/", json={...})
assert r.status_code == 401
def test_create_property_success(auth_headers):
r = client.post("/v1/properties/",
json={"title": "Test", "price": 1000},
headers=auth_headers)
assert r.status_code == 201
assert r.json()["title"] == "Test"
Strategy: unit tests for services, integration tests with a test DB (transactions that roll back), API tests with TestClient. Mock external calls with respx.python:3.11-slim base, copy requirements.txt first (layer caching), then app code. uvicorn as ASGI server. Secrets via env vars / Azure Key Vault, never baked in. Health check at /health. Non-root user, .dockerignore, pinned deps.requirements.txt before app code, the dependency installation layer is cached — only changed app code rebuilds.requirements.txt before source, same base image tag, push layer cache to registry (--cache-from in Docker Buildx).breakpoint(), DB query logging, EXPLAIN ANALYZE.JavaScript · TypeScript · React/Vue · State Management · Performance · Testing · Version Control · Behavioral
.then/.catch) → async/await (modern sugar over Promises). The event loop processes async results from the callback queue when the call stack is empty.function makeCounter() {
let count = 0;
return () => ++count;
}
const counter = makeCounter();
counter(); // 1, counter(); // 2
Hoisting: declarations move to the top of scope at compile time. var initializes as undefined. function declarations are fully hoisted. let/const are hoisted but not initialized (temporal dead zone — accessing before declaration throws ReferenceError).document.querySelector('.list').addEventListener('click', e => {
if (e.target.matches('.item')) { /* handle */ }
});
localStorage: persists until cleared, ~5-10MB, all tabs.interface/type for API response shapes, generics for reusable components/services, enums for constants, strict mode to catch nullability bugs, and typed Axios service layers.// Interface (preferred for API shapes)
interface User { id: number; name: string; }
interface Admin extends User { role: 'admin'; }
// Generic utility
type ApiResponse<T> = { data: T; error: string | null; meta: { page: number } };
const res: ApiResponse<User[]> = await fetchUsers();<script setup> + typed Pinia made each module self-contained.dir="rtl"/"ltr" on <html> based on active locale. CSS logical properties (margin-inline-start instead of margin-left) for layout that flips automatically. i18n with vue-i18n — all strings in ar.json/en.json. RTL-aware Tailwind classes where needed. Tested by switching locale in dev and checking all 43 modules for layout breaks.useState: local component state.useEffect: side effects (data fetching, subscriptions, DOM manipulation). Cleanup function prevents memory leaks.useCallback: memoize functions to prevent child re-renders.useMemo: memoize expensive computations.useRef: persist values without re-rendering, access DOM nodes.useContext: consume context without prop drilling.useCallback/useMemo have overhead too. Profile first.useEffect(fetch) boilerplate and makes stale-while-revalidate trivial.useState, you probably want React Query.defineAsyncComponent(() => import('./Heavy.vue')). In React: React.lazy() + Suspense.main is always deployable → create feature/my-feature → commit with conventional commits (feat:, fix:, chore:) → open PR → review + fix → squash merge → delete branch. At Mahjoz: 43 modules meant branch naming convention was critical to avoid confusion.HTML · CSS · JavaScript Basics · jQuery · Responsive Design · Accessibility · Behavioral
<div> = block-level (full width, new line). <span> = inline (content-width, stays in flow).<header>, <nav>, <main>, <article>, <section>, <aside>, <footer>, <figure>, <time>. Benefits: accessibility (screen readers), SEO, readability. Anti-pattern: <div class="header"> when you mean <header>.box-sizing: border-box includes padding + border in width/height (what you usually want).display: flex, flex-direction, justify-content (main axis), align-items (cross axis), gap. Children: flex: 1 (grow), align-self. For 2D use CSS Grid./* Flexbox */
.parent { display: flex; justify-content: center; align-items: center; }
/* Grid */
.parent { display: grid; place-items: center; }
/* Absolute */
.child { position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); }
block: full width, new line, all box model properties work.undefined, can re-declare. Avoid.0 == "0" → true. === strict, no coercion: 0 === "0" → false. Always use ===.$('#id') // select by id
$('.cls').toggleClass('active');
$('#btn').on('click', fn);
$.ajax({ url: '/api', method: 'GET', success: cb });
$(document).on('click', '.dynamic-item', fn); // delegation
$(document).ready() = DOM parsed, images may not be loaded. window.onload = everything loaded including images.min-width media queries), fluid layouts (%, fr), clamp() for fluid typography, responsive images (srcset, picture), touch targets min 44×44px, real device testing.aria-live for dynamic content, alt text on images, <label> for every input, form errors via aria-describedby.Usability & Accessibility · Tools & Techniques · Behavioural · Advanced · Senior Role
Pipelines & Data Leakage · Pandas · NLP
pipeline.predict() on raw data.df.loc[2, 'name'] = row with label 2.df.iloc[2, 0] = always 3rd row, 1st column.from collections import Counter
from nltk.corpus import stopwords
import nltk; nltk.download('stopwords')
stop_words = set(stopwords.words('english'))
all_words = ' '.join(df['text']).lower().split()
filtered = [w for w in all_words if w.isalpha() and w not in stop_words]
top_3 = Counter(filtered).most_common(3)
For scale (1M+ rows): use CountVectorizer from sklearn or process in chunks. Add lemmatization for cleaner results.Settings · Views & Endpoints · ORM · Django REST Framework
# settings.py ALLOWED_HOSTS = ['localhost', '127.0.0.1', 'mysite.com'] # All hosts — never use in production ALLOWED_HOSTS = ['*']When
DEBUG = False, ALLOWED_HOSTS must be set. When DEBUG = True, Django ignores it (localhost always works).# settings.py DEBUG = True # development DEBUG = False # productionDEBUG = True: Django shows a detailed error page with full stack trace, local variables, and request info. Static files are served by Django automatically.
ALLOWED_HOSTS must be set. Django does NOT serve static files — you need WhiteNoise, nginx, or a CDN.False in production. Never commit True to a live server.@api_view decorator:@api_view(['GET', 'POST'])
def book_list(request):
if request.method == 'GET':
books = Book.objects.all()
return Response(BookSerializer(books, many=True).data)2. Class-Based View (CBV) — extend APIView:class BookList(APIView):
def get(self, request):
books = Book.objects.all()
return Response(BookSerializer(books, many=True).data)3. ModelViewSet + Router — auto-generates all CRUD URLs:class BookViewSet(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
router = DefaultRouter()
router.register('books', BookViewSet)
urlpatterns += router.urls@api_view. You handle each HTTP method with if/else. Simple to read, easy to debug, good for custom logic.get, post, put, delete). Less if/else, more organized for standard CRUD. DRF generic views (ListCreateAPIView, RetrieveUpdateDestroyAPIView) let you write almost no code:class BookDetail(RetrieveUpdateDestroyAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializerRule: FBV for custom logic. CBV for standard CRUD — less repetition.?. Visible in the URL, can be bookmarked, used for filtering or pagination on GET requests.GET /books/?genre=fiction&page=2
request.query_params.get('genre') # access in DRFRequest body (form data / JSON): sent inside the HTTP request body, not visible in the URL. Used when creating or updating a resource (POST, PUT, PATCH).POST /books/
Body: {"title": "1984", "author_id": 5}
request.data.get('title') # access in DRFWhen to prefer the body: any time you're sending data to create or update something, or when the data is sensitive (password, payment info), large, or complex (nested objects). Never put sensitive data in query params — they end up in server logs and browser history.class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=200)
# One-to-many: many books → one author
author = models.ForeignKey(
Author,
on_delete=models.CASCADE,
related_name='books'
)
# Many-to-many: a book can have many genres
genres = models.ManyToManyField('Genre', blank=True)
class Genre(models.Model):
name = models.CharField(max_length=50)Access:book.author # the author object author.books.all() # all books by this author book.genres.all() # all genres of this book book.genres.add(genre_obj) # add a genre
# .get() — returns one object or raises an exception book = Book.objects.get(id=1) # Raises DoesNotExist if not found # Raises MultipleObjectsReturned if more than one match # .filter() — returns a QuerySet (empty, one, or many) books = Book.objects.filter(genre='fiction') # QuerySet book = Book.objects.filter(id=1).first() # safe single fetchRule: use
.get() only when you're certain exactly one record exists (e.g., by primary key or unique field). Use .filter() for anything else — it never raises an exception for zero or many results.(object, created) where created is a boolean.author, created = Author.objects.get_or_create(
name='George Orwell', # lookup field
defaults={'bio': 'British novelist'} # only used when creating
)
if created:
print("New author added")
else:
print("Author already existed")defaults are only applied on creation, not used in the lookup. This is a single atomic database query — safer than doing .get() then .create() separately, which could fail under concurrent requests.# settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
}
# urls.py
urlpatterns = [
path('api/token/', TokenObtainPairView.as_view()),
path('api/token/refresh/', TokenRefreshView.as_view()),
]POST credentials to /api/token/ → get access + refresh tokens. Send Authorization: Bearer <token> on protected routes. Install: pip install djangorestframework-simplejwt.ModelViewSet combines all CRUD actions into one class. Register it with a Router and it auto-creates all URLs.# views.py
class BookViewSet(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
# urls.py
router = DefaultRouter()
router.register('books', BookViewSet)
urlpatterns += router.urlsAuto-generated routes:GET /books/ — list allPOST /books/ — createGET /books/{id}/ — retrieve onePUT /books/{id}/ — full updatePATCH /books/{id}/ — partial updateDELETE /books/{id}/ — deletehttp_method_names = ['get', 'post'] or use ReadOnlyModelViewSet.ModelSerializer auto-generates fields from a model.create() and update() yourself:class BookSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
title = serializers.CharField(max_length=200)
def create(self, validated_data):
return Book.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.title = validated_data.get('title', instance.title)
instance.save()
return instanceModelSerializer — auto-generates fields and create()/update() from the model:class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ['id', 'title', 'author']
# or: fields = '__all__'Use ModelSerializer for standard model CRUD. Use plain Serializer for non-model data (like a login form) or complex custom logic.# models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
avatar = models.ImageField(upload_to='avatars/')
# serializers.py
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
fields = ['avatar']
# views.py
class ProfileView(APIView):
parser_classes = [MultiPartParser, FormParser]
def post(self, request):
serializer = ProfileSerializer(data=request.data)
if serializer.is_valid():
serializer.save(user=request.user)
return Response(serializer.data, status=201)
return Response(serializer.errors, status=400)Also needed in settings.py:MEDIA_URL = '/media/' MEDIA_ROOT = BASE_DIR / 'media'And in
urls.py for development:urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)Install
Pillow — Django's ImageField requires it: pip install Pillow.multipart/form-data, not JSON.Architecture · Design Principles
# Producer — Django view
@api_view(['POST'])
def register(request):
user = User.objects.create(**request.data)
send_welcome_email.delay(user.id) # emit event
return Response({'id': user.id}, status=201)
# Consumer — Celery task
@shared_task
def send_welcome_email(user_id):
user = User.objects.get(id=user_id)
# send the emailWhy use it: the register endpoint doesn't wait for the email to send (faster response). The email worker is decoupled — you can replace or scale it without touching the view.myproject/ ├── users/ ← handles auth, profiles ├── orders/ ← handles orders ├── payments/ ← handles payments └── notifications/ ← handles emails, pushEach Django app has its own
models.py, views.py, urls.py, and serializers.py. Apps communicate through imports or events — they don't reach into each other's internals.