Django基础教程(七十九)Django友情链接组件之实现友情链接前端组件:Django友情链接别再硬编码了!手摸手教你造个会“呼吸”的组件,PM看了直呼内行

一、 开篇吐槽:谁还没被友情链接“坑”过?

兄弟们,不知道你们有没有这种经历:心血来潮建了个个人博客,或者好不容易搞了个小项目站。某天,好基友A跑来:“哥们儿,加个友情链接呗!”你爽快答应,打开模板文件,找到底部那坨HTML,吭哧吭哧加上一行 <a href="...">基友A的站</a>

没过两天,好基友B也来了。你又重复一遍操作。后来,基友C的站打不开了,你得去手动删掉;基友A换域名了,你又得去手动修改……

此时的你,内心OS大概是: 我就想安安静静写个代码,怎么沦为了一个无情的“链接更新工人”?这玩意儿明明就是个简单的列表,为啥每次改动都像在给心脏做搭桥手术?

别慌!今天,咱们就要把这个“远古”流程彻底现代化。我们要实现的,是一个后台动态管理、前端自动渲染、还带点小酷炫效果的友情链接组件!从此,PM(或者就是你自个儿)在后台点点鼠标,前端就能优雅地展示出来,你再也不用碰那“脏兮兮”的模板代码了。

二、 后端基石:把链接“调教”成温顺的数据

前端再花哨,也得有坚实的数据支撑。咱们先花几分钟,用Django的模型(Model)给友情链接建个“户口本”。

1. 模型设计:咱们的链接得有“身份证”

我们不仅要存链接和名字,还得考虑点儿高级货,比如Logo、描述、是否展示等。打开你的 models.py,来这么一段:

from django.db import models

class FriendLink(models.Model):
    # 链接名字,比如“老张的胡思乱想”
    name = models.CharField(max_length=50, verbose_name="网站名称")
    # 完整的网址,别忘了https://
    url = models.URLField(verbose_name="网址")
    # 不是必须的,但有个Logo会显得很专业
    logo = models.ImageField(upload_to='friend_logo/', blank=True, null=True, verbose_name="网站Logo")
    # 一段简短的描述,鼠标放上去能看到,提升逼格
    description = models.CharField(max_length=200, blank=True, verbose_name="描述")
    # 控制是否显示,不想展示某个链接时不用删除,勾掉就行
    is_active = models.BooleanField(default=True, verbose_name="是否激活")
    # 创建时间,可以用来排序
    created_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")

    class Meta:
        verbose_name = "友情链接"
        verbose_name_plural = verbose_name
        ordering = ['-created_time']  # 默认按创建时间倒序排列

    def __str__(self):
        return self.name  # 在后台显示时,直接显示网站名,清晰明了

2. 视图函数:只吐出我们需要的“干货”

数据有了,怎么给前端呢?我们写一个超级简单的视图,只做一件事:把激活的友情链接,打包成JSON格式的数据扔给前端。在 views.py 里:

from django.http import JsonResponse
from .models import FriendLink

def friendlinks_json(request):
    """
    专门用于提供友情链接JSON数据的视图
    """
    # 从数据库里捞出所有“激活”的链接
    links = FriendLink.objects.filter(is_active=True)
    # 把QuerySet对象转换成字典列表,方便序列化成JSON
    data = list(links.values('name', 'url', 'logo', 'description'))
    return JsonResponse(data, safe=False)  # safe=False允许我们返回列表而非字典

3. URL配置:给前端一个“接头地址”

光有视图不行,得告诉Django哪个网址能访问到这个数据。在 urls.py 里加一条:

from django.urls import path
from . import views

urlpatterns = [
    # ... 你其他的url配置
    path('api/friendlinks/', views.friendlinks_json, name='friendlinks_api'),
]

搞定!现在,任何人访问 /api/friendlinks/,就能拿到一份纯正的、热乎乎的友情链接JSON数据了。后端部分,宣告完工!是不是So easy?

三、 前端魔术:让链接列表“活”起来

重头戏来了!前方高能,我们将用纯原生JavaScript和CSS,打造一个低耦合、高颜值的友情链接组件。

1. HTML结构:搭好舞台

我们打算在页面某个地方(比如侧边栏或底部)留一个“坑”,这个坑将来会被我们的友情链接组件自动填充。

<!-- 在你想要展示友情链接的地方,比如sidebar或footer里,放上这个div -->
<aside class="friend-links-container">
    <h3>🌟 小伙伴们</h3>
    <!-- 这个ul就是为我们动态生成的链接列表准备的容器 -->
    <ul id="friend-links-list"></ul>
    <!-- 再来一个加载中的提示,很贴心有木有 -->
    <p id="links-loading">友情链接加载中...</p>
</aside>

2. CSS样式:颜值即正义

光有骨架不行,得给它穿上好看的衣服。我们来写点现代感的CSS:

/* 友情链接容器样式 */
.friend-links-container {
    background: #f9f9f9;
    border-radius: 12px;
    padding: 1.5rem;
    margin-top: 2rem;
    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
}

.friend-links-container h3 {
    margin-top: 0;
    color: #333;
    border-bottom: 2px solid #eee;
    padding-bottom: 0.5rem;
}

/* 链接列表样式 */
#friend-links-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: grid; /* 使用Grid布局,自动适配,比Float不知道高到哪里去了 */
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 1rem;
}

/* 每个链接项的样式 */
.friend-link-item {
    background: white;
    border-radius: 8px;
    padding: 1rem;
    transition: all 0.3s ease; /* 过渡动画,让交互更丝滑 */
    border: 1px solid #eaeaea;
}

.friend-link-item:hover {
    transform: translateY(-3px); /* 悬停时微微上浮 */
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.1);
    border-color: #4a90e2; /* 悬停时边框变蓝色 */
}

/* 链接本身的样式 */
.friend-link {
    display: flex;
    align-items: center;
    text-decoration: none;
    color: #555;
}

/* Logo的小图样式 */
.friend-logo {
    width: 24px;
    height: 24px;
    border-radius: 4px;
    margin-right: 0.75rem;
    object-fit: cover; /* 防止图片被拉伸 */
}

/* 网站名字样式 */
.friend-name {
    font-weight: 600;
    font-size: 0.95rem;
}

/* 加载中的文字样式 */
#links-loading {
    text-align: center;
    color: #999;
    font-style: italic;
}

3. JavaScript:注入灵魂的时刻

最后,就是让这一切动起来的魔法——JavaScript。我们会用 fetch API 去我们刚才定义的后端接口“取数据”。

// 等待整个页面的DOM内容加载完毕再执行我们的脚本
document.addEventListener('DOMContentLoaded', function() {
    const listElement = document.getElementById('friend-links-list');
    const loadingElement = document.getElementById('links-loading');

    // 发起fetch请求,获取数据
    fetch('/api/friendlinks/')  // 这里就是我们在urls.py里配置的地址
        .then(response => {
            if (!response.ok) {
                throw new Error('网络响应不正常');
            }
            return response.json(); // 解析JSON数据
        })
        .then(links => {
            // 先隐藏加载中的提示
            loadingElement.style.display = 'none';

            // 如果拿到了数据且数据长度大于0
            if (links && links.length > 0) {
                // 遍历每一条链接数据
                links.forEach(link => {
                    // 创建一个li元素
                    const li = document.createElement('li');
                    li.className = 'friend-link-item';

                    // 创建a标签
                    const a = document.createElement('a');
                    a.href = link.url;
                    a.className = 'friend-link';
                    a.target = '_blank'; // 在新窗口打开
                    a.rel = 'noopener noreferrer'; // 安全措施,防钓鱼
                    a.title = link.description || link.name; // 鼠标悬停显示描述

                    // 组装HTML内容
                    let htmlContent = '';
                    if (link.logo) {
                        // 如果有Logo,就加上图片
                        htmlContent += `<img src="${link.logo}" alt="${link.name}" class="friend-logo">`;
                    }
                    htmlContent += `<span class="friend-name">${link.name}</span>`;

                    a.innerHTML = htmlContent;
                    li.appendChild(a);
                    listElement.appendChild(li);
                });
            } else {
                // 如果没有数据,显示一个友好的提示
                listElement.innerHTML = '<li>暂无友情链接</li>';
            }
        })
        .catch(error => {
            // 如果请求失败,打印错误并提示用户
            console.error('获取友情链接失败:', error);
            loadingElement.textContent = '友情链接加载失败,请刷新试试~';
        });
});
四、 完整示例:Copy/Paste就能跑

理论说再多,不如一个完整的例子来得实在。假设你有一个 base.html 模板,可以这样整合:

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <title>我的酷站</title>
    <style>
        /* 把上面那坨CSS代码原封不动地拷贝到这里 */
        .friend-links-container { ... }
        /* ... 省略其他CSS,为了篇幅,但你懂的,要全拷过来 */
    </style>
</head>
<body>
    <header>...</header>
    <main>...</main>
    <footer>
        <!-- 这里是我们的友情链接组件 -->
        <aside class="friend-links-container">
            <h3>🌟 小伙伴们</h3>
            <ul id="friend-links-list"></ul>
            <p id="links-loading">友情链接加载中...</p>
        </aside>
    </footer>
    <script>
        // 把上面那坨JavaScript代码原封不动地拷贝到这里
        document.addEventListener('DOMContentLoaded', function() { ... });
    </script>
</body>
</html>

使用步骤:

  1. 将模型、视图、URL配置好,并运行 python manage.py makemigrationsmigrate
  2. 去Django自带的后台,创建几条 FriendLink 数据,记得勾选 is_active
  3. 将上面的完整HTML示例放到你的模板中。
  4. 访问你的网站,刷新页面,就能看到动态加载、带悬停效果的友情链接了!
五、 总结与升华

你看,我们就这样,从一个令人烦躁的重复劳动中,解放了出来!

  • 对站长/你: 以后增删改链接,只需要在Django后台动动手指,前端自动同步,维护成本几乎为零。
  • 对用户: 看到了一个更具动态感和交互性的组件,体验Up!Up!
  • 对SEO: 由于链接是JavaScript动态加载的,对于搜索引擎爬虫,可以考虑使用服务端渲染(SSR)或动态渲染技术来优化,这是后话,但我们的架构为这种进阶玩法留足了空间。

所以,别再傻乎乎地硬编码了!拥抱动态组件,让你的Django项目更智能、更优雅。这一个小小的组件,体现的是前端与后端分离的思想,是追求效率和体验的工匠精神。

快去你的项目里试试吧,保证你用过之后,再也不想回到“原始社会”了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

值引力

持续创作,多谢支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值