首页 > 其他分享 >每天40分玩转Django:Django插件开发

每天40分玩转Django:Django插件开发

时间:2025-01-05 10:31:28浏览次数:3  
标签:comment 插件 generic py comments Django models 40 import

Django插件开发

一、插件开发概述表

阶段主要任务技术要点难度
准备工作项目结构设计、环境配置项目布局、setup.py★★★☆☆
开发实现功能开发、测试编写Django AppConfig、Signals★★★★☆
文档编写API文档、使用说明Markdown、reStructuredText★★★☆☆
发布部署PyPI打包、发布setuptools、twine★★★★☆

二、创建可重用Django应用

我们以一个通用的评论系统插件为例,演示如何创建可重用的Django应用。

2.1 项目结构

django-generic-comments/
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
├── generic_comments/
│   ├── __init__.py
│   ├── apps.py
│   ├── models.py
│   ├── views.py
│   ├── urls.py
│   ├── forms.py
│   ├── signals.py
│   ├── templates/
│   │   └── generic_comments/
│   │       ├── comment_form.html
│   │       └── comment_list.html
│   └── static/
│       └── generic_comments/
│           ├── css/
│           └── js/
└── tests/
    ├── __init__.py
    ├── test_models.py
    └── test_views.py

2.2 核心代码实现

# generic_comments/apps.py
from django.apps import AppConfig

class GenericCommentsConfig(AppConfig):
    name = 'generic_comments'
    verbose_name = 'Generic Comments'
    
    def ready(self):
        import generic_comments.signals
# generic_comments/models.py
from django.db import models
from django.conf import settings
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType

class Comment(models.Model):
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')
    
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    is_public = models.BooleanField(default=True)
    
    class Meta:
        ordering = ['-created_at']
        
    def __str__(self):
        return f'Comment by {self.user.username} on {self.content_object}'
# generic_comments/forms.py
from django import forms
from .models import Comment

class CommentForm(forms.ModelForm):
    class Meta:
        model = Comment
        fields = ['content']
        widgets = {
            'content': forms.Textarea(attrs={'rows': 4})
        }
# generic_comments/views.py
from django.shortcuts import redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.contrib.contenttypes.models import ContentType
from django.contrib import messages
from .forms import CommentForm
from .signals import comment_posted

@login_required
def add_comment(request, content_type_id, object_id):
    content_type = get_object_or_404(ContentType, id=content_type_id)
    content_object = content_type.get_object_for_this_type(id=object_id)
    
    if request.method == 'POST':
        form = CommentForm(request.POST)
        if form.is_valid():
            comment = form.save(commit=False)
            comment.user = request.user
            comment.content_type = content_type
            comment.object_id = object_id
            comment.save()
            
            # 触发评论发布信号
            comment_posted.send(
                sender=comment.__class__,
                comment=comment,
                request=request
            )
            
            messages.success(request, '评论已发布')
            return redirect(content_object.get_absolute_url())
    else:
        form = CommentForm()
        
    return render(request, 'generic_comments/comment_form.html', {
        'form': form,
        'content_object': content_object
    })
# generic_comments/signals.py
from django.dispatch import Signal

comment_posted = Signal()

# 信号接收器示例
def notify_comment_posted(sender, comment, request, **kwargs):
    """当评论发布时发送通知"""
    pass

2.3 配置文件

# setup.py
from setuptools import setup, find_packages

setup(
    name='django-generic-comments',
    version='0.1.0',
    packages=find_packages(exclude=['tests*']),
    include_package_data=True,
    license='MIT',
    description='A Django app for adding comments to any model',
    long_description=open('README.md').read(),
    long_description_content_type='text/markdown',
    url='https://github.com/yourusername/django-generic-comments',
    author='Your Name',
    author_email='your.email@example.com',
    classifiers=[
        'Environment :: Web Environment',
        'Framework :: Django',
        'Framework :: Django :: 3.2',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: MIT License',
        'Operating System :: OS Independent',
        'Programming Language :: Python',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.8',
        'Topic :: Internet :: WWW/HTTP',
        'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
    ],
    python_requires='>=3.8',
    install_requires=[
        'Django>=3.2',
    ],
)
# MANIFEST.in
include LICENSE
include README.md
recursive-include generic_comments/static *
recursive-include generic_comments/templates *
recursive-include docs *

三、应用开发流程图

在这里插入图片描述

四、测试用例编写

# tests/test_models.py
from django.test import TestCase
from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType
from generic_comments.models import Comment

User = get_user_model()

class CommentModelTest(TestCase):
    def setUp(self):
        self.user = User.objects.create_user(
            username='testuser',
            email='test@example.com',
            password='testpass123'
        )
        
    def test_comment_creation(self):
        comment = Comment.objects.create(
            user=self.user,
            content='Test comment',
            content_type=ContentType.objects.get_for_model(User),
            object_id=self.user.id
        )
        
        self.assertEqual(str(comment), f'Comment by testuser on {self.user}')
        self.assertTrue(comment.is_public)
# tests/test_views.py
from django.test import TestCase, Client
from django.urls import reverse
from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType
from generic_comments.models import Comment

User = get_user_model()

class CommentViewsTest(TestCase):
    def setUp(self):
        self.client = Client()
        self.user = User.objects.create_user(
            username='testuser',
            password='testpass123'
        )
        
    def test_add_comment(self):
        self.client.login(username='testuser', password='testpass123')
        
        content_type = ContentType.objects.get_for_model(User)
        response = self.client.post(
            reverse('generic_comments:add_comment', kwargs={
                'content_type_id': content_type.id,
                'object_id': self.user.id
            }),
            {'content': 'Test comment'}
        )
        
        self.assertEqual(response.status_code, 302)
        self.assertEqual(Comment.objects.count(), 1)

五、文档编写

# Django Generic Comments

A reusable Django application for adding comments to any model.

## Installation

```bash
pip install django-generic-comments

Quick Start

  1. Add “generic_comments” to your INSTALLED_APPS setting:
INSTALLED_APPS = [
    ...
    'generic_comments',
]
  1. Include the generic_comments URLconf in your project urls.py:
path('comments/', include('generic_comments.urls')),
  1. Run migrations:
python manage.py migrate

Usage

To add comments to a model:

from django.contrib.contenttypes.fields import GenericRelation
from generic_comments.models import Comment

class YourModel(models.Model):
    comments = GenericRelation(Comment)

## 六、发布到PyPI

### 6.1 打包准备

1. 安装必要工具:
```bash
pip install setuptools wheel twine
  1. 创建分发包:
python setup.py sdist bdist_wheel
  1. 上传到PyPI:
twine upload dist/*

6.2 发布检查清单

  1. 代码质量检查:
# 运行测试
python runtests.py

# 代码风格检查
flake8 generic_comments
  1. 文档完整性检查:
  • README.md 是否完整
  • 使用说明是否清晰
  • API文档是否完整
  1. 版本号管理:
# generic_comments/__init__.py
VERSION = (0, 1, 0)
__version__ = '.'.join(map(str, VERSION))

七、使用示例

7.1 在项目中集成

# settings.py
INSTALLED_APPS = [
    ...
    'generic_comments',
]

# 可选配置
GENERIC_COMMENTS_CONFIG = {
    'moderate_comments': False,
    'email_notifications': True,
}

# models.py
from django.db import models
from django.contrib.contenttypes.fields import GenericRelation
from generic_comments.models import Comment

class Article(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    comments = GenericRelation(Comment)
    
    def get_absolute_url(self):
        return reverse('article_detail', args=[self.id])

7.2 模板使用

{% load generic_comments_tags %}

<div class="comments">
    {% get_comment_list for article as comments %}
    
    {% for comment in comments %}
        <div class="comment">
            <div class="comment-user">{{ comment.user }}</div>
            <div class="comment-content">{{ comment.content }}</div>
            <div class="comment-date">{{ comment.created_at|date:"Y-m-d H:i" }}</div>
        </div>
    {% endfor %}
    
    {% if user.is_authenticated %}
        {% get_comment_form for article as form %}
        <form method="post" action="{% url 'generic_comments:add_comment' content_type_id=content_type.id object_id=article.id %}">
            {% csrf_token %}
            {{ form.as_p }}
            <button type="submit">提交评论</button>
        </form>
    {% endif %}
</div>

八、最佳实践建议

  1. 代码组织:

    • 遵循Django应用规范
    • 保持代码模块化
    • 使用合适的设计模式
  2. 测试覆盖:

    • 编写完整的单元测试
    • 包含集成测试
    • 测试边界情况
  3. 文档维护:

    • 详细的安装说明
    • 清晰的API文档
    • 丰富的使用示例
  4. 版本控制:

    • 语义化版本号
    • 更新日志维护
    • 分支管理策略

本节课程介绍了如何开发和发布一个Django可重用应用。通过具体的评论系统示例,展示了从开发到发布的完整流程。建议学习者在实践中注意以下几点:

  1. 充分考虑应用的可复用性和扩展性
  2. 编写完整的测试和文档
  3. 遵循Python包发布的最佳实践
  4. 持续维护和更新应用

怎么样今天的内容还满意吗?再次感谢朋友们的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!

标签:comment,插件,generic,py,comments,Django,models,40,import
From: https://blog.csdn.net/weixin_40780178/article/details/144941996

相关文章

  • 你有写过vs code插件吗?
    很抱歉,虽然我可以提供关于编写VSCode插件的建议和指导,但我本身并没有实际编写过VSCode插件。不过,我可以向你介绍一些编写VSCode插件的基本概念和步骤,帮助你入门和提高。VSCode插件通常使用TypeScript或JavaScript编写,并且需要遵循VSCode扩展API的规范。以下......
  • 7-406 三七二十一
    某天,诺诺看到三七二十一(3721)数,觉得很神奇,这种数除以3余2,而除以7则余1。例如8是一个3721数,因为8除以3余2,8除以7余1。现在给出两个整数a、b,求区间[a,b]中的所有3721数,若区间内不存在3721数则输出none。输入格式:首先输入一个正整数T,表示测试数据的组数,然后是T组测试数据。每组测......
  • 7-403 互质数
    Sg认识到互质数很有用。若两个正整数的最大公约数为1,则它们是互质数。要求编写函数判断两个整数是否互质数。输入格式:首先输入一个正整数T,表示测试数据的组数,然后是T组测试数据。每组测试先输入1个整数n(1≤n≤100),再输入n行,每行有一对整数a、b(0<a,b<109)。输出格式......
  • 7-402 纵横
    莫大侠练成纵横剑法,走上了杀怪路,每次仅出一招。这次,他遇到了一个正方形区域,由n×n个格子构成,每个格子(行号、列号都从1开始编号)中有若干个怪。莫大侠施展幻影步,抢占了一个格子,使出绝招“横扫四方”,就把他上、下、左、右四个直线方向区域内的怪都灭了(包括抢占点的怪)。请帮他算算......
  • Python+Django+Mysql开发个性化旅游酒店推荐系统 python在线酒店推荐系统设计开发 可
    Python+Django+Mysql开发个性化旅游酒店推荐系统python在线酒店推荐系统设计开发可视化、爬虫协同过滤推荐算法机器学习深度学习人工智能大数据开发教程文档HotelRecommendSysPy一、项目简介1、开发工具和使用技术Python3及以上版本,Django3.6及以上版本,mysql8,nav......
  • Python系列之例题100题(36-40题)
    Hello!友友们,话不多说直接干题!!!36:有序列表添加数据:有一个已经排好序的列表。现输入一个数,要求按原来的规律将它插入数组中。list=[1,3,8,20,40]n=int(input('请输入数据:'))list.append(n)list.sort()print(list)37:变量值互换:给定两个变量交换他们的值。a=5b=......
  • SquareLine Studio教程 图形化 LVGL 移植实际硬件 RP2040
    1.SquareLineStudio的配置如下图所示,如果你用的是ESP32S3等开发板,配置也非常简单,只需要改boardgroup即可,相对的开发环境也可以选择,笔者这边用的是RP2040这个新推出的开发板作为示例,就选择arduinowithTFT_eSPI环境了。 2.如下为我的ui界面,随便拖一个作为示例,如下所示:3.......
  • Spark职位信息推荐系统 协同过滤推荐算法 Echarts可视化 Django框架 简历投递 大数据
    博主介绍:✌全网粉丝10W+,前互联网大厂软件研发、集结硕博英豪成立工作室。专注于计算机相关专业项目实战6年之久,选择我们就是选择放心、选择安心毕业✌>......
  • 基于python+Django+mysql在线外卖点餐订餐网站系统设计与实现
     博主介绍:黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育、辅导。所有项目都配有从入门到精通的基础知识视频课程,学习后应对毕业设计答辩,提供核心代码讲解,答辩指导。项目配有对应开发......
  • 20241403《计算机基础与程序设计》课程总结
    20241403《计算机基础与程序设计》课程总结每周作业链接汇总第一周作业:【内容概要】课程概论第二周作业:【内容概要】①数字化②信息安全③自学教材第三周作业:【内容概要】①掌握门和电路②学习计算机部件③了解冯·诺依曼体系结构④学习C语言基础知识,第四周作业:......