From 7eb98f1554ac964321f5a1f74e50ee94671722cc Mon Sep 17 00:00:00 2001 From: jaykayudo Date: Fri, 4 Apr 2025 05:52:44 +0100 Subject: [PATCH] feat: implement accepted nfts feature --- core/serializers.py | 16 +++++++++++++++ core/tests/__init__.py | 0 core/tests/factories.py | 16 +++++++++++++++ core/tests/test_accepted_nfts.py | 25 +++++++++++++++++++++++ core/urls.py | 10 +++++++++- core/views.py | 8 ++++++++ poetry.lock | 34 +++++++++++++++++++++++++++++++- pyproject.toml | 1 + 8 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 core/tests/__init__.py create mode 100644 core/tests/factories.py create mode 100644 core/tests/test_accepted_nfts.py diff --git a/core/serializers.py b/core/serializers.py index e69de29..d8d8a6d 100644 --- a/core/serializers.py +++ b/core/serializers.py @@ -0,0 +1,16 @@ +from rest_framework import serializers + +from . import models + + +class AcceptedNFTSerializer(serializers.ModelSerializer): + listings_count = serializers.SerializerMethodField() + + class Meta: + model = models.AcceptedNFT + fields = ["name", "contract_address", "listings_count"] + + def get_listings_count(self, obj: models.AcceptedNFT) -> int: + return models.Listing.objects.filter( + nft_contract_address=obj.contract_address + ).count() diff --git a/core/tests/__init__.py b/core/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/core/tests/factories.py b/core/tests/factories.py new file mode 100644 index 0000000..faf1878 --- /dev/null +++ b/core/tests/factories.py @@ -0,0 +1,16 @@ +import random + +import factory + +from core import models + + +class AcceptedNFTFactory(factory.django.DjangoModelFactory): + class Meta: + model = models.AcceptedNFT + + name = factory.Faker("word") + + @factory.lazy_attribute + def contract_address(self): + return "0x" + "".join(random.choices("0123456789abcdef", k=60)) diff --git a/core/tests/test_accepted_nfts.py b/core/tests/test_accepted_nfts.py new file mode 100644 index 0000000..58f098b --- /dev/null +++ b/core/tests/test_accepted_nfts.py @@ -0,0 +1,25 @@ +from django.urls import reverse +from rest_framework.test import APITestCase + +from . import factories + + +class TestAcceptedNFTListAPIView(APITestCase): + def setUp(self): + self.url = reverse("accepted-nfts-list-view") + + def test_accepted_nft_list_view_successful(self): + response = self.client.get(self.url) + self.assertEqual(response.status_code, 200) + + def test_accepted_nft_list_view_with_data(self): + self._generate_data() + response = self.client.get(self.url) + self.assertEqual(response.status_code, 200) + data = response.json() + self.assertEqual(len(data), 3) + + def _generate_data(self): + factories.AcceptedNFTFactory() + factories.AcceptedNFTFactory() + factories.AcceptedNFTFactory() diff --git a/core/urls.py b/core/urls.py index ab25d75..19a6994 100644 --- a/core/urls.py +++ b/core/urls.py @@ -1,3 +1,11 @@ from django.urls import path # noqa -urlpatterns = [] +from . import views + +urlpatterns = [ + path( + "accepted-nfts/", + views.AcceptedNFTListAPIView.as_view(), + name="accepted-nfts-list-view", + ) +] diff --git a/core/views.py b/core/views.py index 60f00ef..7a53eb4 100644 --- a/core/views.py +++ b/core/views.py @@ -1 +1,9 @@ # Create your views here. +from rest_framework.generics import ListAPIView + +from . import models, serializers + + +class AcceptedNFTListAPIView(ListAPIView): + queryset = models.AcceptedNFT.objects.all().order_by("name") + serializer_class = serializers.AcceptedNFTSerializer diff --git a/poetry.lock b/poetry.lock index 6580e36..7f72692 100644 --- a/poetry.lock +++ b/poetry.lock @@ -734,6 +734,38 @@ dev = ["build (>=0.9.0)", "bump-my-version (>=0.19.0)", "eth-hash[pycryptodome]" docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=24,<25)"] test = ["hypothesis (>=4.43.0)", "mypy (==1.10.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] +[[package]] +name = "factory-boy" +version = "3.3.0" +description = "A versatile test fixtures replacement based on thoughtbot's factory_bot for Ruby." +optional = false +python-versions = ">=3.7" +files = [ + {file = "factory_boy-3.3.0-py2.py3-none-any.whl", hash = "sha256:a2cdbdb63228177aa4f1c52f4b6d83fab2b8623bf602c7dedd7eb83c0f69c04c"}, + {file = "factory_boy-3.3.0.tar.gz", hash = "sha256:bc76d97d1a65bbd9842a6d722882098eb549ec8ee1081f9fb2e8ff29f0c300f1"}, +] + +[package.dependencies] +Faker = ">=0.7.0" + +[package.extras] +dev = ["Django", "Pillow", "SQLAlchemy", "coverage", "flake8", "isort", "mongoengine", "sqlalchemy-utils", "tox", "wheel (>=0.32.0)", "zest.releaser[recommended]"] +doc = ["Sphinx", "sphinx-rtd-theme", "sphinxcontrib-spelling"] + +[[package]] +name = "faker" +version = "37.1.0" +description = "Faker is a Python package that generates fake data for you." +optional = false +python-versions = ">=3.9" +files = [ + {file = "faker-37.1.0-py3-none-any.whl", hash = "sha256:dc2f730be71cb770e9c715b13374d80dbcee879675121ab51f9683d262ae9a1c"}, + {file = "faker-37.1.0.tar.gz", hash = "sha256:ad9dc66a3b84888b837ca729e85299a96b58fdaef0323ed0baace93c9614af06"}, +] + +[package.dependencies] +tzdata = "*" + [[package]] name = "filelock" version = "3.18.0" @@ -1928,4 +1960,4 @@ propcache = ">=0.2.0" [metadata] lock-version = "2.0" python-versions = ">=3.12,<3.13" -content-hash = "bf8257a3ee93cefede742db40fe2c50b4d0f1cc579ef823a13ac0664ea27aade" +content-hash = "1c8893ea5fbe5ffc975b9a00bfcbae00bfee7084e17a97218fce74c9051c2016" diff --git a/pyproject.toml b/pyproject.toml index 949b6bb..d11f23c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,6 +17,7 @@ pre-commit = "^4.1.0" dj-database-url = "^2.3.0" django-cors-headers = "^4.7.0" psycopg2-binary = "^2.9.10" +factory-boy = "3.3.0" [tool.poetry.group.dev.dependencies] black = "^23.9.1"