MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Python使用Django框架实现博客系统

2024-12-115.7k 阅读

一、项目准备

  1. 环境搭建 确保你已经安装了Python和Django。如果没有安装,可以通过以下步骤进行安装:
pip install django
  1. 创建Django项目 在命令行中,切换到你想要创建项目的目录,然后使用以下命令创建一个新的Django项目,假设项目名为blog_project
django - admin startproject blog_project

这将在当前目录下创建一个名为blog_project的项目目录,其结构如下:

blog_project/
│
├── blog_project/
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   ├── wsgi.py
│   └── __init__.py
│
└── manage.py
  • manage.py:一个命令行工具,用于与项目进行各种交互,比如运行开发服务器、创建数据库迁移等。
  • blog_project/目录:包含项目的配置文件,如settings.py(项目的配置中心)、urls.py(URL映射配置)等。

二、创建博客应用

  1. 应用创建 在项目根目录(即包含manage.py的目录)下,使用以下命令创建一个名为blog的应用:
python manage.py startapp blog

这将创建一个blog应用目录,结构如下:

blog/
│
├── migrations/
│   └── __init__.py
│
├── __init__.py
├── admin.py
├── apps.py
├── models.py
├── tests.py
└── views.py
  • models.py:用于定义数据库模型。
  • views.py:包含处理用户请求并返回响应的视图函数。
  • admin.py:用于配置Django管理后台。
  1. 注册应用 打开项目的settings.py文件,在INSTALLED_APPS列表中添加'blog.apps.BlogConfig',如下所示:
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog.apps.BlogConfig',
]

这样Django就知道项目中包含了blog应用。

三、定义博客模型

  1. 模型设计 博客系统通常需要文章(Post)和分类(Category)等模型。在blog/models.py文件中定义如下:
from django.db import models
from django.contrib.auth.models import User
from django.utils.timezone import now


class Category(models.Model):
    name = models.CharField(max_length = 100)

    def __str__(self):
        return self.name


class Post(models.Model):
    title = models.CharField(max_length = 200)
    content = models.TextField()
    pub_date = models.DateTimeField(default = now)
    author = models.ForeignKey(User, on_delete = models.CASCADE)
    category = models.ForeignKey(Category, on_delete = models.SET_NULL, null = True)

    def __str__(self):
        return self.title
  • Category模型:name字段用于存储分类名称,__str__方法返回分类名称,方便在管理后台等地方显示。
  • Post模型:
    • title字段存储文章标题,max_length指定标题最大长度为200个字符。
    • content字段存储文章内容,使用TextField类型。
    • pub_date字段记录文章发布日期,默认值为当前时间。
    • author字段通过ForeignKey关联到Django内置的User模型,on_delete = models.CASCADE表示当关联的用户被删除时,该用户的所有文章也会被删除。
    • category字段通过ForeignKey关联到Category模型,on_delete = models.SET_NULLnull = True表示当分类被删除时,文章的分类字段设为NULL
  1. 数据库迁移 定义好模型后,需要将模型映射到数据库中。在命令行中执行以下命令:
python manage.py makemigrations
python manage.py migrate
  • makemigrations命令会检测模型的变化,并生成迁移文件,这些文件记录了如何将模型的变化应用到数据库中。
  • migrate命令会执行这些迁移文件,将模型变化真正应用到数据库中。

四、创建视图

  1. 文章列表视图blog/views.py文件中添加文章列表视图函数:
from django.shortcuts import render
from.models import Post


def post_list(request):
    posts = Post.objects.all()
    context = {'posts': posts}
    return render(request, 'blog/post_list.html', context)

这个视图函数获取所有的文章,并将其传递给名为blog/post_list.html的模板进行渲染。

  1. 文章详情视图 添加文章详情视图函数,用于显示单篇文章的详细内容:
from django.shortcuts import get_object_or_404, render
from.models import Post


def post_detail(request, pk):
    post = get_object_or_404(Post, pk = pk)
    context = {'post': post}
    return render(request, 'blog/post_detail.html', context)

这里使用get_object_or_404函数获取指定主键(pk)的文章,如果文章不存在则返回404页面。然后将文章传递给blog/post_detail.html模板。

五、配置URL

  1. 项目URL配置 打开项目的urls.py文件(blog_project/blog_project/urls.py),添加对blog应用URL的包含:
from django.contrib import admin
from django.urls import path, include


urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('blog.urls')),
]

path('', include('blog.urls'))表示将根路径('')下的URL请求转发到blog应用的URL配置中。

  1. 应用URL配置blog应用目录下创建urls.py文件,并添加以下内容:
from django.urls import path
from. import views


urlpatterns = [
    path('', views.post_list, name = 'post_list'),
    path('post/<int:pk>/', views.post_detail, name = 'post_detail'),
]
  • path('', views.post_list, name = 'post_list'):将根路径映射到post_list视图函数,name = 'post_list'为这个URL模式命名,方便在模板等地方引用。
  • path('post/<int:pk>/', views.post_detail, name = 'post_detail'):将形如post/1/(其中1为文章主键)的URL映射到post_detail视图函数,并将主键作为参数传递给视图。

六、创建模板

  1. 基础模板blog应用目录下创建templates/blog目录,然后在该目录下创建base.html文件,作为基础模板:
<!DOCTYPE html>
<html lang="zh - CN">

<head>
    <meta charset="UTF - 8">
    <meta name="viewport" content="width=device - width, initial - scale = 1.0">
    <title>博客系统</title>
    <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css">
</head>

<body>
    <div class="container">
        {% block content %}
        {% endblock %}
    </div>
    <script src="https://cdn.bootcdn.net/ajax/libs/bootstrap/5.3.0/js/bootstrap.min.js"></script>
</body>

</html>

这个模板使用了Bootstrap CSS框架来美化页面,并定义了一个content块,子模板可以在这个块中填充内容。

  1. 文章列表模板blog/templates/blog目录下创建post_list.html文件:
{% extends 'blog/base.html' %}

{% block content %}
    <h1>文章列表</h1>
    {% for post in posts %}
        <div class="card mb - 3">
            <div class="card - body">
                <h2 class="card - title"><a href="{% url 'post_detail' post.pk %}">{{ post.title }}</a></h2>
                <p class="card - text">{{ post.content|truncatechars:100 }}</p>
                <p class="card - text"><small class="text - body - secondary">发布时间: {{ post.pub_date }}</small></p>
            </div>
        </div>
    {% endfor %}
{% endblock %}
  • {% extends 'blog/base.html' %}:继承base.html模板。
  • {% for post in posts %}循环遍历传递过来的文章列表,{{ post.title }}显示文章标题,{{ post.content|truncatechars:100 }}显示文章内容的前100个字符,{{ post.pub_date }}显示发布时间。{% url 'post_detail' post.pk %}生成文章详情页面的URL。
  1. 文章详情模板 创建post_detail.html文件:
{% extends 'blog/base.html' %}

{% block content %}
    <h1>{{ post.title }}</h1>
    <p>{{ post.content }}</p>
    <p><small class="text - body - secondary">发布时间: {{ post.pub_date }}</small></p>
    <p><small class="text - body - secondary">作者: {{ post.author.username }}</small></p>
    <p><small class="text - body - secondary">分类: {{ post.category.name }}</small></p>
{% endblock %}

该模板显示文章的详细内容,包括标题、正文、发布时间、作者和分类。

七、管理后台配置

  1. 注册模型 打开blog/admin.py文件,注册CategoryPost模型:
from django.contrib import admin
from.models import Category, Post


admin.site.register(Category)
admin.site.register(Post)

这样在Django管理后台就可以对分类和文章进行管理了。

  1. 自定义管理界面 可以对管理界面进行自定义,比如在文章管理页面显示更多信息。修改admin.py文件如下:
from django.contrib import admin
from.models import Category, Post


class PostAdmin(admin.ModelAdmin):
    list_display = ('title', 'author', 'pub_date')
    search_fields = ('title', 'content')


admin.site.register(Category)
admin.site.register(Post, PostAdmin)
  • list_display指定在文章列表页面显示的字段。
  • search_fields指定可以在管理后台搜索文章的字段。

八、用户认证与授权

  1. 用户注册 虽然Django自带用户认证系统,但我们可以创建一个简单的用户注册页面。在blog应用的views.py文件中添加注册视图函数:
from django.shortcuts import render, redirect
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import login


def register(request):
    if request.method == 'POST':
        form = UserCreationForm(request.POST)
        if form.is_valid():
            user = form.save()
            login(request, user)
            return redirect('post_list')
    else:
        form = UserCreationForm()
    context = {'form': form}
    return render(request, 'blog/register.html', context)
  • 如果请求方法是POST,表示用户提交了注册表单,验证表单数据,如果有效则保存用户并登录,然后重定向到文章列表页面。
  • 如果请求方法是GET,则显示空的注册表单。
  1. 注册模板blog/templates/blog目录下创建register.html文件:
{% extends 'blog/base.html' %}

{% block content %}
    <h1>注册</h1>
    <form method="post">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit" class="btn btn - primary">注册</button>
    </form>
{% endblock %}

这里使用Django自带的UserCreationForm{{ form.as_p }}将表单字段以段落形式显示,{% csrf_token %}用于防止跨站请求伪造。

  1. 登录与注销 Django自带了登录和注销视图,我们只需要配置URL和模板即可。在blog/urls.py文件中添加:
from django.urls import path
from. import views
from django.contrib.auth.views import LoginView, LogoutView


urlpatterns = [
    path('', views.post_list, name = 'post_list'),
    path('post/<int:pk>/', views.post_detail, name = 'post_detail'),
    path('register/', views.register, name ='register'),
    path('login/', LoginView.as_view(template_name = 'blog/login.html'), name = 'login'),
    path('logout/', LogoutView.as_view(next_page = 'post_list'), name = 'logout'),
]
  • LoginView.as_view(template_name = 'blog/login.html')指定登录视图使用的模板为blog/login.html
  • LogoutView.as_view(next_page = 'post_list')指定注销后重定向到文章列表页面。
  1. 登录模板blog/templates/blog目录下创建login.html文件:
{% extends 'blog/base.html' %}

{% block content %}
    <h1>登录</h1>
    <form method="post">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit" class="btn btn - primary">登录</button>
    </form>
{% endblock %}

同样使用Django自带的登录表单,以段落形式显示表单字段。

九、添加文章功能

  1. 添加文章视图blog/views.py文件中添加添加文章的视图函数:
from django.shortcuts import render, redirect
from.forms import PostForm
from.models import Post
from django.contrib.auth.decorators import login_required


@login_required
def add_post(request):
    if request.method == 'POST':
        form = PostForm(request.POST)
        if form.is_valid():
            post = form.save(commit = False)
            post.author = request.user
            post.save()
            return redirect('post_list')
    else:
        form = PostForm()
    context = {'form': form}
    return render(request, 'blog/add_post.html', context)
  • @login_required装饰器确保只有登录用户才能访问这个视图。
  • 如果是POST请求,验证表单数据,保存文章时先不提交到数据库(commit = False),设置作者为当前登录用户后再保存。
  • 如果是GET请求,显示空的文章表单。
  1. 文章表单blog应用目录下创建forms.py文件,并添加以下内容:
from django import forms
from.models import Post, Category


class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ['title', 'content', 'category']

这里使用ModelForm根据Post模型创建表单,指定了表单包含的字段。

  1. 添加文章模板blog/templates/blog目录下创建add_post.html文件:
{% extends 'blog/base.html' %}

{% block content %}
    <h1>添加文章</h1>
    <form method="post">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit" class="btn btn - primary">提交</button>
    </form>
{% endblock %}

以段落形式显示文章表单字段。

  1. 在模板中添加链接post_list.html模板中添加“添加文章”链接,方便用户添加新文章:
{% extends 'blog/base.html' %}

{% block content %}
    <h1>文章列表</h1>
    <a href="{% url 'add_post' %}" class="btn btn - primary mb - 3">添加文章</a>
    {% for post in posts %}
        <div class="card mb - 3">
            <div class="card - body">
                <h2 class="card - title"><a href="{% url 'post_detail' post.pk %}">{{ post.title }}</a></h2>
                <p class="card - text">{{ post.content|truncatechars:100 }}</p>
                <p class="card - text"><small class="text - body - secondary">发布时间: {{ post.pub_date }}</small></p>
            </div>
        </div>
    {% endfor %}
{% endblock %}

{% url 'add_post' %}生成添加文章页面的URL。

十、部署博客系统

  1. 静态文件处理 在生产环境中,需要正确处理静态文件(如CSS、JavaScript等)。在settings.py文件中配置静态文件相关设置:
STATIC_URL ='static/'
STATIC_ROOT = BASE_DIR /'staticfiles'

STATIC_URL指定静态文件在浏览器中的访问URL前缀,STATIC_ROOT指定收集静态文件的目录。

然后在项目根目录下执行以下命令收集静态文件:

python manage.py collectstatic

这会将所有应用中的静态文件收集到staticfiles目录中。

  1. 选择服务器 常见的选择有Gunicorn和uWSGI。以Gunicorn为例,首先安装Gunicorn:
pip install gunicorn

假设项目名为blog_project,在项目根目录下创建一个启动脚本,比如start.sh,内容如下:

#!/bin/bash
gunicorn blog_project.wsgi:application --bind 0.0.0.0:8000

赋予脚本执行权限:

chmod +x start.sh

然后就可以通过./start.sh启动Gunicorn服务器,将博客系统部署到0.0.0.0:8000地址上。

  1. 配置Web服务器(以Nginx为例) 安装Nginx后,配置Nginx反向代理到Gunicorn服务器。在Nginx配置文件(通常在/etc/nginx/sites - available/目录下)中添加如下内容:
server {
    listen 80;
    server_name your_domain.com;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X - Real - IP $remote_addr;
        proxy_set_header X - Forwarded - For $proxy_add_x_forwarded_for;
        proxy_set_header X - Forwarded - Proto $scheme;
    }

    location /static/ {
        alias /path/to/your/project/staticfiles/;
    }
}
  • listen 80:监听80端口。
  • server_name your_domain.com:替换为你的域名。
  • proxy_pass:将请求转发到Gunicorn服务器。
  • location /static/:配置静态文件的访问路径。

最后通过软链接将配置文件链接到/etc/nginx/sites - enabled/目录,并重启Nginx服务:

ln -s /etc/nginx/sites - available/your_config /etc/nginx/sites - enabled/
sudo systemctl restart nginx

这样,你的博客系统就可以通过域名正常访问了。

通过以上步骤,我们使用Django框架成功实现了一个简单的博客系统,涵盖了文章的展示、用户认证、文章添加等常见功能,并介绍了如何将其部署到生产环境中。在实际应用中,还可以根据需求进一步扩展和优化,比如添加评论功能、优化性能等。