Django Notes
Django Notes
.\venv\Scripts\activate
cd djchat/
.\venv\Scripts\activate
#settings.py
INSTALLED_APPS: {
"drf_spectacular",
...
}
SPECTACULAR_SETTINGS = {
"TITLE": "Your Project API",
"DESCRIPTION": "Your project description",
"VERSION": "1.0.0",
"SERVE_INCLUDE_SCHEMA": False, # whether we want to make the schema available
for a download
}
#drf spectacular will look at our views look for any endpoints and generate a
schema.
#it is going to generate some metadata which is going to be able to record or
describe the endpoints that we have in our system and we can then utilize this
schema and swagger ui to present the data utilizing the gui.
#urls.py
from django.contrib import admin
from django.urls import path
urlpatterns = [
path("admin/", admin.site.urls),
# Allow us to download the schema.
path("api/docs/schema/", SpectacularAPIView.as_view(), name="schema"),
# To access the swaggerUI
path("api/docs/schema/ui/", SpectacularSwaggerView.as_view()),
]
#You will now encounter error when starting up server and visiting root directory
'http://127.0.0.1:8000/'
#Page not found error
#Possible paths defined in urls.py will be listed
#Hence, to access a path without error, you will use specified endpoints i.e
'http://127.0.0.1:8000/api/docs/schema/ui/
Authentication:
#settings.py
REST_FRAMEWORK = {
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
# whenever we build an endpoint or view which has or needs authentication we
are just going to call upon djangos session authentication class, and thats
going to help us authenticate the user, should the user be logged-in and should
we need it to authenticate the user before they can access the endpoint. Hence, we
need to make sure the user is logged in and serve them the data related to
them.
"DEFAULT_AUTHENTICATION_CLASSES": [
'rest_framework.authentication.SessionAuthentication',
],
}
#server/views.py
from django.shortcuts import render
from rest_framework import viewsets
from rest_framework.response import Response
# ViewSets is a class that will provide CRUD based operations for a model.
# It acts as a bridge between the model and the serializer allowing us to create a
simple and powerful api with little amount of code.
# the second approach which we will use is to create an endpoint, but to allow it
to pass in multiple parameters, so we can return different resource based upon the
parameters that are passed in.
class ServerListViewSet(viewsets.ViewSet):
# If we dont sent any parameters i.e the category parameter we are going to
return all of the servers.
queryset = Server.objects.all()
#server/serializer.py:
from rest_framework import serializers
# What model we are using and fields we want serialized and sent to frontend
class Meta:
model = Server
fields = "__all__"
#djchat/urls.py
from django.contrib import admin
from django.urls import path
router = DefaultRouter()
router.register("api/server/select", ServerListViewSet)
urlpatterns = [
path("admin/", admin.site.urls),
# Allow us to download the schema.
path("api/docs/schema/", SpectacularAPIView.as_view(), name="schema"),
# To access the swaggerUI
path("api/docs/schema/ui/", SpectacularSwaggerView.as_view()),
] + router.urls
#server/views.py
class ServerListViewSet(viewsets.ViewSet):
# If we dont sent any parameters i.e the category parameter we are going to
return all of the servers.
queryset = Server.objects.all()
Refer to endpoint:
http://127.0.0.1:8000/api/server/select/?category=Cat1
Extending an endpoint.
Lets filter servers by quantity
Here we may use a parameter like the number 10 to specify how many servers to
return.
#server/views.py
class ServerListViewSet(viewsets.ViewSet):
# If we dont sent any parameters i.e the category parameter we are going to
return all of the servers.
queryset = Server.objects.all()
if qty:
self.queryset = self.queryset[: int(qty)]
Lets first make our Users table visible in our admin login.
#account/admin.py:
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
#server/views.py
class ServerListViewSet(viewsets.ViewSet):
# If we dont sent any parameters i.e the category parameter we are going to
return all of the servers.
queryset = Server.objects.all()
if by_user:
user_id = request.user.id
self.queryset = self.queryset.filter(member=user_id)
if qty:
self.queryset = self.queryset[: int(qty)]
Now lets create server ser4, and associate it with admin1 as its owner and member.
We will not see admin1's server (ser4) but all other servers (ser1, ser2, ser3)
as the current user logged in is admin, not admin 1, we can see this when we visit
the endpoint: http://127.0.0.1:8000/admin/
Emphasis on 'admin'.
class ChannelSerializer(serializers.ModelSerializer):
class Meta:
model = Channel
fields = "__all__"
class ServerSerializer(serializers.ModelSerializer):
channel_server = ChannelSerializer(many=True)
# What model we are using and fields we want serialized and sent to frontend
class Meta:
model = Server
fields = "__all__"
We have run a query, in whichwe have the field num_members containing the count of
members in a server: #views.py
'''
if with_num_members:
self.queryset = self.queryset.annotate(num_members=Count("member"))
'''
'''
num_members = serializers.SerializerMethodField()
'''
At the moment django doesnt know that this data we have acquired via the queryset
that is referenced by num_members is related to the new field we have create in
serializer.py above, also num_members.
So, what we need to do is just need to tell django that the data in the queryset
should corelate with num_members field in serializer.py that we want to serialize.
So that data in our queryset should be placed right here.
class ServerSerializer(serializers.ModelSerializer):
num_members = serializers.SerializerMethodField()
...
def get_num_members(Self, obj):
#this num_members refers to num_members data returned from views.py
queryset.
if hasattr(obj, "num_members"):
return obj.num_members
return None
Now when data is to be serialized and the code hits the line:
num_members = serializers.SerializerMethodField()
django will ask itself, what is num_members, it will fire off the get_num_members
function
and get num_members data from the queryset in views.py.
One more thing if we do not pass the '?with_num_members=true' parameter into the
url, we dont want to return that field. If we try we get data back something like:
{
{
'id':1,
'num_members: null,
...
}
}
#views.py:
serializer = ServerSerializer(self.queryset, many=True, context={"num_members":
with_num_members})
Turns out, we can then change an object post serialization as well. For that we
need a built in function: 'to_representation' in serializer.py
#settings.py
STATIC_URL = "static/"
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
MEDIA_URL = "media/"
#urls.py
from django.conf import settings
from django.conf.urls.static import static
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)