Merge pull request 'Attributes model added.' (#1) from feat/attributes-model into main
Reviewed-on: #1
This commit is contained in:
1
=4.12
Normal file
1
=4.12
Normal file
@@ -0,0 +1 @@
|
||||
Requirement already satisfied: typing_extensions in ./.venv/lib/python3.12/site-packages (4.12.2)
|
||||
@@ -179,6 +179,9 @@ REST_FRAMEWORK = {
|
||||
"user": "60/min",
|
||||
},
|
||||
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
|
||||
"DEFAULT_AUTHENTICATION_CLASSES": [
|
||||
"rest_framework.authentication.TokenAuthentication",
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -40,9 +40,8 @@ def sms_code(test_user):
|
||||
def test_reg_view(api_client):
|
||||
data = {
|
||||
"phone": "998999999991",
|
||||
"first_name": "John",
|
||||
"last_name": "Doe",
|
||||
"password": "password",
|
||||
"confirm_password":"password"
|
||||
}
|
||||
with patch.object(SmsService, "send_confirm", return_value=True):
|
||||
response = api_client.post(reverse("auth-register"), data=data)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import uuid
|
||||
from typing import Type
|
||||
|
||||
from rest_framework.authentication import TokenAuthentication
|
||||
|
||||
from core.services import UserService, SmsService
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
@@ -186,6 +188,7 @@ class MeView(BaseViewSetMixin, GenericViewSet, UserService):
|
||||
class ChangePasswordView(BaseViewSetMixin, GenericViewSet):
|
||||
serializer_class = ChangePasswordSerializer
|
||||
permission_classes = (IsAuthenticated,)
|
||||
authentication_classes = [TokenAuthentication]
|
||||
|
||||
@extend_schema(
|
||||
request=serializer_class,
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
from .attributes import * # noqa
|
||||
|
||||
28
core/apps/api/admin/attributes.py
Normal file
28
core/apps/api/admin/attributes.py
Normal file
@@ -0,0 +1,28 @@
|
||||
from django.contrib import admin
|
||||
from unfold.admin import ModelAdmin
|
||||
|
||||
from core.apps.api.models import ColorModel, ProductlikeModel, SizeModel
|
||||
|
||||
|
||||
@admin.register(SizeModel)
|
||||
class SizeAdmin(ModelAdmin):
|
||||
list_display = (
|
||||
"id",
|
||||
"__str__",
|
||||
)
|
||||
|
||||
|
||||
@admin.register(ColorModel)
|
||||
class ColorAdmin(ModelAdmin):
|
||||
list_display = (
|
||||
"id",
|
||||
"__str__",
|
||||
)
|
||||
|
||||
|
||||
@admin.register(ProductlikeModel)
|
||||
class ProductlikeAdmin(ModelAdmin):
|
||||
list_display = (
|
||||
"id",
|
||||
"__str__",
|
||||
)
|
||||
1
core/apps/api/filters/__init__.py
Normal file
1
core/apps/api/filters/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .attributes import * # noqa
|
||||
33
core/apps/api/filters/attributes.py
Normal file
33
core/apps/api/filters/attributes.py
Normal file
@@ -0,0 +1,33 @@
|
||||
from django_filters import rest_framework as filters
|
||||
|
||||
from core.apps.api.models import ColorModel, ProductlikeModel, SizeModel
|
||||
|
||||
|
||||
class SizeFilter(filters.FilterSet):
|
||||
# name = filters.CharFilter(field_name="name", lookup_expr="icontains")
|
||||
|
||||
class Meta:
|
||||
model = SizeModel
|
||||
fields = [
|
||||
"name",
|
||||
]
|
||||
|
||||
|
||||
class ColorFilter(filters.FilterSet):
|
||||
# name = filters.CharFilter(field_name="name", lookup_expr="icontains")
|
||||
|
||||
class Meta:
|
||||
model = ColorModel
|
||||
fields = [
|
||||
"name",
|
||||
]
|
||||
|
||||
|
||||
class ProductlikeFilter(filters.FilterSet):
|
||||
# name = filters.CharFilter(field_name="name", lookup_expr="icontains")
|
||||
|
||||
class Meta:
|
||||
model = ProductlikeModel
|
||||
fields = [
|
||||
"name",
|
||||
]
|
||||
1
core/apps/api/forms/__init__.py
Normal file
1
core/apps/api/forms/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .attributes import * # noqa
|
||||
24
core/apps/api/forms/attributes.py
Normal file
24
core/apps/api/forms/attributes.py
Normal file
@@ -0,0 +1,24 @@
|
||||
from django import forms
|
||||
|
||||
from core.apps.api.models import ColorModel, ProductlikeModel, SizeModel
|
||||
|
||||
|
||||
class SizeForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = SizeModel
|
||||
fields = "__all__"
|
||||
|
||||
|
||||
class ColorForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = ColorModel
|
||||
fields = "__all__"
|
||||
|
||||
|
||||
class ProductlikeForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = ProductlikeModel
|
||||
fields = "__all__"
|
||||
57
core/apps/api/migrations/0001_initial.py
Normal file
57
core/apps/api/migrations/0001_initial.py
Normal file
@@ -0,0 +1,57 @@
|
||||
# Generated by Django 5.2.7 on 2026-03-09 07:48
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ColorModel',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('updated_at', models.DateTimeField(auto_now=True)),
|
||||
('name', models.CharField(max_length=255, verbose_name='name')),
|
||||
('code', models.CharField(max_length=255, verbose_name='name')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'ColorModel',
|
||||
'verbose_name_plural': 'ColorModels',
|
||||
'db_table': 'color',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ProductlikeModel',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('updated_at', models.DateTimeField(auto_now=True)),
|
||||
('name', models.CharField(max_length=255, verbose_name='name')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'ProductlikeModel',
|
||||
'verbose_name_plural': 'ProductlikeModels',
|
||||
'db_table': 'productlike',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SizeModel',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('updated_at', models.DateTimeField(auto_now=True)),
|
||||
('name', models.CharField(max_length=255, verbose_name='name')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'SizeModel',
|
||||
'verbose_name_plural': 'SizeModels',
|
||||
'db_table': 'size',
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1 @@
|
||||
from .attributes import * # noqa
|
||||
|
||||
55
core/apps/api/models/attributes.py
Normal file
55
core/apps/api/models/attributes.py
Normal file
@@ -0,0 +1,55 @@
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django_core.models import AbstractBaseModel
|
||||
from model_bakery import baker
|
||||
|
||||
|
||||
class SizeModel(AbstractBaseModel):
|
||||
|
||||
name = models.CharField(verbose_name=_("name"), max_length=255)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.pk)
|
||||
|
||||
@classmethod
|
||||
def _baker(cls):
|
||||
return baker.make(cls)
|
||||
|
||||
class Meta:
|
||||
db_table = "size"
|
||||
verbose_name = _("SizeModel")
|
||||
verbose_name_plural = _("SizeModels")
|
||||
|
||||
|
||||
class ColorModel(AbstractBaseModel):
|
||||
|
||||
name = models.CharField(verbose_name=_("name"), max_length=255)
|
||||
code = models.CharField(verbose_name=_("name"), max_length=255)
|
||||
def __str__(self):
|
||||
return str(self.pk)
|
||||
|
||||
@classmethod
|
||||
def _baker(cls):
|
||||
return baker.make(cls)
|
||||
|
||||
class Meta:
|
||||
db_table = "color"
|
||||
verbose_name = _("ColorModel")
|
||||
verbose_name_plural = _("ColorModels")
|
||||
|
||||
|
||||
class ProductlikeModel(AbstractBaseModel):
|
||||
|
||||
name = models.CharField(verbose_name=_("name"), max_length=255)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.pk)
|
||||
|
||||
@classmethod
|
||||
def _baker(cls):
|
||||
return baker.make(cls)
|
||||
|
||||
class Meta:
|
||||
db_table = "productlike"
|
||||
verbose_name = _("ProductlikeModel")
|
||||
verbose_name_plural = _("ProductlikeModels")
|
||||
1
core/apps/api/permissions/__init__.py
Normal file
1
core/apps/api/permissions/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .attributes import * # noqa
|
||||
34
core/apps/api/permissions/attributes.py
Normal file
34
core/apps/api/permissions/attributes.py
Normal file
@@ -0,0 +1,34 @@
|
||||
from rest_framework import permissions
|
||||
|
||||
|
||||
class SizePermission(permissions.BasePermission):
|
||||
|
||||
def __init__(self) -> None: ...
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
return self
|
||||
|
||||
def has_permission(self, request, view):
|
||||
return True
|
||||
|
||||
|
||||
class ColorPermission(permissions.BasePermission):
|
||||
|
||||
def __init__(self) -> None: ...
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
return self
|
||||
|
||||
def has_permission(self, request, view):
|
||||
return True
|
||||
|
||||
|
||||
class ProductlikePermission(permissions.BasePermission):
|
||||
|
||||
def __init__(self) -> None: ...
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
return self
|
||||
|
||||
def has_permission(self, request, view):
|
||||
return True
|
||||
@@ -0,0 +1 @@
|
||||
from .attributes import * # noqa
|
||||
|
||||
3
core/apps/api/serializers/attributes/__init__.py
Normal file
3
core/apps/api/serializers/attributes/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from .color import * # noqa
|
||||
from .productlike import * # noqa
|
||||
from .size import * # noqa
|
||||
28
core/apps/api/serializers/attributes/color.py
Normal file
28
core/apps/api/serializers/attributes/color.py
Normal file
@@ -0,0 +1,28 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from core.apps.api.models import ColorModel
|
||||
|
||||
|
||||
class BaseColorSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = ColorModel
|
||||
fields = [
|
||||
"id",
|
||||
"name",
|
||||
]
|
||||
|
||||
|
||||
class ListColorSerializer(BaseColorSerializer):
|
||||
class Meta(BaseColorSerializer.Meta): ...
|
||||
|
||||
|
||||
class RetrieveColorSerializer(BaseColorSerializer):
|
||||
class Meta(BaseColorSerializer.Meta): ...
|
||||
|
||||
|
||||
class CreateColorSerializer(BaseColorSerializer):
|
||||
class Meta(BaseColorSerializer.Meta):
|
||||
fields = [
|
||||
"id",
|
||||
"name",
|
||||
]
|
||||
28
core/apps/api/serializers/attributes/productlike.py
Normal file
28
core/apps/api/serializers/attributes/productlike.py
Normal file
@@ -0,0 +1,28 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from core.apps.api.models import ProductlikeModel
|
||||
|
||||
|
||||
class BaseProductlikeSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = ProductlikeModel
|
||||
fields = [
|
||||
"id",
|
||||
"name",
|
||||
]
|
||||
|
||||
|
||||
class ListProductlikeSerializer(BaseProductlikeSerializer):
|
||||
class Meta(BaseProductlikeSerializer.Meta): ...
|
||||
|
||||
|
||||
class RetrieveProductlikeSerializer(BaseProductlikeSerializer):
|
||||
class Meta(BaseProductlikeSerializer.Meta): ...
|
||||
|
||||
|
||||
class CreateProductlikeSerializer(BaseProductlikeSerializer):
|
||||
class Meta(BaseProductlikeSerializer.Meta):
|
||||
fields = [
|
||||
"id",
|
||||
"name",
|
||||
]
|
||||
28
core/apps/api/serializers/attributes/size.py
Normal file
28
core/apps/api/serializers/attributes/size.py
Normal file
@@ -0,0 +1,28 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from core.apps.api.models import SizeModel
|
||||
|
||||
|
||||
class BaseSizeSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = SizeModel
|
||||
fields = [
|
||||
"id",
|
||||
"name",
|
||||
]
|
||||
|
||||
|
||||
class ListSizeSerializer(BaseSizeSerializer):
|
||||
class Meta(BaseSizeSerializer.Meta): ...
|
||||
|
||||
|
||||
class RetrieveSizeSerializer(BaseSizeSerializer):
|
||||
class Meta(BaseSizeSerializer.Meta): ...
|
||||
|
||||
|
||||
class CreateSizeSerializer(BaseSizeSerializer):
|
||||
class Meta(BaseSizeSerializer.Meta):
|
||||
fields = [
|
||||
"id",
|
||||
"name",
|
||||
]
|
||||
1
core/apps/api/signals/__init__.py
Normal file
1
core/apps/api/signals/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .attributes import * # noqa
|
||||
16
core/apps/api/signals/attributes.py
Normal file
16
core/apps/api/signals/attributes.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
|
||||
from core.apps.api.models import ColorModel, ProductlikeModel, SizeModel
|
||||
|
||||
|
||||
@receiver(post_save, sender=SizeModel)
|
||||
def SizeSignal(sender, instance, created, **kwargs): ...
|
||||
|
||||
|
||||
@receiver(post_save, sender=ColorModel)
|
||||
def ColorSignal(sender, instance, created, **kwargs): ...
|
||||
|
||||
|
||||
@receiver(post_save, sender=ProductlikeModel)
|
||||
def ProductlikeSignal(sender, instance, created, **kwargs): ...
|
||||
@@ -0,0 +1 @@
|
||||
from .attributes import * # noqa
|
||||
|
||||
3
core/apps/api/tests/attributes/__init__.py
Normal file
3
core/apps/api/tests/attributes/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from .test_color import * # noqa
|
||||
from .test_productlike import * # noqa
|
||||
from .test_size import * # noqa
|
||||
101
core/apps/api/tests/attributes/test_color.py
Normal file
101
core/apps/api/tests/attributes/test_color.py
Normal file
@@ -0,0 +1,101 @@
|
||||
import pytest
|
||||
from django.urls import reverse
|
||||
from rest_framework.test import APIClient
|
||||
|
||||
from core.apps.api.models import ColorModel
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def instance(db):
|
||||
return ColorModel._baker()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def api_client(instance):
|
||||
client = APIClient()
|
||||
##client.force_authenticate(user=instance.user)
|
||||
return client, instance
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def data(api_client):
|
||||
client, instance = api_client
|
||||
return (
|
||||
{
|
||||
"list": reverse("color-list"),
|
||||
"retrieve": reverse("color-detail", kwargs={"pk": instance.pk}),
|
||||
"retrieve-not-found": reverse("color-detail", kwargs={"pk": 1000}),
|
||||
},
|
||||
client,
|
||||
instance,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_list(data):
|
||||
urls, client, _ = data
|
||||
response = client.get(urls["list"])
|
||||
data_resp = response.json()
|
||||
assert response.status_code == 200
|
||||
assert data_resp["status"] is True
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_retrieve(data):
|
||||
urls, client, _ = data
|
||||
response = client.get(urls["retrieve"])
|
||||
data_resp = response.json()
|
||||
assert response.status_code == 200
|
||||
assert data_resp["status"] is True
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_retrieve_not_found(data):
|
||||
urls, client, _ = data
|
||||
response = client.get(urls["retrieve-not-found"])
|
||||
data_resp = response.json()
|
||||
assert response.status_code == 404
|
||||
assert data_resp["status"] is False
|
||||
|
||||
|
||||
# @pytest.mark.django_db
|
||||
# def test_create(data):
|
||||
# urls, client, _ = data
|
||||
# response = client.post(urls["list"], data={"name": "test"})
|
||||
# assert response.json()["status"] is True
|
||||
# assert response.status_code == 201
|
||||
|
||||
|
||||
# @pytest.mark.django_db
|
||||
# def test_update(data):
|
||||
# urls, client, _ = data
|
||||
# response = client.patch(urls["retrieve"], data={"name": "updated"})
|
||||
# assert response.json()["status"] is True
|
||||
# assert response.status_code == 200
|
||||
#
|
||||
# # verify updated value
|
||||
# response = client.get(urls["retrieve"])
|
||||
# assert response.json()["status"] is True
|
||||
# assert response.status_code == 200
|
||||
# assert response.json()["data"]["name"] == "updated"
|
||||
|
||||
|
||||
# @pytest.mark.django_db
|
||||
# def test_partial_update():
|
||||
# urls, client, _ = data
|
||||
# response = client.patch(urls["retrieve"], data={"name": "updated"})
|
||||
# assert response.json()["status"] is True
|
||||
# assert response.status_code == 200
|
||||
#
|
||||
# # verify updated value
|
||||
# response = client.get(urls["retrieve"])
|
||||
# assert response.json()["status"] is True
|
||||
# assert response.status_code == 200
|
||||
# assert response.json()["data"]["name"] == "updated"
|
||||
|
||||
|
||||
# @pytest.mark.django_db
|
||||
# def test_destroy(data):
|
||||
# urls, client, _ = data
|
||||
# response = client.delete(urls["retrieve"])
|
||||
# assert response.status_code == 204
|
||||
101
core/apps/api/tests/attributes/test_productlike.py
Normal file
101
core/apps/api/tests/attributes/test_productlike.py
Normal file
@@ -0,0 +1,101 @@
|
||||
import pytest
|
||||
from django.urls import reverse
|
||||
from rest_framework.test import APIClient
|
||||
|
||||
from core.apps.api.models import ProductlikeModel
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def instance(db):
|
||||
return ProductlikeModel._baker()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def api_client(instance):
|
||||
client = APIClient()
|
||||
##client.force_authenticate(user=instance.user)
|
||||
return client, instance
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def data(api_client):
|
||||
client, instance = api_client
|
||||
return (
|
||||
{
|
||||
"list": reverse("productlike-list"),
|
||||
"retrieve": reverse("productlike-detail", kwargs={"pk": instance.pk}),
|
||||
"retrieve-not-found": reverse("productlike-detail", kwargs={"pk": 1000}),
|
||||
},
|
||||
client,
|
||||
instance,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_list(data):
|
||||
urls, client, _ = data
|
||||
response = client.get(urls["list"])
|
||||
data_resp = response.json()
|
||||
assert response.status_code == 200
|
||||
assert data_resp["status"] is True
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_retrieve(data):
|
||||
urls, client, _ = data
|
||||
response = client.get(urls["retrieve"])
|
||||
data_resp = response.json()
|
||||
assert response.status_code == 200
|
||||
assert data_resp["status"] is True
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_retrieve_not_found(data):
|
||||
urls, client, _ = data
|
||||
response = client.get(urls["retrieve-not-found"])
|
||||
data_resp = response.json()
|
||||
assert response.status_code == 404
|
||||
assert data_resp["status"] is False
|
||||
|
||||
|
||||
# @pytest.mark.django_db
|
||||
# def test_create(data):
|
||||
# urls, client, _ = data
|
||||
# response = client.post(urls["list"], data={"name": "test"})
|
||||
# assert response.json()["status"] is True
|
||||
# assert response.status_code == 201
|
||||
|
||||
|
||||
# @pytest.mark.django_db
|
||||
# def test_update(data):
|
||||
# urls, client, _ = data
|
||||
# response = client.patch(urls["retrieve"], data={"name": "updated"})
|
||||
# assert response.json()["status"] is True
|
||||
# assert response.status_code == 200
|
||||
#
|
||||
# # verify updated value
|
||||
# response = client.get(urls["retrieve"])
|
||||
# assert response.json()["status"] is True
|
||||
# assert response.status_code == 200
|
||||
# assert response.json()["data"]["name"] == "updated"
|
||||
|
||||
|
||||
# @pytest.mark.django_db
|
||||
# def test_partial_update():
|
||||
# urls, client, _ = data
|
||||
# response = client.patch(urls["retrieve"], data={"name": "updated"})
|
||||
# assert response.json()["status"] is True
|
||||
# assert response.status_code == 200
|
||||
#
|
||||
# # verify updated value
|
||||
# response = client.get(urls["retrieve"])
|
||||
# assert response.json()["status"] is True
|
||||
# assert response.status_code == 200
|
||||
# assert response.json()["data"]["name"] == "updated"
|
||||
|
||||
|
||||
# @pytest.mark.django_db
|
||||
# def test_destroy(data):
|
||||
# urls, client, _ = data
|
||||
# response = client.delete(urls["retrieve"])
|
||||
# assert response.status_code == 204
|
||||
101
core/apps/api/tests/attributes/test_size.py
Normal file
101
core/apps/api/tests/attributes/test_size.py
Normal file
@@ -0,0 +1,101 @@
|
||||
import pytest
|
||||
from django.urls import reverse
|
||||
from rest_framework.test import APIClient
|
||||
|
||||
from core.apps.api.models import SizeModel
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def instance(db):
|
||||
return SizeModel._baker()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def api_client(instance):
|
||||
client = APIClient()
|
||||
##client.force_authenticate(user=instance.user)
|
||||
return client, instance
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def data(api_client):
|
||||
client, instance = api_client
|
||||
return (
|
||||
{
|
||||
"list": reverse("size-list"),
|
||||
"retrieve": reverse("size-detail", kwargs={"pk": instance.pk}),
|
||||
"retrieve-not-found": reverse("size-detail", kwargs={"pk": 1000}),
|
||||
},
|
||||
client,
|
||||
instance,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_list(data):
|
||||
urls, client, _ = data
|
||||
response = client.get(urls["list"])
|
||||
data_resp = response.json()
|
||||
assert response.status_code == 200
|
||||
assert data_resp["status"] is True
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_retrieve(data):
|
||||
urls, client, _ = data
|
||||
response = client.get(urls["retrieve"])
|
||||
data_resp = response.json()
|
||||
assert response.status_code == 200
|
||||
assert data_resp["status"] is True
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_retrieve_not_found(data):
|
||||
urls, client, _ = data
|
||||
response = client.get(urls["retrieve-not-found"])
|
||||
data_resp = response.json()
|
||||
assert response.status_code == 404
|
||||
assert data_resp["status"] is False
|
||||
|
||||
|
||||
# @pytest.mark.django_db
|
||||
# def test_create(data):
|
||||
# urls, client, _ = data
|
||||
# response = client.post(urls["list"], data={"name": "test"})
|
||||
# assert response.json()["status"] is True
|
||||
# assert response.status_code == 201
|
||||
|
||||
|
||||
# @pytest.mark.django_db
|
||||
# def test_update(data):
|
||||
# urls, client, _ = data
|
||||
# response = client.patch(urls["retrieve"], data={"name": "updated"})
|
||||
# assert response.json()["status"] is True
|
||||
# assert response.status_code == 200
|
||||
#
|
||||
# # verify updated value
|
||||
# response = client.get(urls["retrieve"])
|
||||
# assert response.json()["status"] is True
|
||||
# assert response.status_code == 200
|
||||
# assert response.json()["data"]["name"] == "updated"
|
||||
|
||||
|
||||
# @pytest.mark.django_db
|
||||
# def test_partial_update():
|
||||
# urls, client, _ = data
|
||||
# response = client.patch(urls["retrieve"], data={"name": "updated"})
|
||||
# assert response.json()["status"] is True
|
||||
# assert response.status_code == 200
|
||||
#
|
||||
# # verify updated value
|
||||
# response = client.get(urls["retrieve"])
|
||||
# assert response.json()["status"] is True
|
||||
# assert response.status_code == 200
|
||||
# assert response.json()["data"]["name"] == "updated"
|
||||
|
||||
|
||||
# @pytest.mark.django_db
|
||||
# def test_destroy(data):
|
||||
# urls, client, _ = data
|
||||
# response = client.delete(urls["retrieve"])
|
||||
# assert response.status_code == 204
|
||||
1
core/apps/api/translation/__init__.py
Normal file
1
core/apps/api/translation/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .attributes import * # noqa
|
||||
18
core/apps/api/translation/attributes.py
Normal file
18
core/apps/api/translation/attributes.py
Normal file
@@ -0,0 +1,18 @@
|
||||
from modeltranslation.translator import TranslationOptions, register
|
||||
|
||||
from core.apps.api.models import ColorModel, ProductlikeModel, SizeModel
|
||||
|
||||
|
||||
@register(SizeModel)
|
||||
class SizeTranslation(TranslationOptions):
|
||||
fields = []
|
||||
|
||||
|
||||
@register(ColorModel)
|
||||
class ColorTranslation(TranslationOptions):
|
||||
fields = []
|
||||
|
||||
|
||||
@register(ProductlikeModel)
|
||||
class ProductlikeTranslation(TranslationOptions):
|
||||
fields = []
|
||||
@@ -1,9 +1,10 @@
|
||||
from django.urls import path, include
|
||||
from django.urls import include, path
|
||||
from rest_framework.routers import DefaultRouter
|
||||
|
||||
from .views import ColorView, ProductlikeView, SizeView
|
||||
|
||||
router = DefaultRouter()
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path("", include(router.urls)),
|
||||
]
|
||||
router.register("productlike", ProductlikeView, basename="productlike")
|
||||
router.register("color", ColorView, basename="color")
|
||||
router.register("size", SizeView, basename="size")
|
||||
urlpatterns = [path("", include(router.urls))]
|
||||
|
||||
1
core/apps/api/validators/__init__.py
Normal file
1
core/apps/api/validators/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .attributes import * # noqa
|
||||
22
core/apps/api/validators/attributes.py
Normal file
22
core/apps/api/validators/attributes.py
Normal file
@@ -0,0 +1,22 @@
|
||||
# from django.core.exceptions import ValidationError
|
||||
|
||||
|
||||
class SizeValidator:
|
||||
def __init__(self): ...
|
||||
|
||||
def __call__(self):
|
||||
return True
|
||||
|
||||
|
||||
class ColorValidator:
|
||||
def __init__(self): ...
|
||||
|
||||
def __call__(self):
|
||||
return True
|
||||
|
||||
|
||||
class ProductlikeValidator:
|
||||
def __init__(self): ...
|
||||
|
||||
def __call__(self):
|
||||
return True
|
||||
@@ -0,0 +1 @@
|
||||
from .attributes import * # noqa
|
||||
|
||||
59
core/apps/api/views/attributes.py
Normal file
59
core/apps/api/views/attributes.py
Normal file
@@ -0,0 +1,59 @@
|
||||
from django_core.mixins import BaseViewSetMixin
|
||||
from drf_spectacular.utils import extend_schema
|
||||
from rest_framework.permissions import AllowAny
|
||||
from rest_framework.viewsets import ReadOnlyModelViewSet
|
||||
|
||||
from core.apps.api.models import ColorModel, ProductlikeModel, SizeModel
|
||||
from core.apps.api.serializers.attributes import (
|
||||
CreateColorSerializer,
|
||||
CreateProductlikeSerializer,
|
||||
CreateSizeSerializer,
|
||||
ListColorSerializer,
|
||||
ListProductlikeSerializer,
|
||||
ListSizeSerializer,
|
||||
RetrieveColorSerializer,
|
||||
RetrieveProductlikeSerializer,
|
||||
RetrieveSizeSerializer,
|
||||
)
|
||||
|
||||
|
||||
@extend_schema(tags=["size"])
|
||||
class SizeView(BaseViewSetMixin, ReadOnlyModelViewSet):
|
||||
queryset = SizeModel.objects.all()
|
||||
serializer_class = ListSizeSerializer
|
||||
permission_classes = [AllowAny]
|
||||
|
||||
action_permission_classes = {}
|
||||
action_serializer_class = {
|
||||
"list": ListSizeSerializer,
|
||||
"retrieve": RetrieveSizeSerializer,
|
||||
"create": CreateSizeSerializer,
|
||||
}
|
||||
|
||||
|
||||
@extend_schema(tags=["color"])
|
||||
class ColorView(BaseViewSetMixin, ReadOnlyModelViewSet):
|
||||
queryset = ColorModel.objects.all()
|
||||
serializer_class = ListColorSerializer
|
||||
permission_classes = [AllowAny]
|
||||
|
||||
action_permission_classes = {}
|
||||
action_serializer_class = {
|
||||
"list": ListColorSerializer,
|
||||
"retrieve": RetrieveColorSerializer,
|
||||
"create": CreateColorSerializer,
|
||||
}
|
||||
|
||||
|
||||
@extend_schema(tags=["productlike"])
|
||||
class ProductlikeView(BaseViewSetMixin, ReadOnlyModelViewSet):
|
||||
queryset = ProductlikeModel.objects.all()
|
||||
serializer_class = ListProductlikeSerializer
|
||||
permission_classes = [AllowAny]
|
||||
|
||||
action_permission_classes = {}
|
||||
action_serializer_class = {
|
||||
"list": ListProductlikeSerializer,
|
||||
"retrieve": RetrieveProductlikeSerializer,
|
||||
"create": CreateProductlikeSerializer,
|
||||
}
|
||||
Reference in New Issue
Block a user