Skip to content

Commit

Permalink
Merge pull request #1 from Atomnp/certificate
Browse files Browse the repository at this point in the history
Certificate
  • Loading branch information
Atomnp authored Oct 14, 2022
2 parents bf2f770 + 7b5d1b2 commit c9327a5
Show file tree
Hide file tree
Showing 12 changed files with 228 additions and 51 deletions.
3 changes: 2 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"program": "${workspaceFolder}/certification_system/manage.py",
"args": ["runserver"],
"django": true,
"justMyCode": true
"justMyCode": true,
"cwd": "${workspaceFolder}/certification_system"
}
]
}
10 changes: 10 additions & 0 deletions certification_system/category/models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
from django.db import models
from event.models import Event

# Create your models here.
class Category(models.Model):
name = models.CharField(max_length=50)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
event=models.ForeignKey(Event, related_name="categories", on_delete=models.CASCADE)


def __str__(self):
return self.name
8 changes: 8 additions & 0 deletions certification_system/category/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from rest_framework import serializers
from .models import Category

class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
read_only_fields = ('created_at', 'updated_at')
fields = '__all__'
10 changes: 10 additions & 0 deletions certification_system/category/views.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
from category.models import Category
from django.shortcuts import render

# Create your views here.
from rest_framework import viewsets
from rest_framework import permissions
from category.serializers import CategorySerializer

class CategoryViewSet(viewsets.ModelViewSet):
queryset = Category.objects.all()
serializer_class = CategorySerializer
# permission_classes = [permissions.IsAuthenticated]

22 changes: 22 additions & 0 deletions certification_system/certificate/models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
from django.db import models
from category.models import Category
from event.models import Event
import uuid
from certification_system.utils.images import get_file_path

# Create your models here.
class Certificate(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField()
active = models.BooleanField()
category = models.ForeignKey(
Category, related_name="certificates", on_delete=models.CASCADE
)
event = models.ForeignKey(
Event, related_name="certificates", on_delete=models.CASCADE
)
# save certificates to media/certificates folder
image = models.ImageField(upload_to=get_file_path, null=True, blank=True)

created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

def __str__(self):
return self.name
10 changes: 10 additions & 0 deletions certification_system/certificate/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# serializers for certificate
from rest_framework import serializers
from .models import Certificate

class CertificateSerializer(serializers.ModelSerializer):
class Meta:
model = Certificate
# read only attributes
read_only_fields = ('created_at', 'updated_at')
fields = '__all__'
78 changes: 77 additions & 1 deletion certification_system/certificate/views.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,79 @@
from django.shortcuts import render
import uuid
from certificate.models import Certificate
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
import csv
import io
from io import BytesIO
from django.core.files.base import ContentFile

# Create your views here.
from rest_framework import viewsets
from rest_framework import permissions
from certificate.serializers import CertificateSerializer
from PIL import Image
from certification_system.utils.images import save_temporary_image, delete_temporary_image


def generate_certificate_dummy(template, data, mappings):
"""
Generate certificate from template and data
"""
file_path = save_temporary_image(template)
image = Image.open(file_path)
delete_temporary_image(file_path)
image = image.convert("L")
f = BytesIO()
try:
image.save(f, format="png")
return ContentFile(f.getvalue(), name=uuid.uuid4().hex + ".png")
finally:
f.close()


class CertificateViewSet(viewsets.ModelViewSet):
queryset = Certificate.objects.all().order_by("name")
serializer_class = CertificateSerializer
# permission_classes = [permissions.IsAuthenticated]


# route to generate bulk certificates using template image and csv file from the request
class BulkCertificateGenerator(APIView):
def post(self, request, format=None):
template_image = request.FILES["template_image"]
csv_file = request.FILES["csv_file"]
mapping = request.data["mapping"]

file = csv_file.read().decode("utf-8")
reader = csv.DictReader(io.StringIO(file))

for person in reader:
data = {
"name": person["name"],
"email": person["email"],
"active": True,
"category": request.data["category"],
"event": request.data["event"],
"image": generate_certificate_dummy(template_image, person, mapping),
}

certificate = CertificateSerializer(data=data)
try:
certificate.is_valid(raise_exception=True)
except Exception as e:
print(e)
return Response(
{"error": "Invalid data", "message": str(e)},
status=status.HTTP_400_BAD_REQUEST,
)
certificate.save()

return Response(
data={
"success": True,
"message": "Certificates generated successfully",
"data": [],
},
status=status.HTTP_201_CREATED,
)
84 changes: 44 additions & 40 deletions certification_system/certification_system/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,61 +20,62 @@
# 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-hk#rs6+=ymd$4biyom%e9@jw+t6bhpb@qwtji-wk=5&loivo+c'

SECRET_KEY = "django-insecure-hk#rs6+=ymd$4biyom%e9@jw+t6bhpb@qwtji-wk=5&loivo+c"


# Application definition

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'event'
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"rest_framework",
"event",
"category",
"certificate",
]

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',
"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 = 'certification_system.urls'
ROOT_URLCONF = "certification_system.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',
"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 = 'certification_system.wsgi.application'
WSGI_APPLICATION = "certification_system.wsgi.application"


# Database
# https://docs.djangoproject.com/en/4.1/ref/settings/#databases

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db' / 'db.sqlite3',
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db" / "db.sqlite3",
}
}

Expand All @@ -84,26 +85,26 @@

AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
},
]


# Internationalization
# https://docs.djangoproject.com/en/4.1/topics/i18n/

LANGUAGE_CODE = 'en-us'
LANGUAGE_CODE = "en-us"

TIME_ZONE = 'UTC'
TIME_ZONE = "UTC"

USE_I18N = True

Expand All @@ -113,13 +114,16 @@
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.1/howto/static-files/

STATIC_URL = 'static/'
STATIC_ROOT = '/app/static/'
STATIC_URL = "static/"
STATIC_ROOT = "/app/static/"
MEDIA_URL = "media/"
MEDIA_ROOT = BASE_DIR / "media/"


# Default primary key field type
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"


# Manual additions
Expand Down
26 changes: 18 additions & 8 deletions certification_system/certification_system/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,31 @@
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import include,path
from django.urls import include, path
from rest_framework import routers
from event import views
from event.views import EventViewSet
from category.views import CategoryViewSet
from certificate.views import CertificateViewSet, BulkCertificateGenerator
from django.conf.urls.static import static
from django.conf import settings

router = routers.DefaultRouter()
router.register(r'events', views.EventViewSet)
router.register(r"events", EventViewSet)
router.register(r"categories", CategoryViewSet)
router.register(r"certificates", CertificateViewSet)
# router.register(r'groups', views.GroupViewSet)



urlpatterns = [
path('', include(router.urls)),
path('admin/', admin.site.urls),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]
path("", include(router.urls)),
path("admin/", admin.site.urls),
path("api-auth/", include("rest_framework.urls", namespace="rest_framework")),
path(
"generate-bulk-certificate/",
BulkCertificateGenerator.as_view(),
name="generate-bulk-certificate",
),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
# urlpatterns = [
# path('admin/', admin.site.urls),
# ]
2 changes: 1 addition & 1 deletion certification_system/event/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Create your models here.
class Event(models.Model):
name = models.CharField(max_length=50)
name = models.CharField(max_length=50,primary_key=True)
description = models.TextField()
start_date = models.DateField()
end_date = models.DateField()
Expand Down
2 changes: 2 additions & 0 deletions certification_system/event/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@
class EventSerializer(serializers.ModelSerializer):
class Meta:
model = Event
# read only attributes
read_only_fields = ('created_at', 'updated_at')
fields = '__all__'
24 changes: 24 additions & 0 deletions certification_system/utils/images.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import uuid
import os
from django.core.files.storage import default_storage


def get_file_path(instance, filename):
ext = filename.split(".")[-1]
filename = "%s.%s" % (uuid.uuid4(), ext)
return os.path.join("certificates", filename)


def save_temporary_image(file_obj):
filename = str(uuid.uuid4()) + ".png"
with default_storage.open(filename, "wb+") as destination:
for chunk in file_obj.chunks():
destination.write(chunk)
import os

print(os.getcwd())
return "media/" + filename


def delete_temporary_image(filename):
default_storage.delete(filename.split("/")[-1])

0 comments on commit c9327a5

Please sign in to comment.