detail
Let's get into the nitty-gritty details of setting up your Django REST Framework (DRF) backend and integrating it with your SvelteKit frontend. We'll go step-by-step, focusing on clear instructions.
Assumptions:
You have a Django project named
myapiset up with appsauthandcontent.You have a SvelteKit project ready to go.
You have Python, Node.js, and npm (or yarn/pnpm) installed.
You have a GitHub OAuth application configured with a Client ID and Secret.
You have PostgreSQL installed and set up (or know how to use Docker for it).
Let's Start with the Backend (Django/DRF):
1. PostgreSQL Database Configuration (if not using Docker):
Ensure PostgreSQL is running.
Create a database (e.g.,
my_app_db).Create a user and grant them permissions on the database.
In your
myapi/settings.pyfile, update theDATABASESsection with your credentials:DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'my_app_db', 'USER': 'your_db_user', 'PASSWORD': 'your_db_password', 'HOST': 'localhost', 'PORT': '5432', } }
2. Django App: auth (Authentication):
auth/models.py(You don't need to create a new user model for Github Auth):# Using Django's default User model (no changes needed)auth/serializers.py:from rest_framework import serializers from django.contrib.auth.models import User class UserSerializer(serializers.ModelSerializer): class Meta: model = User fields = ['id', 'username', 'email'] class AuthSerializer(serializers.Serializer): code = serializers.CharField(required=True)auth/views.py:```python from rest_framework import status from rest_framework.views import APIView from rest_framework.response import Response from django.shortcuts import redirect from django.conf import settings from django.contrib.auth.models import User from .serializers import UserSerializer, AuthSerializer from social_django.utils import load_strategy, load_backend from social_core.exceptions import SocialAuthBaseException import jwt from rest_framework_simplejwt.tokens import RefreshToken
def get_tokens_for_user(user): refresh = RefreshToken.for_user(user)
return { 'refresh': str(refresh), 'access': str(refresh.access_token), }
class LoginView(APIView): def get(self, request): strategy = load_strategy() backend = load_backend(strategy, 'github', redirect_uri=settings.GITHUB_CALLBACK_URL) auth_url = backend.auth_url() return redirect(auth_url)
class CallbackView(APIView): def post(self, request): serializer = AuthSerializer(data=request.data) if serializer.is_valid(raise_exception=True): strategy = load_strategy() backend = load_backend(strategy, 'github', redirect_uri=settings.GITHUB_CALLBACK_URL) try: user = backend.complete(request, serializer.validated_data.get('code')) except SocialAuthBaseException as e: return Response({'error': 'Social Authentication failed.'}, status=status.HTTP_400_BAD_REQUEST) if user: if not isinstance(user, User): user = user.user tokens = get_tokens_for_user(user) serializer = UserSerializer(user) return Response({'user': serializer.data, 'tokens': tokens}, status=status.HTTP_200_OK) else: return Response({'error': 'Social Authentication failed'}, status=status.HTTP_400_BAD_REQUEST)
class LogoutView(APIView): def post(self, request): return Response({'message': 'Logged Out'}, status=status.HTTP_200_OK)
class UserInfoView(APIView): def get(self, request): user = request.user serializer = UserSerializer(user) return Response(serializer.data, status=status.HTTP_200_OK)
* `auth/`[`urls.py`](http://urls.py):
```python
from django.urls import path
from .views import LoginView, CallbackView, LogoutView, UserInfoView
urlpatterns = [
path('login/', LoginView.as_view(), name='login'),
path('callback/', CallbackView.as_view(), name='callback'),
path('logout/', LogoutView.as_view(), name='logout'),
path('user/', UserInfoView.as_view(), name='user'),
]
myapi/urls.py:from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('auth/', include('auth.urls')), path('content/', include('content.urls')), ]myapi/settings.py(Crucial Configurations):INSTALLED_APPS = [ ..., 'rest_framework', 'rest_framework_simplejwt', 'social_django', ... ] AUTHENTICATION_BACKENDS = ( 'social_core.backends.github.GithubOAuth2', 'django.contrib.auth.backends.ModelBackend', ) REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework_simplejwt.authentication.JWTAuthentication', ) } GITHUB_CALLBACK_URL='http://localhost:8000/auth/callback/' SOCIAL_AUTH_GITHUB_KEY = os.environ.get('GITHUB_CLIENT_ID') SOCIAL_AUTH_GITHUB_SECRET = os.environ.get('GITHUB_CLIENT_SECRET')- Environment Variables: Make sure you set up environment variables in your terminal or
.envfile
- Environment Variables: Make sure you set up environment variables in your terminal or
export GITHUB_CLIENT_ID="your_client_id"
export GITHUB_CLIENT_SECRET="your_client_secret"
3. Django App: content (Example Data):
content/models.py:from django.db import models from django.contrib.auth.models import User class BlogPost(models.Model): title = models.CharField(max_length=200) content = models.TextField() author = models.ForeignKey(User, on_delete=models.CASCADE) created_at = models.DateTimeField(auto_now_add=True)content/serializers.py:from rest_framework import serializers from .models import BlogPost class BlogPostSerializer(serializers.ModelSerializer): author = serializers.ReadOnlyField(source='author.username') class Meta: model = BlogPost fields = ['id', 'title', 'content', 'author', 'created_at']content/views.py:```python from rest_framework import generics from .models import BlogPost from .serializers import BlogPostSerializer from rest_framework.permissions import IsAuthenticated
class BlogPostListCreateView(generics.ListCreateAPIView): queryset = BlogPost.objects.all() serializer_class = BlogPostSerializer permission_classes = [IsAuthenticated]
def perform_create(self, serializer): serializer.save(author=self.request.user)
class BlogPostRetrieveUpdateDestroyView(generics.RetrieveUpdateDestroyAPIView): queryset = BlogPost.objects.all() serializer_class = BlogPostSerializer permission_classes = [IsAuthenticated]
* `content/`[`urls.py`](http://urls.py):
```python
from django.urls import path
from .views import BlogPostListCreateView, BlogPostRetrieveUpdateDestroyView
urlpatterns = [
path('', BlogPostListCreateView.as_view(), name='blogpost-list-create'),
path('<int:pk>/', BlogPostRetrieveUpdateDestroyView.as_view(), name='blogpost-retrieve-update-destroy'),
]
4. Run Migrations:
Make migrations for both
authandcontentapps:python manage.py makemigrations auth content python manage.py migrate
5. Test the API:
Run the Django development server (
pythonmanage.pyrunserver).Use tools like Postman, curl, or a browser to test your API endpoints.
Try accessing
http://localhost:8000/auth/login/. You should be redirected to GitHub.After you log in with github you are gonna be redirected back to
http://localhost:8000/auth/callback/- NOTE: The frontend will send the github code in the body to the backend endpoint
Try hitting
http://localhost:8000/content/with a POST request with atitleandcontentin the body.- Note: This endpoint should require authentication, meaning you would need to send a JWT token in the headers of the request.
Authorization: Bearer <token>
- Note: This endpoint should require authentication, meaning you would need to send a JWT token in the headers of the request.