I am newbie to django and was using SQLite during development, when i moved to postgres when trying to deploy to production i get the below error
Cannot cast type time without time zone to timestamp with time zone
settings.py
Django settings for todoBackend project.
Generated by 'django-admin startproject' using Django 3.2.5.
For more information on this file, see
https://docs.djangoproject.com/en/3.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.2/ref/settings/
"""
from pathlib import Path
from django.core.management.utils import get_random_secret_key
import os
import sys
import dj_database_url
# 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/3.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.getenv("DJANGO_SECRET_KEY", get_random_secret_key())
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = os.getenv("DEBUG", "False") == "True"
ALLOWED_HOSTS = os.getenv("DJANGO_ALLOWED_HOSTS", "127.0.0.1,localhost").split(",")
# Application definition
INSTALLED_APPS = [
"rest_framework",
"corsheaders",
"api.apps.ApiConfig",
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
]
MIDDLEWARE = [
"corsheaders.middleware.CorsMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
CORS_ALLOW_ALL_ORIGINS = True
ROOT_URLCONF = "todoBackend.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 = "todoBackend.wsgi.application"
# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases
DEVELOPMENT_MODE = os.getenv("DEVELOPMENT_MODE", "False") == "True"
# DEVELOPMENT_MODE = True
if DEVELOPMENT_MODE is True:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": os.path.join(BASE_DIR, "db.sqlite3"),
}
}
elif len(sys.argv) > 0 and sys.argv[1] != "collectstatic":
if os.getenv("DATABASE_URL", None) is None:
raise Exception("DATABASE_URL environment variable not defined")
DATABASES = {
"default": dj_database_url.parse(os.environ.get("DATABASE_URL")),
}
# Password validation
# https://docs.djangoproject.com/en/3.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/3.2/topics/i18n/
LANGUAGE_CODE = "en-us"
TIME_ZONE = "Asia/Kolkata"
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/
STATIC_URL = "/static/"
STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
# Default primary key field type
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
models.py
from django.db import models
# Create your models here.
class Tasks(models.Model):
title = models.CharField(max_length=200, blank=False, null=False)
description = models.CharField(max_length=1000, blank=True)
start_time = models.DateTimeField(blank=True, null=True)
end_time = models.DateTimeField(blank=True, null=True)
duration = models.CharField(max_length=25, blank=True)
completed = models.BooleanField(default=False)
last_modified = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
I am not sure why i am getting the error, i did setup the timezone in settings.py
The above code was working perfectly with SQLite , It only throws the error in Postgres
As #Iain shelvington in the comments pointed out , I had a migration that converted the end_time field from Character field to Time Field, Hence i was getting this error
I reset all my migrations and created a single migration which resolved the issue
Related
I just deployed my django application to a beanstalk server linked to an s3 bucket in the aws console.
In my application pdfs from each post are created and forwarded to the media folder in the subfolder "postings". However, in the bucket no such folder is created and the pdfs also don't show up anywhere else. only the uploaded images of the post is there.
How do I get the pdfs there?
also, I get an ValueError now for the Image in the PDF (which is the uploaded image, and which was working just fine before adding the bucket). How do I get it to work again? I think both problems are due to some connection missing... This is my first project deploying to aws. Please help me out with a little explanation.
Here is the code of the created upload and pdf:
views.py
def post_create(request):
if request.method == 'POST':
form = PostCreateForm(request.POST, request.FILES)
if form.is_valid():
form.cleaned_data['num_post'] = Post.objects.count() + 1
Post.objects.create(**form.cleaned_data)
else:
form = PostCreateForm()
return render(request, 'index.html', {'form': form})
def upload(request):
if request.method == 'POST':
image = request.FILES.get('image_upload')
caption = request.POST['caption']
num_post = Post.objects.count() + 1
new_post = Post.objects.create(image=image, caption=caption, num_post=num_post)
new_post.save()
# create pdf
buffer = io.BytesIO()
x_start = 100
y_start = 100
folder_path = f"media/postings/post{num_post}.pdf"
folder_name = os.path.join(BASE_DIR, folder_path)
p = canvas.Canvas(folder_name, pagesize=A4, )
if image is not None:
register_heif_opener()
pil_image = io.BytesIO()
PIL.Image.open(image.file).save(pil_image, 'PNG')
p.drawImage(ImageReader(PIL.Image.open(pil_image)), x_start, y_start, width=420, preserveAspectRatio=True,
mask='auto')
p.drawString(150, 650, new_post.caption)
p.drawString(100, 650, "caption:")
p.drawString(100, 170, str(new_post.created_at))
p.drawString(200, 700, str(num_post))
p.drawString(100, 700, "post no.:")
p.drawString(250, 700, "//")
p.drawString(100, 690, "===========================================================")
p.drawString(300, 700, str(new_post.id))
p.save()
buffer.seek(0)
return redirect('/')
else:
return redirect('/')
the Post Model
def post_images(instance, filename):
ext = filename.split('.')[-1]
filename = 'postimg{}.{}'.format(instance.num_post, ext)
return os.path.join('uploads', filename)
class Post(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
num_post = models.IntegerField(default=0)
image = models.ImageField(upload_to=post_images)
caption = models.TextField(max_length=300)
created_at = models.DateTimeField(auto_now_add=True)
number_of_likes = models.IntegerField(default=0)
number_of_dislikes = models.IntegerField(default=0)
likes_string = models.TextField(max_length=800, default="")
dislikes_string = models.TextField(max_length=800, default="")
interaction_count = models.IntegerField(default=0)
#property
def filename(self):
return os.path.basename(self.image.name).split('.')[0]
def __str__(self):
return self.caption
the media settings
from django.contrib import staticfiles
# 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.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = "..."
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = getenv("IS_DEVELOPMENT", True)
ALLOWED_HOSTS = [
getenv("APP_HOST", "localhost"),
'127.0.0.1'
]
# Application definition
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
'core.apps.CoreConfig',
'storages'
]
MIDDLEWARE = [
"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 = "social_book.urls"
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [os.path.join(BASE_DIR, 'templates')]
,
"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 = "social_book.wsgi.application"
# Database
# https://docs.djangoproject.com/en/4.1/ref/settings/#databases
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": "postgres",
"USER": "feedingcycle",
"PASSWORD": "...",
"HOST": "django-social-media.cuo1odqldl3u.us-east-1.rds.amazonaws.com",
"PORT": "5432"
}
}
# Password validation
# https://docs.djangoproject.com/en/4.1/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.1/topics/i18n/
LANGUAGE_CODE = "en-us"
TIME_ZONE = "UTC"
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.1/howto/static-files/
STATIC_URL = "static/"
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static'),)
# Default primary key field type
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
AWS_STORAGE_BUCKET_NAME = "django-feeding-cycle"
AWS_S3_REGION_NAME = "us-east-1"
AWS_ACCESS_KEY_ID = "..."
AWS_SECRET_ACCESS_KEY = "..."
AWS_S3_CUSTOM_DOMAIN = f"{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com"
STATICFILES_STORAGE = "storages.backends.s3boto3.S3Boto3Storage"
MEDIAFILES_FOLDER = "media"
DEFAULT_FILE_STORAGE = "custom_storages.MediaFileStorage"
the storage
from django.conf import settings
from storages.backends.s3boto3 import S3Boto3Storage
class MediaFileStorage(S3Boto3Storage):
location = settings.MEDIAFILES_FOLDER
and the config
option_settings:
aws:elasticbeanstalk:environment:proxy:staticfiles:
/static: staticfiles
/media: media
So when I create an media folder like this, i get the error and no pdf is created. if i just use the default in the bucket I don't get the error but still no pdf is created... in the project preview server everything was working just fine. also without the bucket. But i need the bucket, so that I can sinc it with a local folder, to get the posted files directly...
I have built a server with Django and I am receiving a 400 Bad Request within Postman when I check the POST method. However, it is displaying the JSON data within the Postman as well.
Originally, I thought it was a frontend issue, because my console log was stating
AxiosError {message: 'Request failed with status code 400', name: 'AxiosError', code: 'ERR_BAD_REQUEST', config: {…}, request: XMLHttpRequest, …}
As I stated before, the error is showing in Postman so I'm assuming it's actually a server issue.
Im real "finicky" when it comes to file colors, and if it is any color than the default color, I feel like there is errors within the file. Could these orange/beige files contain the problem? If I click on one of those files Im met with:
The file is not displayed in the editor because it is either binary or uses an unsupported text encoding.
Because I am new to django, I don't want to do something that's going to create an even bigger problem than what I already have.
Below will be my settings.py
"""
Django settings for django_rest_api project.
Generated by 'django-admin startproject' using Django 4.1.4.
For more information on this file, see
https://docs.djangoproject.com/en/4.1/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.1/ref/settings/
"""
from pathlib import Path
# 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.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = "django-insecure-2r=5^!2(nj*^*m*sa_39h(xldjpau&$wmn&pc5=^frws#w&25="
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
"corsheaders",
"rest_framework",
"todo_api",
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
]
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",
]
CORS_ALLOW_ALL_ORIGINS = True
ROOT_URLCONF = "django_rest_api.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 = "django_rest_api.wsgi.application"
# Database
# https://docs.djangoproject.com/en/4.1/ref/settings/#databases
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": "todo_api",
"USER": "",
"PASSWORD" : '',
"HOST": "localhost"
}
}
# Password validation
# https://docs.djangoproject.com/en/4.1/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.1/topics/i18n/
LANGUAGE_CODE = "en-us"
TIME_ZONE = "UTC"
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.1/howto/static-files/
STATIC_URL = "static/"
# Default primary key field type
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
Below is my views.py
from django.shortcuts import render
from rest_framework import generics
from .serializer import TodoSerializer
from .models import Todo
# Create your views here.
class TodoList(generics.ListCreateAPIView):
queryset = Todo.objects.all().order_by('id')
serializer_class = TodoSerializer
class TodoDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Todo.objects.all().order_by('id')
serializer_class = TodoSerializer
Im not exactly sure what information everyone needs to provide a proper solution for this, but hopefully I have provided more than enough.
I think it is worth noting that I am using postgreql and my database is working properly, and I can access Django admin and manually enter data from there as well.
I created a django project tha uses a customUser for authentication, following this blog post.
I now would like to attach another app to the project that is a REST API that leverages that authentication.
In this new app I create a model for the data that the uses will consume and I add as foreign key in the model the custom user model previously created.
#project/api/models.py
from django.contrib.postgres.fields import ArrayField
from django.db import models
from accounts.models import CustomUser
class Signal(models.Model):
name = models.CharField(max_length=30, blank=True, null=True)
data = ArrayField(models.FloatField(), unique=True)
threshold = models.FloatField(blank=True, null=True)
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
def __str__(self) -> str:
return f"{self.name}"
while the project/api/views.py file is
from django.template.defaultfilters import pluralize
from rest_framework.decorators import api_view
from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.request import Request
from rest_framework.response import Response
from . import serializers
from .algorithm.compute_crossing import count_crossing_pos as count_cross
from .models import Signal
class SignalViewset(ListCreateAPIView):
permission_classes = [IsAuthenticated]
queryset = Signal.objects.all()
serializer_class = serializers.SignalSerializer
def get_queryset(self):
return super().get_queryset().filter(user=self.request.user)
class SignalDetail(RetrieveUpdateDestroyAPIView):
permission_classes = [IsAuthenticated]
queryset = Signal.objects.all()
serializer_class = serializers.SignalSerializer
def get_queryset(self):
return super().get_queryset().filter(user=self.request.user)
#api_view(http_method_names=["POST"])
def send_data(request: Request) -> Response():
"""send signal data with threshold in request payload
and compute crossing times around given threshold
:param request: [request payload]
:type request: [type]
"""
if request.user.is_authenticated:
count = count_cross(request.data.get("data"), request.data.get("threshold"))
return Response(
{
"status": "success",
"info": "signal crosses the given threshold {} tim{}".format(
count, pluralize(count, "e,es")
),
"count": str(count),
},
status=200,
)
else:
count = count_cross(request.data.get("data"), request.data.get("threshold"))
return Response(
{
"status": "success",
"info": "you are an AnonymousUser but I will give you an answer nonetheless \n \n signal crosses the given threshold {} tim{}".format(
count, pluralize(count, "e,es")
),
"count": str(count),
},
status=200,
)
Everytime I access the send_data endpoint I go into the else statement as request.user.is_authenticated is False.
how do I connect the rest api with the authentication (accounts) app?
my settings.py file is:
from pathlib import Path
from decouple import config
# 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/3.2/howto/deployment/checklist/
SYSTEM_ENV = config("SYSTEM_ENV")
ALLOWED_HOSTS = [
"*",
]
# Application definition
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"api",
"rest_framework",
"rest_framework.authtoken",
"dj_rest_auth",
"django.contrib.sites",
"allauth",
"allauth.account",
"dj_rest_auth.registration",
"accounts",
]
AUTH_USER_MODEL = "accounts.CustomUser" # new
MIDDLEWARE = [
"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 = "signal_crossing.urls"
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [str(BASE_DIR.joinpath("templates"))],
"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 = "signal_crossing.wsgi.application"
# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases
if SYSTEM_ENV == "PRODUCTION" or SYSTEM_ENV == "STAGING":
print("docker")
DEBUG = False
SECRET_KEY = config("SECRET_KEY")
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql_psycopg2",
"NAME": "postgres",
"USER": "postgres",
"PASSWORD": "postgres",
"HOST": "db",
"PORT": 5432,
}
}
elif SYSTEM_ENV == "GITHUB_WORKFLOW":
DEBUG = True
SECRET_KEY = "TESTING_KEY"
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql_psycopg2",
"NAME": "github_actions",
"USER": "postgres",
"PASSWORD": "postgres",
"HOST": "127.0.0.1",
"PORT": "5432",
}
}
elif SYSTEM_ENV == "DEVELOPMENT":
DEBUG = True
SECRET_KEY = "DEVELOP_KEY"
# DATABASES = {
# "default": {
# "ENGINE": "django.db.backends.postgresql_psycopg2",
# "NAME": config("DB_NAME"),
# "USER": config("POSTGRES_LOCAL_USER"),
# "PASSWORD": config("POSTGRES_LOCAL_PASSWORD"),
# "HOST": "localhost",
# "PORT": "5432",
# }
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3",
}
}
# Password validation
# https://docs.djangoproject.com/en/3.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/3.2/topics/i18n/
LANGUAGE_CODE = "en-us"
TIME_ZONE = "UTC"
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/
STATIC_URL = "/static/"
# Default primary key field type
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
SITE_ID = 1
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": [
# 'rest_framework.authentication.TokenAuthentication',
"dj_rest_auth.jwt_auth.JWTCookieAuthentication",
],
}
REST_USE_JWT = True
JWT_AUTH_COOKIE = "my-app-auth"
AUTHENTICATION_BACKENDS = [
"django.contrib.auth.backends.ModelBackend",
# allauth specific authentication methods, such as login by e-mail
"allauth.account.auth_backends.AuthenticationBackend",
# Needed to login by username in Django admin, regardless of allauth
"django.contrib.auth.backends.ModelBackend",
]
# ACCOUNT_AUTHENTICATION_METHOD = "username"
# LOGIN_URL = "/login/"
# LOGIN_REDIRECT_URL = "/"
# LOGOUT_REDIRECT_URL = "/"
DJANGO_SETTINGS_MODULE = "signal_crossing.settings"
LOGIN_REDIRECT_URL = "home"
LOGOUT_REDIRECT_URL = "home"
I've built a Django API that uses django-graphql-auth and django-graphql-jwt packages to implement authentication. I followed the package's documentation and got everything to work and everything is working from my Angular UI. The only issue is that even requests made from Postman without the Authorization header, are able to fetch the data from the graphql API.
This is my Django project's settings.py
"""
Django settings for myproject project.
Generated by 'django-admin startproject' using Django 3.2.3.
For more information on this file, see
https://docs.djangoproject.com/en/3.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.2/ref/settings/
"""
from pathlib import Path
import os
import sys
# 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/3.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-)3#2sm6lgn_p83_t(l-44hd16ou5-qbk=rso!$b1#$fu*n2^rq'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = ["*"]
CORS_ORIGIN_ALLOW_ALL = True
# Application definition
INSTALLED_APPS = [
'corsheaders',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'myapp',
'graphene_django',
'graphql_jwt.refresh_token.apps.RefreshTokenConfig',
'graphql_auth',
'rest_framework',
'django_filters'
]
GRAPHENE = {
'SCHEMA': 'myproject.schema.schema',
'MIDDLEWARE': [
'graphql_jwt.middleware.JSONWebTokenMiddleware',
],
}
GRAPHENE_DJANGO_EXTRAS = {
'DEFAULT_PAGINATION_CLASS': 'graphene_django_extras.paginations.LimitOffsetGraphqlPagination',
'DEFAULT_PAGE_SIZE': 20,
'MAX_PAGE_SIZE': 50,
'CACHE_ACTIVE': True,
'CACHE_TIMEOUT': 300 # seconds
}
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'common.utils.UpdateLastActivityMiddleware'
]
AUTHENTICATION_BACKENDS = [
'graphql_auth.backends.GraphQLAuthBackend',
'django.contrib.auth.backends.ModelBackend',
]
GRAPHQL_JWT = {
"JWT_ALLOW_ANY_CLASSES": [
"graphql_auth.mutations.Register",
"graphql_auth.mutations.VerifyAccount",
"graphql_auth.mutations.ResendActivationEmail",
"graphql_auth.mutations.SendPasswordResetEmail",
"graphql_auth.mutations.PasswordReset",
"graphql_auth.mutations.ObtainJSONWebToken",
"graphql_auth.mutations.VerifyToken",
"graphql_auth.mutations.RefreshToken",
"graphql_auth.mutations.RevokeToken",
],
'JWT_PAYLOAD_HANDLER': 'common.utils.jwt_payload',
"JWT_VERIFY_EXPIRATION": True,
"JWT_LONG_RUNNING_REFRESH_TOKEN": True
}
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
ROOT_URLCONF = 'myproject.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates'), ],
'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 = 'myproject.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases
# DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': BASE_DIR / 'db.sqlite3',
# }
# }
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'myprojectdb',
'USER': 'myprojectadmin',
'PASSWORD': 'password',
'HOST': 'db',
'PORT': '5432',
}
}
# Password validation
# https://docs.djangoproject.com/en/3.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/3.2/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/
STATIC_URL = '/static/'
STATICFILES_DIRS = (
BASE_DIR / "static",
'/var/www/static/',
)
# Media files
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
# Default primary key field type
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# This is here because we are using a custom User model
# https://docs.djangoproject.com/en/2.2/topics/auth/customizing/#substituting-a-custom-user-model
AUTH_USER_MODEL = "myapp.User"
urls.py
from django.contrib import admin
from django.urls import include, path
from django.views.decorators.csrf import csrf_exempt
from graphene_django.views import GraphQLView
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('', include('myapp.urls')),
path('admin/', admin.site.urls),
path('graphql/', csrf_exempt(GraphQLView.as_view(graphiql=True))),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Sample query:-
query users {
users {
id
nickName
lastLogin
}
}
As you can see, I've followed all the necessary steps to accomodate the instructions in both the packages. How do I prevent unauthorized requests accessing my data?
Updates:-
I'm using Django-graphql-extras for pagination, filtering on my Graphql api. So the queries are all using the built-in methods from that package.
The mutations however are manual.
Queries file:-
from graphene_django.types import ObjectType
from .gqTypes import InstitutionType, UserType, GroupType
from graphene_django_extras import DjangoObjectField, DjangoFilterPaginateListField, LimitOffsetGraphqlPagination
class Query(ObjectType):
institution = DjangoObjectField(
InstitutionType, description='Single User query')
user = DjangoObjectField(UserType, description='Single User query')
group = DjangoObjectField(GroupType, description='Single User query')
institutions = DjangoFilterPaginateListField(
InstitutionType, pagination=LimitOffsetGraphqlPagination())
users = DjangoFilterPaginateListField(
UserType, pagination=LimitOffsetGraphqlPagination())
groups = DjangoFilterPaginateListField(
GroupType, pagination=LimitOffsetGraphqlPagination())
Sample mutation code:-
class CreateUser(graphene.Mutation):
class Meta:
description = "Mutation to create a new User"
class Arguments:
input = UserInput(required=True)
ok = graphene.Boolean()
user = graphene.Field(UserType)
#staticmethod
def mutate(root, info, input=None):
ok = True
error = ""
if input.name is None:
error += "Name is a required field<br />"
if len(error) > 0:
raise GraphQLError(error)
searchField = input.name
searchField += input.title if input.title is not None else ""
searchField += input.bio if input.bio is not None else ""
searchField = searchField.lower()
user_instance = User(user_id=input.user_id, title=input.title, bio=input.bio,
institution_id=input.institution_id, searchField=searchField)
user_instance.save()
return CreateUser(ok=ok, user=user_instance)
You should add the login_required decorator to your queries and mutations resolvers. Like this:
from graphql_jwt.decorators import login_required
class Query(graphene.ObjectType):
viewer = graphene.Field(UserType)
#login_required
def resolve_viewer(self, info, **kwargs):
return info.context.user
In your case put it after staticmethod decorator, like this:
#staticmethod
#login_required
def mutate():
pass
django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.
checked all INSTALLED_APPS in settings.py
registered models,apps.py.
Earlier this error was not coming when i was working with core and users applications under the same project.
settings.py
"""
Django settings for jam project.
Generated by 'django-admin startproject' using Django 2.2.1.
For more information on this file, see
https://docs.djangoproject.com/en/2.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/ref/settings/
"""
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'bj))qqcyggizpqmxp9zru$pb%m#bt0--_z%$#z6!xz^$ij3#^#'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
#All applications are working
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'home.apps.HomeConfig',
'core.apps.CoreConfig',
'users.apps.UsersConfig',
'crispy_forms',
]
MIDDLEWARE = [
'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 = 'jam.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')]
,
'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 = 'jam.wsgi.application'
# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Password validation
# https://docs.djangoproject.com/en/2.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/2.2/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/
from home import views
STATIC_URL = '/static/'
LOGIN_REDIRECT_URL = views.index
CRISPY_TEMPLATE_PACK= 'bootstrap4'
#managing media
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
home/models.py
from django.db import models
class OurPicks(models.Model):
title = models.CharField(max_length=150)
pro_id = models.AutoField
pro_desc = models.TextField()
size = models.CharField(max_length=200)
quantity = models.CharField(max_length=200)
slug = models.SlugField()
sleeves_length = models.CharField(max_length=15)
neck_style = models.CharField(max_length=20)
updated = models.DateTimeField(auto_now=True)
availability = models.BooleanField(default=True)
orignal_price = models.FloatField(blank=True)
discounted_price = models.FloatField(blank=True)
image1 = models.ImageField(upload_to='media', default='')
image2 = models.ImageField(upload_to='media', default='')
image3 = models.ImageField(upload_to='media', default='')
image4 = models.ImageField(upload_to='media', default='')
color = models.CharField(max_length=200)
JEWELLERY = 'JEWELLERY'
KURTIS = 'KURTIS'
LADIES_SUIT = 'LADIES_SUIT'
CATEGORIES = [
(JEWELLERY, 'jewellery'),
(KURTIS, 'kurtis'),
(LADIES_SUIT, 'ladies_suit'),
]
categories = models.CharField(
max_length=11,
choices=CATEGORIES,
default=None,
)
def __str__(self):
return self.title
home/admin.py
from django.contrib import admin
from .models import OurPicks
from core.apps import CoreConfig,AppConfig
from core.models import Orders
# from .modelv1 import Productcolor
#class PicksAdmin(admin.ModelAdmin):
admin.site.register(OurPicks)
home/apps.py
from django.apps import AppConfig
django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.