Important
Important
Business logic can be implemented in database layer, in middle tier or in user interface.
Implement the rules that should not be changed in the database tier, the most complex and
changes frequently in the middle tier, and simple rules and can be changed frequently in the user
interface.
In a client-server architecture is it true that the client always sent a request to a service? The
typical pattern is: Yes, the client usually initiates the communication by sending a request to the
server, and the server responds with the requested resource or service. Why?
Push notifications: Servers can send data to clients without an explicit request using server
push, WebSockets, or HTTP/2 server push.
Real-time systems: With WebSockets, SignalR, or gRPC streaming, the connection is
bidirectional, so the server can send messages without waiting for a new client request.
Publish/Subscribe models: Servers can push updates when new data is available (e.g.,
Firebase Realtime Database, MQTT).
APIs, by their nature, are accessible pro-grammatically, allowing threat actors to quickly scale
up automated probes and attacks.
Serializer class help you to define all the fields manually. Good when.You don’t have a model
(e.g., external API, computed data). You want full control over fields, validation, and data
transformation. Serializers let you control what fields are exposed. Example: You don’t want to
expose internal fields like password or is_admin. You can rename fields or nest related objects.
When receiving data from the client (e.g., POST request), we need to validate it before saving.
So serialization is needed because: Models can’t be directly turned into JSON. Validation &
security. Control over what data is exposed. Standardized format for communication.
Logging → is a fundamental part of applications. The goal of logging is to save time when
problems happen, and to do so you need to be able to track what is happening during runtime.
Logging is important both for development and for production sites.
Normally I don’t recommend running migrate on new projects until after a custom user model
has been configured. Otherwise Django will bind the database to the built-in User model which
is difficult to modify later on in the project.
In Django, a view is simply a Python function (or a class) that takes in a web request and returns
a web response. This response could be an HTML page, a redirect, a 404 error, or even a JSON
response in the context of an API. The `as_view()` method is a built-in Django method to
convert class based views to function-based views which are needed for URL routing.
`name=‘api-view’` is the name we give this URL pattern. It’s useful for reverse URL matching.
Which software engineering principles does api supports? APIs support several core Software
Engineering principles that promote clean architecture, maintainability, and scalability. Here are
the main principles supported by using APIs:
APIs are programming interfaces that connect applications to each other, a database, or a
messaging system. Sometimes, you might want a little bit of information—a movie rating, stock
price, or product availability—but what you need is available only in HTML pages, surrounded
by ads and extraneous content. You could extract what you’re looking for manually by doing the
following:
1. Type the URL into your browser.
2. Wait for the remote page to load.
3. Look through the displayed page for the information you want.
4. Write it down somewhere.
5. Possibly repeat the process for related URLs.
However, it’s much more satisfying to automate some or all of these steps. An automated web
fetcher is called a crawler or spider. After the contents have been retrieved from the remote web
servers, a scraper parses it to find the needle in the haystack.
I suppose the first question you need to ask are what permissions do you need and what sort. By
what sort, I mean do you want Model- or Object-level. To clarify the difference say you have a
model Car. If you want to give permissions on all cars, then Model-level is appropriate, but if
you want to give permissions on a per-car basis you want Object-level. You may need both, and
this isn't a problem as we'll see.
For Model permissions, Django handles these for you... mostly. For each model Django will
create permissions in the form 'appname.permissionname_modelname'. If you have an app called
'drivers' with the Car model then one permission would be 'drivers.delete_car'. The permissions
that Django automatically creates will be create, change, and delete. For some strange reason
they decided not to include read permissions from CRUD, you will have to do this yourself. Note
that Django decided to change CRUD's 'update' to 'change' for some reason. To add more
permissions to a model, say read permissions, you use the Meta class:
class Car( models.Model ):
# model stuff here
class Meta:
permissions = (
( "read_car", "Can read Car" ),
)
Note that permissions is a set of tuples, where the tuple items are the permission as described
above and a description of that permission. You don't have to follow the permname_modelname
convention but I usually stick with it.
Finally, to check permissions, you can use has_perm:
obj.has_perm( 'drivers.read_car' )
Where obj is either a User or Group instance. I think it is simpler to write a function for this:
def has_model_permissions( entity, model, perms, app ):
for p in perms:
if not entity.has_perm( "%s.%s_%s" % ( app, p, model.__name__ ) ):
return False
return True
Where entity is the object to check permissions on (Group or User), model is the instance of a model,
perms is a list of permissions as strings to check (e.g. ['read', 'change']), and app is the application name
as a string. To do the same check as has_perm above you'd call something like this:
result = has_model_permissions( myuser, mycar, ['read'], 'drivers' )
If you need to use object or row permissions (they mean the same thing), then Django can't really help
you by itself. The nice thing is that you can use both model and object permissions side-by-side. If you
want object permissions you'll have to either write your own (if using 1.2+) or find a project someone
else has written, one I like is django-objectpermissions from washingtontimes.
select_related('beacon')
Optimizes database queries by performing an SQL JOIN between Advertisement and Beacon
(since beacon is a ForeignKey). This ensures that when you access ad.beacon, no additional query is
needed.
Django Channels is a new piece in the Django ecosystem that allows us to solve a class of
problems that standard Django does not solve well: event-driven programming. Event-driven
programming is the best paradigm to use when a system has high input/output load, which goes
beyond normal HTTP request/response traffic. Chat systems fit in this, because people do not
talk by following a request/response pattern.
Information providers always have a website, but those are targeted for human eyes, not
automation. If data is published only on a website, anyone who wants to access and structure the
data needs to write scrapers and rewrite them each time a page format changes. This is usually
tedious. In contrast, if a website offers an API to its data, the data becomes directly available to
client programs. APIs change less often than web page layouts, so client rewrites are less
common. A fast, clean data pipeline also makes it easier to build unforeseen but useful
combinations. In many ways, the easiest API is a web interface, but one that provides data in a
structured format such as JSON or XML rather than plain text or HTML. The API might be
minimal or a full-fledged RESTful API but it provides another outlet for those restless bytes.
By Default Nested Serializers Are Read-Only unless you override the create() and update()
methods.
Basic Authentication
How It Works:
The client sends an HTTP request with an Authorization header containing the
username and password encoded in Base64.
Format: Authorization: Basic
<Base64Encoded(username:password)>
The server decodes the credentials and verifies them against its database.
If valid, the server processes the request; otherwise, it denies access.
Advantages:
Simple to implement.
No state is maintained on the server (stateless).
Disadvantages:
The username and password are sent with every request (even if encoded, not
encrypted).
Relies on HTTPS to secure communication.
No session management; the client must re-authenticate for every request.
Use Cases:
Session Authentication
How It Works:
Requires server-side storage, which doesn’t scale well for large applications.
The session can expire, requiring re-authentication.
Cookies must be securely managed to prevent theft (e.g., via cross-site scripting attacks).
Use Cases:
Sessions: A sequence of requests and responses from one browser to one (or more) sites
Session can be long (Gmail - two weeks) or short
without session mgmt: users would have to constantly re-authenticate
Session mgmt: Authorize user once; All subsequent requests are tied to user
Token Authentication
How It Works:
Mobile and single-page applications (SPAs) where the client handles state.
APIs requiring lightweight, stateless authentication.
Example:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE2ODk0N
jQ0MDB9.dXiLIYFgN4sGd72JUpZowH_2fp3KwTtSg3JPj6o8ZnY
Advantages:
Comparison Table
Session Token
Feature Basic Authentication JWT Authentication
Authentication Authentication
Low (server-side
Scalability High High Very High
storage)
Testing or simple
Use Case Traditional web apps Mobile apps, APIs Scalable APIs, SPAs
apps
OAuth 2.0 operates using authorization flows. The most common flows are:
1. The client redirects the user to the authorization server for login.
2. The user logs in and authorizes the application.
3. The authorization server sends an authorization code to the client.
4. The client exchanges the code for an access token.
5. The client uses the access token to make authorized API calls.
B. Implicit Flow
Use Case: Front-end applications where tokens are directly issued to the client.
Steps:
1. The client sends its client ID and client secret to the authorization server.
2. The server verifies the client and returns an access token.
3. The client uses the token for API access.
For example:
Stateless
State Stateless Stateful Stateless Stateless
(tokens)
Scope &
None None None Customizable Fine-grained
Granularity
Delegated
No No No No Yes
Access
Possible via
Revocation Not Applicable Easy Moderate Challenging
scopes
Third-party
Use Case Simple APIs Web apps Mobile apps SPAs, APIs
integrations
For an API to handle more requests, it needs to utilize more servers, which costs more money.
web-hooks, a technique where the client both makes requests and listens for them, allowing the
server to easily push updates to it. it's sometimes very easy to extend the client's functionality to
also listen for requests, enabling two-way communication. In its simplest form, web-hooks
requires the client to provide a Callback URL where it can receive events, and the server to have
a place for a person to enter that Callback URL. Then, whenever something changes on the
server, the server can send a request to the client's Callback URL to let the client know about the
update. Changes happening on the server are sent instantly to the client, so you have true real-
time communication. Also, web-hooks are efficient since there is only one request per update.
Token-based authentication is a security mechanism for APIs where a client provides a token
instead of credentials. The client must include this token in the header of every subsequent
request to the server. The server validates the token to authorize or deny the request.
JWT is used for user authentication and is passed between the user and the server. The
full definition of the acronym is JSON Web Token. The way they work is to encode the
user identity and sign it digitally, making it an unforgeable token that identifies the user,
and the application can later control access for the user based on their identity.
A JWT is a string composed of the header, payload, and signature. Those three parts are
separated by a .. Here is an example:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NjQ5ODI5OTcs
Im5iZiI6MTU2NDk4Mjk5NywianRpIjoiMGIzOTVlODQtNjFjMy00NjM3LTkwMzYtZjgyZDg
y
YTllNzc5IiwiZXhwIjoxNTY0OTgzODk3LCJpZGVudGl0eSI6MywiZnJlc2giOmZhbHNlLCJ
0eXBlIjoiYWNjZXNzIn0.t6F3cnAmbUXY_PwLnnBkKD3Z6aJNvIDQ6khMJWj9xZM
The header of the JWT contains the encryption type, "alg": "HS256", and the
encryption algorithm, "typ": "JWT". We can see this clearly if we base64 decode the
header string:
>>> import base64
>>> header = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9'
>>> base64.b64decode(header)
b'{"typ":"JWT","alg":"HS256"}'
The content of the payload part is arbitrary. It can be anything the developer likes. We
can put in it the user ID, nickname, and so on. When the application server receives this
token, it can base64 decode it and obtain the information inside. One important thing to
note is that this information is not encrypted, therefore it is not recommended to store
credit card details or passwords here:
>>> import base64
>>> payload = 'eyJpYXQiOjE1NjQ5ODI5OTcsIm5iZiI6MTU2NDk4Mjk5NywianRpI
joiMGIzOTVlODQtNjFjMy00NjM3LTkwMzYtZjgyZDgyYTllNzc5IiwiZXhwIjoxNTY0
OTgzODk3LCJpZGVudGl0eSI6MywiZnJlc2giOmZhbHNlLCJ0eXBlIjoiYWNjZXNzIn0'
>>> base64.b64decode(payload + '==')
b'{"iat":1564982997,"nbf":1564982997,"jti":"0b395e84-61c3-4637-9036-f82d82a9
e779","exp":1564983897,"identity":3,"fresh":false,"type":"access"}'
The secret part here is a signature created by the HS256 algorithm. The algorithm is
encrypting the encoded header and payload data with a secret key that is known by the
application server only. While anyone can modify the JWT content, that would result in
a different signature, thus the data integrity is protected.