diff --git a/NoobRPG/NoobRPG/urls.py b/NoobRPG/NoobRPG/urls.py index 5fde70d..cf7c7a5 100644 --- a/NoobRPG/NoobRPG/urls.py +++ b/NoobRPG/NoobRPG/urls.py @@ -4,6 +4,9 @@ urlpatterns = [ path('admin/', admin.site.urls), - path('entities/', include('entities.urls')), - path('locations/', include('locations.urls')), + path('api/v1/entities/', include('entities.urls')), + path('api/v1/items/', include('items.urls')), + path('api/v1/locations/', include('locations.urls')), + path('api/v1/rarity/', include('rarity.urls')), + path('api/v1/sellers_offers/', include('sellers_offers.urls')), ] diff --git a/NoobRPG/entities/tests.py b/NoobRPG/entities/tests.py index 5b08e31..e4990b4 100644 --- a/NoobRPG/entities/tests.py +++ b/NoobRPG/entities/tests.py @@ -30,7 +30,7 @@ def setUp(self): def test_npc_list_without_query_param(self): view = NPCsViewSet.as_view({'get': 'list'}) - request = self.factory.get('/entities/npcs/') + request = self.factory.get('/api/v1/entities/npcs/') force_authenticate(request, user=self.user) response = view(request) @@ -40,7 +40,7 @@ def test_npc_list_without_query_param(self): def test_npc_list_with_location_query_param(self): view = NPCsViewSet.as_view({'get': 'list'}) request = self.factory.get( - '/entities/npcs/?current_location__slug=forest', + '/api/v1/entities/npcs/?current_location__slug=forest', ) force_authenticate(request, user=self.user) response = view(request) @@ -52,7 +52,7 @@ def test_npc_list_with_location_query_param(self): def test_npc_list_with_nonexistent_location(self): view = NPCsViewSet.as_view({'get': 'list'}) request = self.factory.get( - '/entities/npcs/?current_location__slug=nonexistent', + '/api/v1/entities/npcs/?current_location__slug=nonexistent', ) force_authenticate(request, user=self.user) response = view(request) diff --git a/NoobRPG/items/models.py b/NoobRPG/items/models.py index 04406ef..cd7f28f 100644 --- a/NoobRPG/items/models.py +++ b/NoobRPG/items/models.py @@ -4,7 +4,18 @@ from rarity.models import Rarity +class ItemManager(models.Manager): + def all_fields(self) -> models.QuerySet: + queryset = self.get_queryset().select_related( + Items.rarity.field.name, + ) + return queryset.order_by( + Items.id.field.name, + ) + + class Items(models.Model): + objects = ItemManager() name = models.CharField( 'item name', max_length=100, diff --git a/NoobRPG/items/serializers.py b/NoobRPG/items/serializers.py new file mode 100644 index 0000000..6d8c5fa --- /dev/null +++ b/NoobRPG/items/serializers.py @@ -0,0 +1,30 @@ +__all__ = () + +from items.models import Items +from rest_framework import serializers + + +class ItemSerializer(serializers.HyperlinkedModelSerializer): + + class Meta: + model = Items + fields = [ + 'url', + Items.id.field.name, + Items.name.field.name, + Items.rarity.field.name, + Items.damage.field.name, + ] + + def build_field(self, field_name, info, model_class, nested_depth): + field_class, field_kwargs = super().build_field( + field_name, + info, + model_class, + nested_depth, + ) + + if field_name == 'url': + field_kwargs['view_name'] = 'items-detail' + + return field_class, field_kwargs diff --git a/NoobRPG/items/urls.py b/NoobRPG/items/urls.py new file mode 100644 index 0000000..b33083d --- /dev/null +++ b/NoobRPG/items/urls.py @@ -0,0 +1,11 @@ +from django.urls import include, path +from items import views +from rest_framework import routers + + +router = routers.DefaultRouter() +router.register(r'', views.ItemViewSet, basename='items') + +urlpatterns = [ + path('items/', include(router.urls)), +] diff --git a/NoobRPG/items/views.py b/NoobRPG/items/views.py new file mode 100644 index 0000000..04c770c --- /dev/null +++ b/NoobRPG/items/views.py @@ -0,0 +1,26 @@ +__all__ = () + +from core.functions import get_filterable_fields +from django.core.exceptions import FieldError +from items.models import Items +from items.serializers import ItemSerializer +from rest_framework import permissions, viewsets + + +class ItemViewSet(viewsets.ModelViewSet): + queryset = Items.objects.all_fields() + serializer_class = ItemSerializer + permission_classes = [permissions.IsAuthenticated] + + def get_queryset(self): + queryset = Items.objects.all_fields() + allowed_params = get_filterable_fields(Items, depth=1) + + for param, value in self.request.query_params.items(): + if param in allowed_params: + try: + queryset = queryset.filter(**{param: value}) + except (TypeError, ValueError, FieldError): + continue + + return queryset diff --git a/NoobRPG/locations/serializers.py b/NoobRPG/locations/serializers.py index 23b0a04..62436c5 100644 --- a/NoobRPG/locations/serializers.py +++ b/NoobRPG/locations/serializers.py @@ -8,7 +8,21 @@ class LocationSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Location fields = [ + 'url', Location.id.field.name, Location.name.field.name, Location.slug.field.name, ] + + def build_field(self, field_name, info, model_class, nested_depth): + field_class, field_kwargs = super().build_field( + field_name, + info, + model_class, + nested_depth, + ) + + if field_name == 'url': + field_kwargs['view_name'] = 'locations-detail' + + return field_class, field_kwargs diff --git a/NoobRPG/locations/urls.py b/NoobRPG/locations/urls.py index 6167687..e9982e5 100644 --- a/NoobRPG/locations/urls.py +++ b/NoobRPG/locations/urls.py @@ -4,7 +4,7 @@ router = routers.DefaultRouter() -router.register(r'locations', views.LocationViewSet) +router.register(r'', views.LocationViewSet, basename='location') urlpatterns = [ path('', include(router.urls)), diff --git a/NoobRPG/locations/views.py b/NoobRPG/locations/views.py index 6f2fe81..22f8090 100644 --- a/NoobRPG/locations/views.py +++ b/NoobRPG/locations/views.py @@ -1,5 +1,7 @@ __all__ = () +from core.functions import get_filterable_fields +from django.core.exceptions import FieldError from locations.models import Location from locations.serializers import LocationSerializer from rest_framework import permissions, viewsets @@ -9,3 +11,16 @@ class LocationViewSet(viewsets.ModelViewSet): queryset = Location.objects.all() serializer_class = LocationSerializer permission_classes = [permissions.IsAuthenticated] + + def get_queryset(self): + queryset = Location.objects.all() + allowed_params = get_filterable_fields(Location, depth=1) + + for param, value in self.request.query_params.items(): + if param in allowed_params: + try: + queryset = queryset.filter(**{param: value}) + except (TypeError, ValueError, FieldError): + continue + + return queryset diff --git a/NoobRPG/rarity/serializers.py b/NoobRPG/rarity/serializers.py new file mode 100644 index 0000000..9878550 --- /dev/null +++ b/NoobRPG/rarity/serializers.py @@ -0,0 +1,28 @@ +__all__ = () + +from rarity.models import Rarity +from rest_framework import serializers + + +class RaritySerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = Rarity + fields = [ + 'url', + Rarity.id.field.name, + Rarity.name.field.name, + Rarity.slug.field.name, + ] + + def build_field(self, field_name, info, model_class, nested_depth): + field_class, field_kwargs = super().build_field( + field_name, + info, + model_class, + nested_depth, + ) + + if field_name == 'url': + field_kwargs['view_name'] = 'rarity-detail' + + return field_class, field_kwargs diff --git a/NoobRPG/rarity/urls.py b/NoobRPG/rarity/urls.py new file mode 100644 index 0000000..22a4afb --- /dev/null +++ b/NoobRPG/rarity/urls.py @@ -0,0 +1,11 @@ +from django.urls import include, path +from rarity import views +from rest_framework import routers + + +router = routers.DefaultRouter() +router.register(r'', views.RarityViewSet, basename='rarity') + +urlpatterns = [ + path('', include(router.urls)), +] diff --git a/NoobRPG/rarity/views.py b/NoobRPG/rarity/views.py new file mode 100644 index 0000000..370dc12 --- /dev/null +++ b/NoobRPG/rarity/views.py @@ -0,0 +1,26 @@ +__all__ = () + +from core.functions import get_filterable_fields +from django.core.exceptions import FieldError +from rarity.models import Rarity +from rarity.serializers import RaritySerializer +from rest_framework import permissions, viewsets + + +class RarityViewSet(viewsets.ModelViewSet): + queryset = Rarity.objects.all() + serializer_class = RaritySerializer + permission_classes = [permissions.IsAuthenticated] + + def get_queryset(self): + queryset = Rarity.objects.all() + allowed_params = get_filterable_fields(Rarity, depth=1) + + for param, value in self.request.query_params.items(): + if param in allowed_params: + try: + queryset = queryset.filter(**{param: value}) + except (TypeError, ValueError, FieldError): + continue + + return queryset diff --git a/NoobRPG/sellers_offers/models.py b/NoobRPG/sellers_offers/models.py index 7ef3545..9ded97f 100644 --- a/NoobRPG/sellers_offers/models.py +++ b/NoobRPG/sellers_offers/models.py @@ -4,7 +4,18 @@ from items.models import Items +class SellerOfferManager(models.Manager): + def all_fields(self) -> models.QuerySet: + queryset = self.get_queryset().select_related( + SellerOffer.item.field.name, + ) + return queryset.order_by( + SellerOffer.id.field.name, + ) + + class SellerOffer(models.Model): + objects = SellerOfferManager() item = models.ForeignKey( Items, on_delete=models.CASCADE, diff --git a/NoobRPG/sellers_offers/serializers.py b/NoobRPG/sellers_offers/serializers.py new file mode 100644 index 0000000..12352e2 --- /dev/null +++ b/NoobRPG/sellers_offers/serializers.py @@ -0,0 +1,28 @@ +__all__ = () + +from rest_framework import serializers +from sellers_offers.models import SellerOffer + + +class SellerOfferSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = SellerOffer + fields = [ + 'url', + SellerOffer.id.field.name, + SellerOffer.item.field.name, + SellerOffer.cost.field.name, + ] + + def build_field(self, field_name, info, model_class, nested_depth): + field_class, field_kwargs = super().build_field( + field_name, + info, + model_class, + nested_depth, + ) + + if field_name == 'url': + field_kwargs['view_name'] = 'sellers-offers-detail' + + return field_class, field_kwargs diff --git a/NoobRPG/sellers_offers/urls.py b/NoobRPG/sellers_offers/urls.py new file mode 100644 index 0000000..b3df250 --- /dev/null +++ b/NoobRPG/sellers_offers/urls.py @@ -0,0 +1,11 @@ +from django.urls import include, path +from rest_framework import routers +from sellers_offers import views + + +router = routers.DefaultRouter() +router.register(r'', views.SellerOfferViewSet, basename='sellers-offers') + +urlpatterns = [ + path('', include(router.urls)), +] diff --git a/NoobRPG/sellers_offers/views.py b/NoobRPG/sellers_offers/views.py new file mode 100644 index 0000000..0022c8c --- /dev/null +++ b/NoobRPG/sellers_offers/views.py @@ -0,0 +1,26 @@ +__all__ = () + +from core.functions import get_filterable_fields +from django.core.exceptions import FieldError +from rest_framework import permissions, viewsets +from sellers_offers.models import SellerOffer +from sellers_offers.serializers import SellerOfferSerializer + + +class SellerOfferViewSet(viewsets.ModelViewSet): + queryset = SellerOffer.objects.all_fields() + serializer_class = SellerOfferSerializer + permission_classes = [permissions.IsAuthenticated] + + def get_queryset(self): + queryset = SellerOffer.objects.all_fields() + allowed_params = get_filterable_fields(SellerOffer, depth=1) + + for param, value in self.request.query_params.items(): + if param in allowed_params: + try: + queryset = queryset.filter(**{param: value}) + except (TypeError, ValueError, FieldError): + continue + + return queryset