Skip to content

Commit 9fc0a2d

Browse files
authored
Merge pull request #70 from rss-translator/next
feat: add tags
2 parents e0b3453 + fddb862 commit 9fc0a2d

File tree

13 files changed

+1776
-94
lines changed

13 files changed

+1776
-94
lines changed

.dockerignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@ __pycache__/
99
.pdm-python
1010
.eggs/
1111
.git/
12+
.github/
1213
!.git/HEAD
1314
!.git/refs/heads/*
1415

1516
venv/
1617
.venv/
1718
.venv-old/
1819
.docker-venv/
20+
.vscode/
1921
node_modules/
2022

2123
docs/
@@ -30,4 +32,5 @@ docker/
3032

3133
data/
3234
output/
33-
deploy/
35+
deploy/
36+
website/

.vscode/launch.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"version": "0.2.0",
3+
"configurations": [
4+
{
5+
"name": "Python Debug: Django",
6+
"type": "debugpy",
7+
"python": "${workspaceFolder}/venv/bin/python",
8+
"env": {"GEVENT_SUPPORT": "True"},
9+
"request": "launch",
10+
"args": [
11+
"run_dev"
12+
],
13+
"django": true,
14+
"autoStartBrowser": false,
15+
"program": "${workspaceFolder}/manage.py"
16+
}
17+
]
18+
}

config/settings.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,21 @@
5858
'translator.apps.TranslatorConfig',
5959
'core.apps.CoreConfig',
6060
'encrypted_model_fields', # must set FIELD_ENCRYPTION_KEY value
61+
'tagulous',
6162
]
6263
DEBUG_PLUGINS = [
6364
"debug_toolbar",
6465
'bx_django_utils', # https://github.com/boxine/bx_django_utils
6566
#'huey_monitor',
6667
]
6768

69+
SERIALIZATION_MODULES = {
70+
'xml': 'tagulous.serializers.xml_serializer',
71+
'json': 'tagulous.serializers.json',
72+
'python': 'tagulous.serializers.python',
73+
'yaml': 'tagulous.serializers.pyyaml',
74+
}
75+
6876
MIDDLEWARE = [
6977
"django.middleware.security.SecurityMiddleware",
7078
"whitenoise.middleware.WhiteNoiseMiddleware",

core/admin.py

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
from django.urls import path
88
from django.shortcuts import render,redirect
99
from django.core.paginator import Paginator
10-
1110
from django.contrib.auth.models import User, Group
1211
from django.urls import reverse
1312
from django.utils.html import format_html
1413
from django.utils.translation import gettext_lazy as _
1514
from .models import O_Feed, T_Feed
15+
#from taggit.models import Tag
1616
from .tasks import update_original_feed, update_translated_feed
1717
from utils.modelAdmin_utils import CustomModelActions, get_translator_and_summary_choices, get_all_app_models, valid_icon
1818

@@ -189,7 +189,7 @@ def __init__(self, *args, **kwargs):
189189

190190
class Meta:
191191
model = O_Feed
192-
fields = ['feed_url', 'update_frequency', 'max_posts', 'translator', 'translation_display', 'summary_engine', 'summary_detail', 'additional_prompt', 'name', 'fetch_article', 'quality']
192+
fields = ['feed_url', 'update_frequency', 'max_posts', 'translator', 'translation_display', 'summary_engine', 'summary_detail', 'additional_prompt', 'fetch_article', 'quality', 'name', 'tags', ]
193193

194194
# 重写save方法,以处理自定义字段的数据
195195
def save(self, commit=True):
@@ -216,9 +216,9 @@ class O_FeedAdmin(admin.ModelAdmin, CustomModelActions):
216216
form = O_FeedForm
217217
inlines = [T_FeedInline]
218218
list_display = ["name", "is_valid", "show_feed_url", "translated_language", "translator", "size_in_kb",
219-
"update_frequency", "last_updated", "last_pull"]
220-
search_fields = ["name", "feed_url"]
221-
list_filter = ["valid"]
219+
"update_frequency", "last_updated", "last_pull", "tag_list"]
220+
search_fields = ["name", "feed_url", "tags__name"]
221+
list_filter = ["valid","tags"]
222222
actions = ['o_feed_force_update', 'o_feed_export_as_opml', 'o_feed_batch_modify']
223223

224224

@@ -264,6 +264,12 @@ def translated_language(self, obj):
264264
return ", ".join(t_feed.language for t_feed in obj.t_feed_set.all())
265265
translated_language.short_description = _('Translated Language')
266266

267+
def get_queryset(self, request):
268+
return super().get_queryset(request).prefetch_related('tags')
269+
270+
def tag_list(self, obj):
271+
return ", ".join(o.name for o in obj.tags.all())
272+
267273
def size_in_kb(self, obj):
268274
return int(obj.size / 1024)
269275

@@ -310,7 +316,8 @@ def o_feed_batch_modify(self, request, queryset):
310316
'summary_detail': 'summary_detail_value',
311317
'additional_prompt': 'additional_prompt_value',
312318
'fetch_article': 'fetch_article',
313-
'quality': 'quality'
319+
'quality': 'quality',
320+
'tags': 'tags_value'
314321
}
315322
field_types = {
316323
'update_frequency': int,
@@ -322,6 +329,7 @@ def o_feed_batch_modify(self, request, queryset):
322329
'quality': literal_eval
323330
}
324331
update_fields = {}
332+
tags_value = None
325333
for field, value_field in fields.items():
326334
value = post_data.get(value_field)
327335
if post_data.get(field, 'Keep') != 'Keep' and value:
@@ -334,12 +342,20 @@ def o_feed_batch_modify(self, request, queryset):
334342
content_type_summary_id, object_id_summary = map(int, value.split(':'))
335343
update_fields['content_type_summary_id'] = content_type_summary_id
336344
update_fields['object_id_summary'] = object_id_summary
345+
case 'tags':
346+
tags_value = value.split(",")
337347
case _:
338348
update_fields[field] = field_types.get(field, str)(value)
339349

340350
if update_fields:
341351
queryset.update(**update_fields)
342352

353+
if tags_value is not None:
354+
for obj in queryset:
355+
obj.tags = [*tags_value]
356+
obj.save()
357+
#O_Feed.objects.bulk_update(queryset, ['tags'])??
358+
343359
#self.message_user(request, f"Successfully modified {queryset.count()} items.")
344360
#return HttpResponseRedirect(request.get_full_path())
345361
return redirect(request.get_full_path())
@@ -348,19 +364,21 @@ def o_feed_batch_modify(self, request, queryset):
348364
logging.info("translator_choices: %s, summary_engine_choices: %s", translator_choices, summary_engine_choices)
349365
return render(request, 'admin/o_feed_batch_modify.html', context={**core_admin_site.each_context(request), 'items': queryset,'translator_choices': translator_choices, 'summary_engine_choices': summary_engine_choices})
350366
o_feed_batch_modify.short_description = _("Batch modification")
351-
367+
352368

353369
class T_FeedAdmin(admin.ModelAdmin, CustomModelActions):
354370
list_display = ["id", "feed_url", "o_feed", "status_icon", "language", "translate_title", "translate_content", "summary", "total_tokens", "total_characters", "size_in_kb", "modified"]
355-
list_filter = ["status", "translate_title", "translate_content"]
356-
search_fields = ["sid"]
371+
list_filter = ["status", "translate_title", "translate_content", "o_feed__tags__name"]
372+
search_fields = ["sid", "o_feed__tags__name", "o_feed__feed_url"]
357373
readonly_fields = ["status", "language", "sid", "o_feed", "total_tokens", "total_characters", "size", "modified"]
358374
actions = ['t_feed_force_update', 't_feed_export_as_opml', 't_feed_batch_modify']
359-
def get_search_results(self, request, queryset, search_term):
360-
queryset, use_distinct = super().get_search_results(request, queryset, search_term)
361-
queryset |= self.model.objects.filter(o_feed__feed_url__icontains=search_term)
362-
return queryset, use_distinct
363-
375+
# def get_search_results(self, request, queryset, search_term):
376+
# queryset, use_distinct = super().get_search_results(request, queryset, search_term)
377+
# queryset |= self.model.objects.filter(o_feed__feed_url__icontains=search_term)
378+
# return queryset, use_distinct
379+
380+
def get_queryset(self, request):
381+
return super().get_queryset(request).prefetch_related('o_feed__tags')
364382

365383
def size_in_kb(self, obj):
366384
return int(obj.size / 1024)
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Generated by Django 5.0.6 on 2024-05-16 08:54
2+
3+
import tagulous.models.fields
4+
import tagulous.models.models
5+
from django.db import migrations, models
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
dependencies = [
11+
("core", "0013_alter_o_feed_sid_alter_t_feed_sid"),
12+
]
13+
14+
operations = [
15+
migrations.CreateModel(
16+
name="Tagulous_O_Feed_tags",
17+
fields=[
18+
(
19+
"id",
20+
models.BigAutoField(
21+
auto_created=True,
22+
primary_key=True,
23+
serialize=False,
24+
verbose_name="ID",
25+
),
26+
),
27+
("name", models.CharField(max_length=255, unique=True)),
28+
("slug", models.SlugField()),
29+
(
30+
"count",
31+
models.IntegerField(
32+
default=0,
33+
help_text="Internal counter of how many times this tag is in use",
34+
),
35+
),
36+
(
37+
"protected",
38+
models.BooleanField(
39+
default=False,
40+
help_text="Will not be deleted when the count reaches 0",
41+
),
42+
),
43+
],
44+
options={
45+
"ordering": ("name",),
46+
"abstract": False,
47+
"unique_together": {("slug",)},
48+
},
49+
bases=(tagulous.models.models.BaseTagModel, models.Model),
50+
),
51+
migrations.AddField(
52+
model_name="o_feed",
53+
name="tags",
54+
field=tagulous.models.fields.TagField(
55+
_set_tag_meta=True,
56+
blank=True,
57+
force_lowercase=True,
58+
help_text="Enter a comma-separated tag string",
59+
to="core.tagulous_o_feed_tags",
60+
),
61+
),
62+
]

core/models.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from django.db import models
99
from django.utils.translation import gettext_lazy as _
1010
from django.core.validators import MinValueValidator, MaxValueValidator
11+
from tagulous.models import TagField
1112

1213

1314
class O_Feed(models.Model):
@@ -48,6 +49,7 @@ class O_Feed(models.Model):
4849
help_text=_("Level of detail of summaries of longer articles. 0: Normal, 1: Most detailed (cost more tokens)"))
4950

5051
additional_prompt = models.TextField(_("Addtional Prompt"), default=None, blank=True, null=True, help_text=_("Addtional Prompt for translation and summary"))
52+
tags = TagField(force_lowercase=True, blank=True, help_text=_("Enter a comma-separated tag string"))
5153

5254
def __str__(self):
5355
return self.feed_url

core/signals.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from django.dispatch import receiver
77

88
from .models import O_Feed, T_Feed
9+
#from taggit.models import TaggedItem
910

1011
@receiver(post_delete, sender=O_Feed)
1112
def delete_o_feed_xml(sender, instance, **kwargs):
@@ -20,3 +21,10 @@ def delete_t_feed_xml(sender, instance, **kwargs):
2021
feed_file_path = f"{settings.DATA_FOLDER}/feeds/{instance.sid}.xml"
2122
if os.path.exists(feed_file_path):
2223
os.remove(feed_file_path)
24+
25+
#For django-taggit
26+
# @receiver(post_delete, sender=TaggedItem)
27+
# def delete_unused_tags(sender, instance, **kwargs):
28+
# n_tagged = TaggedItem.objects.filter(tag_id=instance.tag_id).count()
29+
# if n_tagged == 0:
30+
# instance.tag.delete()

core/tasks.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ def translate_feed(
233233
title = entry["title"]
234234

235235
# Translate title
236-
if translate_title:
236+
if translate_engine and translate_title:
237237
cached = Translated_Content.is_translated(title, target_language) # check cache db
238238
translated_text = ''
239239
if not cached:
@@ -274,7 +274,7 @@ def translate_feed(
274274
logging.warning("Fetch original article error:%s", e)
275275

276276
# Translate content
277-
if translate_content:
277+
if translate_engine and translate_content:
278278
if translate_engine == None:
279279
logging.warning("No translate engine")
280280
continue
@@ -305,7 +305,7 @@ def translate_feed(
305305
bulk_save_cache(need_cache_objs)
306306
need_cache_objs = {}
307307

308-
if summary:
308+
if summary_engine and summary:
309309
if summary_engine == None:
310310
logging.warning("No Summarize engine")
311311
continue

0 commit comments

Comments
 (0)