Skip to content
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
10 changes: 7 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,23 @@ repos:
hooks:
- id: black
args: ['-l', '140', '-t', 'py311']

- repo: https://github.com/myint/autoflake
rev: v1.4
hooks:
- id: autoflake
args:
- --in-place
- --remove-unused-variables
- --remove-all-unused-imports
- --remove-unused-variables
- --ignore-init-module-imports
- --in-place
- --recursive

- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
- id: isort
args: ['--line-length', '140']
args: ['--profile', 'black', '--filter-files', 'true']

default_language_version:
python: python3.11
File renamed without changes.
2 changes: 1 addition & 1 deletion common/views.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from rest_framework.response import Response
from rest_framework.views import APIView

from common.dacorator import mandatories, optionals
from common.decorator import mandatories, optionals


class QueryTestView(APIView):
Expand Down
35 changes: 29 additions & 6 deletions posts/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
# Generated by Django 4.2.6 on 2023-10-25 07:12
# Generated by Django 4.2.6 on 2023-10-28 12:59

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import uuid


class Migration(migrations.Migration):

initial = True

dependencies = [
('users', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
Expand All @@ -18,17 +20,17 @@ class Migration(migrations.Migration):
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=32)),
('hashtag_count', models.IntegerField(default=0)),
('created_at', models.DateTimeField(auto_now_add=True)),
],
options={
'db_table': 'hashtag',
'db_table': 'hashtags',
},
),
migrations.CreateModel(
name='Post',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('content_id', models.UUIDField(default=uuid.uuid4, editable=False)),
('post_type', models.CharField(choices=[('facebook', 'Facebook'), ('twitter', 'Twitter'), ('instagram', 'Instagram'), ('threads', 'Threads')], max_length=16)),
('title', models.CharField(max_length=32)),
('content', models.TextField()),
Expand All @@ -37,11 +39,32 @@ class Migration(migrations.Migration):
('share_count', models.IntegerField(default=0)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('hashtag', models.ManyToManyField(related_name='posts', to='posts.hashtag')),
('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='users.user')),
],
options={
'db_table': 'posts',
},
),
migrations.CreateModel(
name='PostHashtag',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('hashtag', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='posts.hashtag')),
('post', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='posts.post')),
],
options={
'db_table': 'posts_hashtags',
'unique_together': {('post', 'hashtag')},
},
),
migrations.AddField(
model_name='post',
name='hashtag_set',
field=models.ManyToManyField(through='posts.PostHashtag', to='posts.hashtag'),
),
migrations.AddField(
model_name='post',
name='user',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
]
19 changes: 0 additions & 19 deletions posts/migrations/0002_post_content_id.py

This file was deleted.

24 changes: 17 additions & 7 deletions posts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

from django.db import models

from users.models import User


class Post(models.Model):
class PostType(models.TextChoices):
Expand All @@ -21,23 +19,35 @@ class PostType(models.TextChoices):
share_count = models.IntegerField(default=0)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
hashtag = models.ManyToManyField("HashTag", related_name="posts")
user = models.ForeignKey("users.User", on_delete=models.SET_NULL, null=True)
hashtag_set = models.ManyToManyField("HashTag", through="PostHashtag", through_fields=("post", "hashtag"))

class Meta:
db_table = "posts"

def __str__(self):
return f"{self.title} by {self.user.email}"
return f"[{self.user.email}]: {self.title}"


class HashTag(models.Model):
name = models.CharField(max_length=32)
hashtag_count = models.IntegerField(default=0)
created_at = models.DateTimeField(auto_now_add=True)

class Meta:
db_table = "hashtag"
db_table = "hashtags"

def __str__(self):
return self.name


class PostHashtag(models.Model):
post = models.ForeignKey("Post", on_delete=models.SET_NULL, null=True)
hashtag = models.ForeignKey("HashTag", on_delete=models.SET_NULL, null=True)
created_at = models.DateTimeField(auto_now_add=True)

class Meta:
db_table = "posts_hashtags"
unique_together = ("post", "hashtag")

def __str__(self):
return f"{self.post.title} - {self.hashtag.name}"
11 changes: 11 additions & 0 deletions posts/serializers.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from rest_framework import serializers

from posts.models import HashTag


class StatisticsQuerySerializer(serializers.Serializer):
type = serializers.ChoiceField(choices=["date", "hour"])
Expand All @@ -12,3 +14,12 @@ class StatisticsQuerySerializer(serializers.Serializer):
class StatisticsListSerializer(serializers.Serializer):
datetime = serializers.DateTimeField()
count = serializers.IntegerField()


class HashTagRecommendListSerializer(serializers.ModelSerializer):
class Meta:
model = HashTag
fields = (
"id",
"name",
)
55 changes: 55 additions & 0 deletions posts/tests/views/test_hashtag_recommend_list_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APITestCase

from posts.models import HashTag, Post
from users.models import User


class HashTagRecommendListViewTest(APITestCase):
@classmethod
def setUpTestData(cls):
cls.hasgtag1 = HashTag.objects.create(
name="hashtag1",
)
cls.hasgtag2 = HashTag.objects.create(
name="hashtag2",
)
for i in range(1, 10):
cls.users = User.objects.create_user(
email=f"user{i}@example.com",
password="testpassword",
)
cls.posts = Post.objects.create(
post_type="facebook",
title=f"title {i}",
content=f"content {i}",
view_count=i,
like_count=i,
share_count=i,
user=cls.users,
)
if i % 2 == 0:
cls.posts.hashtag_set.set([cls.hasgtag2])
else:
cls.posts.hashtag_set.set([cls.hasgtag1, cls.hasgtag2])

def setUp(self):
pass
# self.access_token = self.client.post(reverse("token_obtain_pair"), self.user_data).data["access"]

def test_get_hash_tag_recommend_list_success(self):
response = self.client.get(
path=reverse("hashtag_recommend_list"),
# HTTP_AUTHORIZATION=f"Bearer {self.access_token}",
)
self.assertEqual(response.data[0]["id"], 2)
self.assertEqual(response.data[0]["name"], "hashtag2")
self.assertEqual(response.status_code, status.HTTP_200_OK)

# @TODO: 로그인 로직 구현 후 주석 풀기 @SaJH
# def test_get_hash_tag_recommend_list_fail_unauthenticated(self):
# response = self.client.get(
# path=reverse("hashtag_recommend_list"),
# )
# self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
18 changes: 9 additions & 9 deletions posts/tests/views/test_statics_list_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ def setUpTestData(cls):
share_count=i,
user=cls.users,
)
cls.posts.hashtag.set([cls.hasgtag])
cls.posts.hashtag_set.set([cls.hasgtag])

def setUp(self):
pass
# self.access_token = self.client.post(reverse("token_obtain_pair"), self.user_data).data["access"]

def test_get_statistics_list_date_success(self):
response = self.client.get(
path=reverse("statistics"),
path=reverse("statistics_list"),
data={
"type": "date",
"hashtag": "hashtag",
Expand All @@ -46,7 +46,7 @@ def test_get_statistics_list_date_success(self):

def test_get_statistics_list_hour_success(self):
response = self.client.get(
path=reverse("statistics"),
path=reverse("statistics_list"),
data={
"type": "hour",
"hashtag": "hashtag",
Expand All @@ -58,7 +58,7 @@ def test_get_statistics_list_hour_success(self):

def test_get_statistics_list_not_found(self):
response = self.client.get(
path=reverse("statistics"),
path=reverse("statistics_list"),
data={
"type": "date",
"hashtag": "hashtag1",
Expand All @@ -72,7 +72,7 @@ def test_get_statistics_list_not_found(self):
# @TODO: 로그인 로직 구현 후 주석 풀기 @SaJH
# def test_get_statistics_list_fail_unauthenticated(self):
# response = self.client.get(
# path=reverse("statistics"),
# path=reverse("statistics_list"),
# data={
# "type": "date",
# "hashtag": "hashtag",
Expand All @@ -83,7 +83,7 @@ def test_get_statistics_list_not_found(self):

def test_get_statistics_list_fail_missing_parameter(self):
response = self.client.get(
path=reverse("statistics"),
path=reverse("statistics_list"),
data={
"hashtag": "hashtag",
},
Expand All @@ -93,7 +93,7 @@ def test_get_statistics_list_fail_missing_parameter(self):

def test_get_statistics_list_fail_invalid_parameter_type(self):
response = self.client.get(
path=reverse("statistics"),
path=reverse("statistics_list"),
data={
"type": "test",
"hashtag": "hashtag",
Expand All @@ -105,7 +105,7 @@ def test_get_statistics_list_fail_invalid_parameter_type(self):

def test_get_statistics_list_fail_invalid_parameter_max_days(self):
response = self.client.get(
path=reverse("statistics"),
path=reverse("statistics_list"),
data={
"type": "date",
"start": "2023-10-1",
Expand All @@ -119,7 +119,7 @@ def test_get_statistics_list_fail_invalid_parameter_max_days(self):

def test_get_statistics_list_fail_invalid_parameter_value(self):
response = self.client.get(
path=reverse("statistics"),
path=reverse("statistics_list"),
data={
"type": "date",
"hashtag": "hashtag",
Expand Down
5 changes: 3 additions & 2 deletions posts/urls.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from django.urls import path

from posts.views import StatisticsListView
from posts.views import HashTagRecommendListView, StatisticsListView

urlpatterns = [
path("statistics/", StatisticsListView.as_view(), name="statistics"),
path("statistics/", StatisticsListView.as_view(), name="statistics_list"),
path("hashtag/recommend/", HashTagRecommendListView.as_view(), name="hashtag_recommend_list"),
]
Loading