Ad like uchun apilar chiqarildi

This commit is contained in:
2025-11-26 16:47:37 +05:00
parent f619856e41
commit 900f23e5f6
21 changed files with 9428 additions and 53 deletions

View File

@@ -1,7 +1,7 @@
from django.contrib import admin
from unfold.admin import ModelAdmin
from core.apps.accounts.models import SearchHistory
from core.apps.accounts.models import SearchHistory, UserLike
@admin.register(SearchHistory)
@@ -10,3 +10,11 @@ class SearchHistoryAdmin(ModelAdmin):
"id",
"__str__",
)
@admin.register(UserLike)
class UserLikeAdmin(ModelAdmin):
list_display = (
"id",
"__str__",
)

View File

@@ -0,0 +1,31 @@
# Generated by Django 5.2.7 on 2025-11-26 10:04
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0004_business_searchhistory'),
('api', '0013_alter_feedback_comment'),
]
operations = [
migrations.CreateModel(
name='UserLike',
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)),
('ad', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='likes', to='api.admodel', verbose_name='Ad')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='likes', to=settings.AUTH_USER_MODEL, verbose_name='User')),
],
options={
'verbose_name': 'User Like',
'verbose_name_plural': 'User Likes',
'db_table': 'user_like',
},
),
]

View File

@@ -0,0 +1,28 @@
# Generated by Django 5.2.7 on 2025-11-26 10:06
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('accounts', '0005_userlike'),
]
operations = [
migrations.RenameField(
model_name='business',
old_name='address_name',
new_name='address',
),
migrations.RenameField(
model_name='business',
old_name='latitude',
new_name='lat',
),
migrations.RenameField(
model_name='business',
old_name='longitude',
new_name='long',
),
]

View File

@@ -13,9 +13,9 @@ class Business(AbstractBaseModel):
facebook = models.CharField(max_length=255, verbose_name=_('Facebook'))
telegram = models.CharField(max_length=255, verbose_name=_('Telegram'))
bio = models.TextField(verbose_name=_('Bio'))
address_name = models.CharField(max_length=255, verbose_name=_('Address Name'))
longitude = models.FloatField(verbose_name=_('Longitude'))
latitude = models.FloatField(verbose_name=_('Latitude'))
address = models.CharField(max_length=255, verbose_name=_('Address Name'))
long = models.FloatField(verbose_name=_('Longitude'))
lat = models.FloatField(verbose_name=_('Latitude'))
def __str__(self):
return str(self.pk)

View File

@@ -3,6 +3,7 @@ from django.db import models
from ..choices import RoleChoice, AccountType
from ..managers import UserManager
from model_bakery import baker
class User(auth_models.AbstractUser):
@@ -22,5 +23,9 @@ class User(auth_models.AbstractUser):
USERNAME_FIELD = "phone"
objects = UserManager()
@classmethod
def _baker(cls):
return baker.make(cls)
def __str__(self):
return self.phone

View File

@@ -0,0 +1,23 @@
from django.contrib.auth import get_user_model
from django.db import models
from django_core.models.base import AbstractBaseModel
from django.utils.translation import gettext_lazy as _
from core.apps.api.models import AdModel
from model_bakery import baker
class UserLike(AbstractBaseModel):
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, verbose_name=_("User"), related_name="likes")
ad = models.ForeignKey(AdModel, on_delete=models.CASCADE, verbose_name=_("Ad"), related_name="likes")
@classmethod
def _baker(cls):
return baker.make(cls)
def __str__(self):
return str(self.pk)
class Meta:
db_table = "user_like"
verbose_name = _("User Like")
verbose_name_plural = _("User Likes")

View File

@@ -0,0 +1,18 @@
# Generated by Django 5.2.7 on 2025-11-26 10:04
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('api', '0012_rename_command_feedback_comment'),
]
operations = [
migrations.AlterField(
model_name='feedback',
name='comment',
field=models.CharField(max_length=255, verbose_name='Comment'),
),
]

View File

@@ -1,3 +1,4 @@
from .category import * # noqa
from .search import * # noqa
from .ad import * # noqa
from .user import * # noqa

View File

@@ -0,0 +1 @@
from .ad_like import * # noqa

View File

@@ -0,0 +1,45 @@
from rest_framework import serializers
from core.apps.accounts.models import UserLike
from core.apps.api.models import AdModel
from core.apps.api.serializers.ad.home_api import ListHomeAdSerializer
from rest_framework.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
class BaseUserLikeSerializer(serializers.ModelSerializer):
ad = ListHomeAdSerializer(many=False, read_only=True)
class Meta:
model = UserLike
fields = [
"id",
"ad",
]
class ListUserLikeSerializer(BaseUserLikeSerializer):
class Meta(BaseUserLikeSerializer.Meta): ...
class RetrieveUserLikeSerializer(BaseUserLikeSerializer):
class Meta(BaseUserLikeSerializer.Meta): ...
class CreateUserLikeSerializer(BaseUserLikeSerializer):
ad = serializers.PrimaryKeyRelatedField(queryset=AdModel.objects.all())
class Meta(BaseUserLikeSerializer.Meta): ...
def validate(self, data):
user = self.context["request"].user
ad = data["ad"]
if UserLike.objects.filter(user=user, ad=ad).exists():
raise ValidationError({"detail": _("Siz bu elonga allaqachon like bosgansiz.")})
return data
def create(self, validated_data):
validated_data['user'] = self.context['request'].user
like = UserLike.objects.create(**validated_data)
return like

View File

@@ -1,3 +1,4 @@
from .category import * # noqa
from .ad import * # noqa
from .search import * # noqa
from .user import * # noqa

View File

@@ -0,0 +1 @@
from .test_user_like import * # noqa

View File

@@ -0,0 +1,62 @@
import pytest
from django.urls import reverse
from rest_framework.test import APIClient
from core.apps.accounts.models import UserLike, AdModel
@pytest.fixture
def instance(db):
return UserLike._baker()
@pytest.fixture
def ad(db):
return AdModel._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("user-like-list"),
"retrieve": reverse("user-like-detail", kwargs={"pk": instance.pk}),
"retrieve-not-found": reverse("user-like-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_create(data,ad):
urls, client, instance = data
response = client.post(urls["list"], data={"ad": ad.pk})
data_resp = response.json()
print(data_resp)
assert response.status_code == 201
assert data_resp["status"] is True
@pytest.mark.django_db
def test_destroy(data):
urls, client, _ = data
response = client.delete(urls["retrieve"])
assert response.status_code == 204

View File

@@ -1,9 +1,11 @@
from django.urls import include, path
from rest_framework.routers import DefaultRouter
from core.apps.api.views import CategoryHomeApiViewSet, CategoryViewSet, HomeAdApiView, SearchHistoryViewSet
from core.apps.api.views import CategoryHomeApiViewSet, CategoryViewSet, HomeAdApiView, SearchHistoryViewSet, \
UserLikeViewSet
router = DefaultRouter()
router.register("user-like", UserLikeViewSet, basename="user-like")
router.register("category", CategoryViewSet, basename="category")
router.register("category-home", CategoryHomeApiViewSet, basename="category-home")
router.register("search-history", SearchHistoryViewSet, basename="search-history")

View File

@@ -1,4 +1,4 @@
from .category import * # noqa
from .search import * # noqa
from .ad import * # noqa
from .user import * # noqa

View File

@@ -0,0 +1 @@
from .ad_like import * # noqa

View File

@@ -0,0 +1,28 @@
from rest_framework import mixins
from rest_framework.viewsets import GenericViewSet
from django_core.mixins.base import BaseViewSetMixin
from drf_spectacular.utils import extend_schema
from rest_framework.permissions import IsAuthenticated
from core.apps.accounts.models import UserLike
from core.apps.api.serializers.user.ad_like import (
ListUserLikeSerializer,
CreateUserLikeSerializer,
)
@extend_schema(tags=['User Like'])
class UserLikeViewSet(BaseViewSetMixin, mixins.ListModelMixin, mixins.CreateModelMixin,
mixins.DestroyModelMixin, GenericViewSet):
serializer_class = ListUserLikeSerializer
permission_classes = [IsAuthenticated]
http_method_names = ['get', 'post', 'delete']
action_permission_classes = {}
action_serializer_class = {
'list': ListUserLikeSerializer,
'create': CreateUserLikeSerializer,
}
def get_queryset(self):
queryset = UserLike.objects.filter(user=self.request.user).order_by('-id')
return queryset