Update sharing domain

This commit is contained in:
2026-03-21 21:22:04 +11:00
parent aa16044cc6
commit e191147a14
7 changed files with 147 additions and 4 deletions
BIN
View File
Binary file not shown.
+23
View File
@@ -0,0 +1,23 @@
# Generated by Django 5.2.11 on 2026-03-21 10:19
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('links', '0039_file_upload'),
]
operations = [
migrations.CreateModel(
name='SiteSettings',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('public_sharing_domain', models.CharField(blank=True, default='', help_text='Domain (with protocol) used for public sharing links, e.g. https://go.example.com. Leave blank to use the same domain as the app.', max_length=255, verbose_name='Public Sharing Domain')),
],
options={
'verbose_name': 'Site Settings',
},
),
]
+42 -3
View File
@@ -387,9 +387,16 @@ class FileUpload(models.Model):
@property
def public_url(self):
import re
safe_name = re.sub(r'[^\w.\-]', '-', self.name)
return f'/public/files/{self.pk}-{safe_name}'
import re as _re
safe_name = _re.sub(r'[^\w.\-]', '-', self.name)
path = f'/public/files/{self.pk}-{safe_name}'
if not self.is_public:
return path
try:
domain = SiteSettings.get().public_sharing_domain.rstrip('/')
except Exception:
domain = ''
return f'{domain}{path}' if domain else path
def formatted_size(self):
if self.size < 1024:
@@ -399,3 +406,35 @@ class FileUpload(models.Model):
elif self.size < 1024 * 1024 * 1024:
return f"{self.size / (1024 * 1024):.1f} MB"
return f"{self.size / (1024 * 1024 * 1024):.2f} GB"
class SiteSettings(models.Model):
"""
Singleton model for app-wide configuration.
Always use SiteSettings.get() to retrieve the instance.
"""
public_sharing_domain = models.CharField(
_('Public Sharing Domain'),
max_length=255,
blank=True,
default='',
help_text=_(
'Domain (with protocol) used for public sharing links, e.g. https://go.example.com. '
'Leave blank to use the same domain as the app.'
),
)
class Meta:
verbose_name = _('Site Settings')
def __str__(self):
return 'Site Settings'
@classmethod
def get(cls):
obj, _ = cls.objects.get_or_create(pk=1)
return obj
def save(self, *args, **kwargs):
self.pk = 1
super().save(*args, **kwargs)
+56
View File
@@ -0,0 +1,56 @@
{% extends 'base.html' %}
{% load i18n %}
{% load static %}
{% block extra_css %}
<link href="{% static 'css/dist/styles.css' %}" rel="stylesheet">
{% endblock %}
{% block content %}
<div class="max-w-2xl mx-auto">
<h1 class="text-2xl font-bold text-gray-800 mb-6">{% trans "Settings" %}</h1>
<form method="post">
{% csrf_token %}
<!-- Public Sharing Domain -->
<div class="bg-white rounded-lg shadow p-6 mb-6">
<h2 class="text-lg font-semibold text-gray-700 mb-1">{% trans "Public Sharing Domain" %}</h2>
<p class="text-sm text-gray-500 mb-4">
{% trans "Domain (with protocol) used for public file sharing links. Leave blank to use the same domain as the app." %}
<br>
<span class="font-mono text-xs text-gray-400">{% trans "Example:" %} https://go.example.com</span>
</p>
<input
type="url"
name="public_sharing_domain"
id="public_sharing_domain"
value="{{ site_settings.public_sharing_domain }}"
placeholder="https://go.example.com"
class="w-full border border-gray-300 rounded-md px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
>
{% if site_settings.public_sharing_domain %}
<p class="mt-2 text-xs text-green-600">
{% trans "Active. Public links will use:" %}
<span class="font-mono">{{ site_settings.public_sharing_domain }}/public/files/…</span>
</p>
{% else %}
<p class="mt-2 text-xs text-gray-400">
{% trans "Not set. Public links will use the app's own domain." %}
</p>
{% endif %}
</div>
<div class="flex justify-end">
<button
type="submit"
style="background:#1d4ed8;color:#fff;padding:.5rem 1.5rem;border-radius:.375rem;font-size:.875rem;font-weight:500;cursor:pointer;"
onmouseover="this.style.background='#1e40af'"
onmouseout="this.style.background='#1d4ed8'"
>
{% trans "Save Settings" %}
</button>
</div>
</form>
</div>
{% endblock %}
+1
View File
@@ -21,6 +21,7 @@ urlpatterns = [
path('ui/tools/', views.ToolsView.as_view(), name='tools'),
path('tools/export-database/', views.export_database, name='export_database'),
path('ui/help/', views.HelpView.as_view(), name='help'),
path('ui/settings/', views.SiteSettingsView.as_view(), name='site-settings'),
# Pages
path('ui/pages/', page_views.PageListView.as_view(), name='page-list'),
+16 -1
View File
@@ -4,7 +4,7 @@ from django.views import View # Add this import
from django.urls import reverse_lazy, reverse # Add 'reverse' here
from django.db.models import F, Count, Q, Case, When, Value, IntegerField
from django.db.models.functions import TruncDate
from .models import Link, ClickLog, LinkChangeLog, Page, Post
from .models import Link, ClickLog, LinkChangeLog, Page, Post, SiteSettings
from .forms import LinkForm, PageForm
import json
from django.core.serializers.json import DjangoJSONEncoder
@@ -533,6 +533,21 @@ def export_database(request):
class HelpView(TemplateView):
template_name = 'links/help.html'
class SiteSettingsView(View):
template_name = 'links/settings.html'
def get(self, request):
site_settings = SiteSettings.get()
return render(request, self.template_name, {'site_settings': site_settings})
def post(self, request):
site_settings = SiteSettings.get()
site_settings.public_sharing_domain = request.POST.get('public_sharing_domain', '').strip()
site_settings.save()
messages.success(request, _('Settings saved.'))
return redirect('site-settings')
@require_http_methods(["POST"])
def generate_tts(request, post_id):
"""Generate TTS audio for a post"""
+9
View File
@@ -177,6 +177,15 @@
{% trans "Help" %}
</div>
</a>
<a href="{% url 'site-settings' %}" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">
<div class="flex items-center">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4"/>
</svg>
{% trans "Settings" %}
</div>
</a>
</div>
</div>
<!-- 语言选择器 -->