skip to Main Content

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


  1. Chosen as BEST ANSWER

    I was finally able to deploy DRF (Django Rest Framework) in azure with SQL server database. Following this tutorial by MS .


  2. 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:

    django-admin startproject ProjectName
    cd ProjectName
    django-admin startapp ProjectName_api
    

    I have made the following changes in todo/settings.py and referred to the code from the link above .

    ALLOWED_HOSTS = ["*"]
    

    Remove CORS_ALLOWED_ORIGINS and CSRF_TRUSTED_ORIGINS in settings.py .

    Then, add 'rest_framework' and your app ('APIName_api') to the INSTALLED_APPS section in todo/settings.py:

    INSTALLED_APPS = [
    
        'rest_framework',
        'todo_api',
    ]
    

    Next, create a model for the to-do list in api/models.py and define a serializer to convert the Todo model into JSON format in api/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 in api/urls.py:

    urlpatterns = [
        path('api/', TodoListApiView.as_view()),
        path('api/<int:todo_id>/', TodoDetailApiView.as_view()),
    ]
    

    Then include the _api URL in the main project by editing ProjectName/urls.py:

    urlpatterns = [ path('admin/', admin.site.urls), path('Url/', include('ProjectName_api.urls')), ]
    

    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:

    dbname=<db_name> host=<db_host> port=5432 user=<db_user> password=<db_password>
    

    Add the following to settings.py and update the below parameters:

    settings.py
    
    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'),
            'OPTIONS': {'sslmode': 'require'},
        }
    }
    

    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:

         - name: Run Django makemigrations and migrate
            run: |
              source venv/bin/activate
              python manage.py makemigrations
              python manage.py migrate
            env:
              DBNAME: postgres
              DBHOST: AzureHost
              DBUSER: postgres
              DBPASS: postgres
    
          - name: Create Django superuser
            run: |
              source venv/bin/activate
              python manage.py createsuperuser --noinput --username admin1 --email [email protected]
            env:
              DBNAME: postgres
              DBHOST: AzureHost
              DBUSER: postgres
              DBPASS: postgres
    

    Output:

    enter image description here

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search