Skip to content

Commit defbf8b

Browse files
committed
Исключены новости программ из общей ленты
1 parent 0900d34 commit defbf8b

6 files changed

Lines changed: 26 additions & 41 deletions

File tree

docs/modules/feed.md

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -52,20 +52,12 @@ View выбирает подходящие `news.News`, сериализует
5252

5353
### 2. В ленту попадает обычная новость
5454

55-
Если `news.News` содержит текст и относится к пользователю, проекту или
56-
партнерской программе, лента возвращает ее как новость.
55+
Если `news.News` содержит текст и относится к пользователю или проекту, лента
56+
возвращает ее как новость.
5757

5858
Проектная новость с текстом возвращается как `type_model = "news"`, даже если
5959
ее `content_object` - проект.
6060

61-
Новость партнерской программы с текстом тоже возвращается как
62-
`type_model = "news"`. Отдельный `type_model = "partner_program"` пока не
63-
вводится.
64-
65-
Служебные feed-записи партнерских программ сейчас не создаются. Если такой
66-
сценарий понадобится, для него нужно отдельно согласовать `type_model` и
67-
frontend-контракт.
68-
6961
### 3. В ленту попадает служебная запись
7062

7163
Служебные feed-записи создаются через `feed.services.create_news_for_model()`.
@@ -91,17 +83,15 @@ frontend-контракт.
9183
- `GET /feed/?type=news` - новости пользователей.
9284
- `GET /feed/?type=project` - проектные новости и проектные feed-записи.
9385
- `GET /feed/?type=vacancy` - служебные feed-записи вакансий.
94-
- `GET /feed/?type=partnerprogram` - новости партнерских программ.
95-
- `GET /feed/?type=project|vacancy|news|partnerprogram` - комбинированная
96-
выдача по нескольким типам.
86+
- `GET /feed/?type=project|vacancy|news` - комбинированная выдача по нескольким
87+
типам.
9788

9889
## Ограничения и правила
9990

10091
- Feed читает данные из `news.News`, но не отвечает за создание обычных
101-
project/user/program news.
92+
project/user news.
10293
- Служебная feed-запись определяется через пустой `text`.
103-
- Новости партнерских программ с текстом отображаются как обычные новости;
104-
отдельные служебные карточки программ в ленте пока не поддерживаются.
94+
- Новости партнерских программ не отображаются в `/feed/`.
10595
- Signals `feed` создают или удаляют служебные feed-записи для проектов и
10696
вакансий. Более широкие сценарии публикации проекта остаются в модуле
10797
`projects`.
@@ -112,8 +102,6 @@ frontend-контракт.
112102

113103
- `/feed/?type=news` возвращает пользовательские новости;
114104
- `/feed/?type=project` возвращает проектные новости в frontend-формате;
115-
- `/feed/?type=partnerprogram` возвращает новости программ как
116-
`type_model = "news"`;
117105
- `/feed/?type=project` возвращает служебную feed-запись проекта как
118106
`type_model = "project"`;
119107
- `/feed/?type=vacancy` возвращает служебную feed-запись вакансии как

docs/modules/partner-programs.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,6 @@
161161
`PartnerProgramProject`.
162162
- `users` - участники и менеджеры программы.
163163
- `news` - новости программы создаются и читаются через общий news API.
164-
- `feed` - текстовые новости программы могут попадать в общую ленту как
165-
`type_model = "news"`.
166164
- `courses` - курс может быть связан с программой и доступен участникам
167165
программы.
168166
- `project_rates` - оценки проектов используются в выгрузке результатов.
@@ -176,8 +174,6 @@
176174
- Значения дополнительных полей хранятся в `PartnerProgramFieldValue`.
177175
- После сдачи проекта в конкурсной программе значения полей редактировать
178176
нельзя.
179-
- Служебные feed-карточки программ пока не поддерживаются; новости программ в
180-
feed отображаются как обычные новости.
181177
- Основной API-код пока сосредоточен во `views.py`; перед крупным рефакторингом
182178
нужно зафиксировать больше regression-тестов.
183179

feed/serializers.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
from news.mapping import NewsMapping
77
from news.models import News
88
from news.services import is_content_news
9-
from partner_programs.models import PartnerProgram
109
from projects.models import Project
1110
from users.models import CustomUser
1211

@@ -24,11 +23,6 @@ class FeedNewsContentSerializer(serializers.ModelSerializer):
2423
def get_type_model(self, obj) -> str | None:
2524
content_model = obj.content_type.model
2625

27-
if content_model == PartnerProgram.__name__.lower():
28-
# Новости программ сейчас отображаются как обычные новости.
29-
# Отдельная служебная карточка программы в ленте пока не согласована.
30-
return "news" if is_content_news(obj) else None
31-
3226
if is_content_news(obj) and content_model == Project.__name__.lower():
3327
return "news"
3428

feed/tests/test_feed_api.py

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,15 @@ def test_feed_returns_project_news_as_news_content(self):
4343
self.assertEqual(item["content"]["id"], news.id)
4444
self.assertEqual(item["content"]["text"], "Project feed news")
4545

46-
def test_feed_returns_program_news_as_news_content(self):
46+
def test_feed_ignores_program_news_filter(self):
4747
program = create_partner_program(name="Feed program")
48-
news = create_news_for(program, text="Program feed news")
48+
create_news_for(program, text="Program feed news")
49+
create_news_for(program, text="")
4950

5051
response = self.client.get("/feed/?type=partnerprogram")
5152

5253
self.assertEqual(response.status_code, 200)
53-
item = response.data["results"][0]
54-
self.assertEqual(set(item.keys()), {"type_model", "content"})
55-
self.assertEqual(item["type_model"], "news")
56-
self.assertEqual(item["content"]["id"], news.id)
57-
self.assertEqual(item["content"]["text"], "Program feed news")
54+
self.assertEqual(response.data["results"], [])
5855

5956
def test_feed_returns_project_feed_record_as_project_content(self):
6057
project = create_project(name="Feed record project")
@@ -80,7 +77,7 @@ def test_feed_returns_vacancy_feed_record_as_vacancy_content(self):
8077
self.assertEqual(item["content"]["id"], vacancy.id)
8178
self.assertEqual(item["content"]["role"], "Backend developer")
8279

83-
def test_feed_combines_all_supported_filters(self):
80+
def test_feed_combines_supported_filters_and_ignores_program_news(self):
8481
project_news = create_news_for(
8582
create_project(name="Combined project news"),
8683
text="Combined project news",
@@ -117,14 +114,11 @@ def test_feed_combines_all_supported_filters(self):
117114
items_by_text[project_news.text]["content"]["id"],
118115
project_news.id,
119116
)
120-
self.assertEqual(
121-
items_by_text[program_news.text]["content"]["id"],
122-
program_news.id,
123-
)
124117
self.assertEqual(
125118
items_by_text[user_news.text]["content"]["id"],
126119
user_news.id,
127120
)
121+
self.assertNotIn(program_news.text, items_by_text)
128122
self.assertIn(project.id, content_ids_by_type["project"])
129123
self.assertIn(vacancy.id, content_ids_by_type["vacancy"])
130124

feed/views.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ def _get_filter_data(self) -> list[str]:
2121
news_types: list[str] = filter_queries.split("|")
2222
if "news" in news_types:
2323
news_types.append("customuser")
24-
return news_types
24+
return [
25+
news_type
26+
for news_type in news_types
27+
if news_type != "partnerprogram"
28+
]
2529

2630
def get_queryset(self) -> QuerySet[News]:
2731
filters = self._get_filter_data()

news/tests/test_news_user_program_api.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,15 @@ def test_program_news_list_orders_pinned_news_first(self):
9797
news_ids = [item["id"] for item in response.data["results"]]
9898
self.assertEqual(news_ids, [pinned_news.id, regular_news.id])
9999

100+
def test_program_news_list_returns_program_news(self):
101+
news = create_news_for(self.program, text="Visible program news")
102+
103+
response = self.client.get(f"/programs/{self.program.id}/news/")
104+
105+
self.assertEqual(response.status_code, 200)
106+
self.assertEqual(response.data["results"][0]["id"], news.id)
107+
self.assertEqual(response.data["results"][0]["text"], "Visible program news")
108+
100109
def test_missing_program_context_returns_not_found(self):
101110
response = self.client.get("/programs/999999/news/")
102111

0 commit comments

Comments
 (0)