Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Public api #60

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions kerckhoff/packages/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,6 @@ def create_version(
updated_package_item_titles: List[str],
):
"""Creates new PackageVersion object

Arguments:
user {User} -- User object, required argument
package_version {PackageVersion} -- the package version to be added
Expand Down Expand Up @@ -300,4 +299,4 @@ def create_from_google_drive_item(
mime_type=google_drive_file.mimeType,
)
pi.save()
return pi
return pi
66 changes: 66 additions & 0 deletions kerckhoff/packages/serializers.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import os
from dataclasses import field
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you meant to import this. I'm guessing it was added by the IDE

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used it for string manipulation.

from rest_framework import serializers
from rest_framework.validators import UniqueTogetherValidator

Expand Down Expand Up @@ -172,3 +174,67 @@ def get_version_data(self, obj: Package):
class Meta(PackageSerializer.Meta):
fields = PackageSerializer.Meta.fields + ("version_data",)
read_only_fields = PackageSerializer.Meta.read_only_fields + ("version_data",)

class PublicPackageSerializer(serializers.ModelSerializer):
package_set = serializers.StringRelatedField()
latest_version = serializers.StringRelatedField()
description = serializers.SerializerMethodField()

data = serializers.SerializerMethodField()
cached_article_preview = serializers.SerializerMethodField()

def get_description(self, obj: Package):

obj.fetch_cache()
if not obj.latest_version:
return "Has Not Created A Version Yet"
versionSerializer = PackageVersionSerializer(obj.get_version(obj.latest_version.id_num))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add some error handling in case no versions have been created yet. Right now it will just crash the server.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually this serializer should be able to return something for packages even if they have no version, because the list packages endpoint should show every package even if no version has been created

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

return versionSerializer.data["version_description"]

def get_data(self, obj: Package):
obj.fetch_cache()
if not obj.latest_version:
return "Has Not Created A Version Yet"
package_items = obj.get_version(obj.latest_version.id_num).packageitem_set.all()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok when I wrote this line a few years ago I didn't realize that obj.latest_version.packageitem_set.all() is good enough.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this one, again please add handling for the case where no versions have been created yet

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

for file in package_items:
file_ext = os.path.splitext(file.file_name)[-1]
if(file.file_name == "article.aml"):
aml_data = file.data["content_rich"]["data"]
return {"article": aml_data}

def get_cached_article_preview(self, obj: Package):
obj.fetch_cache()
cached = obj.cached
for item in cached:
if(item["title"] == "article.aml"):
cached_article_preview = item["content_plain"]["raw"]
return cached_article_preview


class Meta:
model = Package
fields = (
"slug",
"description",
"metadata",
"data",
"cached_article_preview",
"last_fetched_date",
"package_set",
"latest_version",

)
read_only_fields = (
"description",
"metadata",
"data",
"cached_article_preview",
"last_fetched_date",
"package_set",
"latest_version",
)
validators = [
UniqueTogetherValidator(
queryset=Package.objects.all(), fields=("slug", "package_set")
)
]
46 changes: 43 additions & 3 deletions kerckhoff/packages/views.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
from multiprocessing import log_to_stderr
import os
from typing import List
import os
import json
from importlib_metadata import packages_distributions
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a bunch of unused imports here. I think again it's from the IDE

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed extra imports.

from rest_framework import mixins, viewsets, filters
from rest_framework.permissions import IsAuthenticated
from rest_framework.permissions import IsAuthenticated, IsAuthenticatedOrReadOnly
from rest_framework.decorators import action
from rest_framework.serializers import Serializer
from rest_framework.response import Response

from kerckhoff.integrations.serializers import IntegrationSerializer
from .tasks import sync_gdrive_task

from .models import PackageSet, Package
from .models import PackageSet, Package, PackageVersion, PackageItem
from .serializers import (
PackageSetSerializer,
PackageSerializer,
RetrievePackageSerializer,
PackageVersionSerializer,
CreatePackageVersionSerializer,
PackageSetDetailedSerializer,
PackageItemSerializer,
PackageInfoSerializer
)


Expand Down Expand Up @@ -80,7 +88,7 @@ class PackageViewSet(
):
"""
Updates and retrieves packages
"""
"""
def get_queryset(self):
return Package.objects.filter(package_set__slug=self.kwargs["package_set_slug"])

Expand Down Expand Up @@ -128,6 +136,8 @@ def retrieve(self, request, **kwargs):
)
response = serializer.data
return Response(response)




class PackageCreateAndListViewSet(
Expand All @@ -150,3 +160,33 @@ def perform_create(self, serializer):
lookup_value_regex = slug_with_dots
filter_backends = (filters.OrderingFilter,)
ordering_fields = ("slug", "last_fetched_date", "created_at", "updated_at")



# Public Package View set for External site Kerckhoff API

# mixins.ListModelMixin list out all packages in package set
# mixins.RetrieveModelMixin retrieves specific/individual package within the package set
class PublicPackageViewSet(viewsets.GenericViewSet, mixins.ListModelMixin, mixins.RetrieveModelMixin):
"""
List and retrieve packages for external site
"""

# Retrieve only the packages from the package set that has the same name/ slug as the defined package set name/slug in the url
def get_queryset(self):
# return package_set
return Package.objects.filter(package_set__slug=self.kwargs["package_set_slug"])


serializer_class = PackageInfoSerializer
permission_classes = (IsAuthenticatedOrReadOnly,)
# set slug as the lookup field so that we look up for packages in the package set with the same slug
lookup_field = "slug"
# verifies if the url slug is a valid slug and matches our valid slug format defined at the top of this file
lookup_value_regex = slug_with_dots






45 changes: 40 additions & 5 deletions kerckhoff/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
PackageSetCreateAndListViewSet,
PackageViewSet,
PackageCreateAndListViewSet,
PublicPackageViewSet
)
from .comments.views import CommentViewSet
from .integrations.views import IntegrationOAuthView
Expand All @@ -28,16 +29,47 @@
router.register(r"package-sets", PackageSetViewSet)
router.register(r"package-sets", PackageSetCreateAndListViewSet)

package_set_router = NestedSimpleRouter(router, r"package-sets", lookup="package_set")
# API Router for Public External Site
public_package_set_router = NestedSimpleRouter(
router,
r"package-sets",
lookup="package_set")

public_package_set_router.register(
r"packages",
PublicPackageViewSet,
base_name="public-package"
)



# To Internal Kerckhoff Frontend Site
package_set_router = NestedSimpleRouter(
router,
r"package-sets",
lookup="package_set")

package_set_router.register(
r"packages", PackageViewSet, base_name="package-sets_packages"
r"packages",
PackageViewSet,
base_name="package-generate_packages"
)

package_set_router.register(
r"packages", PackageCreateAndListViewSet, base_name="package-sets_packages"
r"packages",
PackageCreateAndListViewSet,
base_name="package-sets_packages"
)

package_router = NestedSimpleRouter(package_set_router, r"packages", lookup="package")
package_router.register(r"comments", CommentViewSet, base_name="comments")
package_router = NestedSimpleRouter(
package_set_router,
r"packages",
lookup="package")

package_router.register(
r"comments",
CommentViewSet,
base_name="comments")

schema_view = get_schema_view(
openapi.Info(
Expand Down Expand Up @@ -73,6 +105,9 @@
path("api/v1/", include(router.urls)),
path("api/v1/", include(package_set_router.urls)),
path("api/v1/", include(package_router.urls)),
# path for external site api
path("api/v1/public/",include(public_package_set_router.urls)),

path("api/v1/integrations/", IntegrationOAuthView.as_view()),
path("api-oauth/", include(auth_urlpatterns)),
path("api-token-auth/", views.obtain_auth_token),
Expand Down