I have tried to solve how to deploy Django project on Azure, been following many tutorials but in this point i cant point whats the issue.
Deploying from GitHub, deployment have been success whew times but i cant to access to my application, i get mostly 404 or application error when run trough browser.
I have postgre locally migrated but i want to use Azure postgre DB.
Been pandering with ENV variables, i cant to connect to SHH to apply migrations, CONN CLOSE..etc
So i have no idea where to start now actually?
I have tried Microsoft guides, guides from internet, asking help from ChatGPT.
I want to deploy my Django app on Azure but have no idea now , ‘how to’ .
EDIT: Added Code, sorry for the delay.
SETTINGS.PY
#default moduuli
from pathlib import Path
#ympäristö muuttuja moduulit
import os
from dotenv import load_dotenv
#lataa ympäristö muuttujat
load_dotenv()
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.getenv('SECRET_KEY')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = os.getenv('DEBUG') == 'True' # Muunna merkkijonoksi booleaniksi
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'main',
'rest_framework',
'corsheaders',
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'restapi.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'restapi.wsgi.application'
# Databases
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
'''
#sqlite
#uncomment to use
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
'''
#Postgre
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ.get('DBNAME'),
'HOST': os.environ.get('DBHOST'),
'USER': os.environ.get('DBUSER'),
'PASSWORD': os.environ.get('DBPASS'),
}
}
# Password validation
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/4.2/topics/i18n/
LANGUAGE_CODE = 'fi-fi'
#TIME_ZONE = 'UTC'
TIME_ZONE = 'Europe/Helsinki'
USE_TZ = True
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.2/howto/static-files/
STATIC_URL = 'static/'
# Default primary key field type
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
#HUOM
#Muut asetukset tänne!
######################
#Tietoliikenne asetukset
ALLOWED_HOSTS = [
'192.168.201.225', #oma IP
'localhost',
'127.0.0.1',
]
CORS_ALLOWED_ORIGINS = [
"http://localhost:3000",
"http://127.0.0.1:5000",
"http://192.168.201.225:8000", # Lisää oma IP
"http://192.168.201.225", # Lisää oma IP
]
#Django 4 ---> tarvitaan cross site request forgery määritys
CSRF_TRUSTED_ORIGINS = [
"http://localhost:3000",
"http://127.0.0.1:5000",
"http://192.168.201.225",# Lisää oma IP
]
#vain testausta varten ei tuotantoon!
#CSRF_COOKIE_SECURE = False
#istunnon cookie timeout
#SESSION_COOKIE_AGE = 3600
MODELS.PY:
# main/models.py
from django.db import models
from django.contrib.auth.models import User
class Post(models.Model):
content = models.TextField() # Postin sisältö
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='posts')
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
def __str__(self):
return f"{self.author.username} - {self.content[:20]}..."
class Comment(models.Model):
comment_content = models.TextField() # Kommentin sisältö
commenter = models.ForeignKey(User, on_delete=models.CASCADE, related_name='comments')
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
def __str__(self):
return f"{self.commenter.username} - {self.comment_content[:20]}..."
class Like(models.Model):
liker = models.ForeignKey(User, on_delete=models.CASCADE, related_name='likes')
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='likes')
def __str__(self):
return f"{self.liker.username} liked {self.post.content[:20]}..."
API_VIEWS.PY:
# main/api_views.py
#REST Api näkymä funktiot
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework import viewsets, permissions, status, generics
from rest_framework.response import Response
from .models import Post, Comment, Like, User
from .serializers import PostSerializer, CommentSerializer, LikeSerializer, SignupSerializer
from django.contrib.auth import authenticate, login, logout
from .serializers import UserSerializer
from django.http import JsonResponse
from django.middleware.csrf import get_token
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
from rest_framework import viewsets, permissions
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import AllowAny
'''
#Poistaa CSRF tarkistuksen testausta varten
#Viittaa ViewSetissä lisäämäällä --> authentication_classes = [CsrfExemptSessionAuthentication]
class CsrfExemptSessionAuthentication(SessionAuthentication):
def enforce_csrf(self, request):
return # Ei tarkista CSRF-tokenia
'''
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all().order_by('-created')
serializer_class = PostSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
#Poistaa CSRF tarkistuksen
#authentication_classes = [CsrfExemptSessionAuthentication]
def perform_create(self, serializer):
serializer.save(author=self.request.user)
class CommentViewSet(viewsets.ModelViewSet):
queryset = Comment.objects.all()
serializer_class = CommentSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
def perform_create(self, serializer):
print("Received data:", self.request.data) # Tulostaa saatu data
post_id = self.request.data.get('post')
print("Post ID:", post_id) # Tulostaa post_id:n
try:
post = Post.objects.get(id=post_id)
print("Post found:", post) # Tulostaa löytyneen postin
serializer.save(commenter=self.request.user, post=post)
except Post.DoesNotExist:
print(f"Post with id {post_id} does not exist.")
except Exception as e:
print(f"An error occurred: {str(e)}")
class LikeViewSet(viewsets.ModelViewSet):
queryset = Like.objects.all()
serializer_class = LikeSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
def get_queryset(self):
# Palauttaa vain kirjautuneen käyttäjän querysetin
return User.objects.filter(id=self.request.user.id)
#Käyttäjä tiedot
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def user_profile_view(request):
"""
Palauttaa kirjautuneen käyttäjän profiilitiedot.
"""
user = request.user
serializer = UserSerializer(user)
return Response(serializer.data)
@api_view(['POST'])
def login_view(request):
"""
Ohje.
Käyttäjän kirjautuminen.
Kirjoita käyttäjätunnus ja salasana POST-pyyntöön JSON-muodossa ja merkkijonot string tyyppinä.
Esim:
{
"username": "Käyttäjä",
"password": "salasana"
}
"""
username = request.data.get('username')
password = request.data.get('password')
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return Response({'message': 'Login successful'}, status=status.HTTP_200_OK)
else:
return Response({'error': 'Invalid credentials'}, status=status.HTTP_400_BAD_REQUEST)
# Tunnusten luonti API endpoint
@api_view(['POST'])
def signup(request):
serializer = SignupSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response({"message": "User created successfully!"}, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['POST'])
def logout_view(request):
logout(request)
return Response({'message': 'Logged out successfully'}, status=status.HTTP_200_OK)
#tee csfr token haku kun suoritetaan POST ja DELETE pyyntöjä
def csrf_token_view(request):
csrf_token = get_token(request)
return JsonResponse({'csrfToken': csrf_token})
SERIALIZERS.PY
# main/serializers.py
from rest_framework import serializers
from .models import Post, Comment, Like
from django.contrib.auth.models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'username', 'first_name', 'last_name']
class PostSerializer(serializers.ModelSerializer):
author = UserSerializer(read_only=True)
class Meta:
model = Post
fields = ['id', 'author', 'content', 'created']
class CommentSerializer(serializers.ModelSerializer):
commenter = UserSerializer(read_only=True)
post = PostSerializer(read_only=True)
class Meta:
model = Comment
fields = ['id', 'commenter', 'post', 'comment_content', 'created'] # päivitetty kentät 'user' -> 'commenter', 'content' -> 'comment_content', ja 'created_at' -> 'created'
read_only_fields = ['commenter', 'created'] # commenter kenttä vain luettavaksi
class LikeSerializer(serializers.ModelSerializer):
liker = UserSerializer(read_only=True)
post = PostSerializer(read_only=True)
class Meta:
model = Like
fields = ['id', 'liker', 'post'] # päivitetty kenttä 'user' -> 'liker'
class SignupSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True)
first_name = serializers.CharField(required=False, allow_blank=True)
last_name = serializers.CharField(required=False, allow_blank=True)
class Meta:
model = User
fields = ['username', 'password', 'email', 'first_name', 'last_name']
def create(self, validated_data):
user = User(
username=validated_data['username'],
email=validated_data['email'],
first_name=validated_data.get('first_name', ''), # Oikea tapa käyttää get()
last_name=validated_data.get('last_name', '') # Oikea tapa käyttää get()
)
user.set_password(validated_data['password'])
user.save()
return user
URLS.PY
# main/urls.py
from rest_framework.routers import DefaultRouter
from .api_views import CommentViewSet, LikeViewSet,UserViewSet, login_view, logout_view ,PostViewSet
from django.urls import path, include
from . import api_views
from .api_views import csrf_token_view #,PostCreateView
# REST API reititys
router = DefaultRouter()
router.register(r'posts', PostViewSet)
router.register(r'comments', CommentViewSet)
router.register(r'likes', LikeViewSet)
router.register(r'users', UserViewSet)
# URLS
urlpatterns = [
# REST API reitit
path('api/', include(router.urls)),
path('api/login/', login_view, name='api_login'),
path('api/logout/', logout_view, name='api_logout'),
path('api/csrf/', csrf_token_view, name='csrf-token'),
path('api/profile/', api_views.user_profile_view, name='user-profile'),
path('api/signup/', api_views.signup, name='signedup'),
#feed
#path('', views.feed, name='feed'),
]
#ok
2
Answers
I was finally able to deploy DRF (Django Rest Framework) in azure with SQL server database. Following this tutorial by MS .
I tried your code and encountered the same issue. I found this link that explains how to deploy and create a REST API using the Django REST Framework.
After setting up the REST API backend by using below command:
I have made the following changes in
todo/settings.py
and referred to the code from the link above .Remove
CORS_ALLOWED_ORIGINS
andCSRF_TRUSTED_ORIGINS
in settings.py .Then, add
'rest_framework'
and your app ('APIName_api'
) to theINSTALLED_APPS
section intodo/settings.py
:Next, create a model for the to-do list in
api/models.py
and define a serializer to convert theTodo
model into JSON format inapi/serializers.py
.Define the API views for listing, creating, updating, and deleting to-dos in
api/views.py
. Then, define the URL patterns for the API endpoints inapi/urls.py
:Then include the
_api
URL in the main project by editingProjectName/urls.py
:I followed this link to integrate Azure PostgreSQL DB with Django. First, create an Azure PostgreSQL instance, and the connection string for the Azure PostgreSQL database will have the following format:
Add the following to
settings.py
and update the below parameters:Migrate the database, create a superuser, and start the server locally for testing. Afterward, push the code to Git.You can test your API at
todos/api
.Create a web with GitHub Actions enabled by setting up continuous deployment and basic authentication.Make sure to add PostgreSQL parameters in Environment variables azure web app.
Update your
.yml
file as follows:Output: