个人博客项目

个人博客项目:

主要使用django2.2.3+pycharm+sqlite3完成,
注:此篇文章只是自己用来记录笔记的,若有疑问,联系13484413532

最后结果图:
在这里插入图片描述
s-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDc5OTEzOQ==,size_16,color_FFFFFF,t_70)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
一、分析项目需求
1、能够实现用户的登录、注册、注销等功能
2、只有登录上去才可以能够修改自己的个人信息,头像等
3、登录后可以写博客,
4、首页展示点击量最高的三篇文章和按时间顺序写的文章并且点击可以查看详情
5、可以按标签浏览文章并且分页展示

然后创建django项目:blogs
更改配置文件

STATIC_URL = '/static/'
STATICFILES_DIRS = (os.path.join(BASE_DIR,'static'),)      #开发中的创建静态配置
#STATIC_ROOT = os.path.join(BASE_DIR,'static')  #实际中的配置

二、需要的表
1、用户表UserProfile:
创建app—>blog
在model.py文件里创建UserProfile:

from django.db import models
from django.contrib.auth.models import AbstractUser

class UserProfile(AbstractUser):
    mobile = models.CharField(max_length=11,
                              verbose_name = '手机号码',
                              unique=True
                              )
    icon = models.ImageField(upload_to='uploads/%Y/%m/%d',default='upload/orages.PNG')
    email = models.EmailField()
    class Meta:
        db_table : 'UserProfile'
        verbose_name = '用户表'
        verbose_name_plural = verbose_name

我继承的是AbstractUser,并且定义为用户表
但是这里一定需要在settings.py里更改为以下:

AUTH_USER_MODEL = 'blog.UserProfile'

然后进行迁移和同步:

python manage.py makemigrations
python manage.py migration

2、用户注册表与登录表:
在app中创建一个form.py文件,定义用户注册表

#用户注册表单
class UserRegisterForm(Form):
    username =forms.CharField(max_length=14,min_length=6,
                              error_messages={'min_length':'用户名最少6位',
                                              'max_length':'用户名最大14位'},label='用户名')
    email = forms.EmailField(max_length=30,min_length=6,error_messages={'required':'必须填写邮箱',},label='邮箱')
    password = forms.CharField(max_length=14,min_length=6,error_messages={'required':'必须填写密码',},label='密码')
    mobile = forms.CharField(max_length=11,min_length=10,error_messages={'required':'必须填写手机号码',},label='手机号码')


class RegisterForm(ModelForm):
    class Meta:
        model =UserProfile
        # fields ='__all__'
        #exclude = ['']  两个搭配使用意为使用除去exclude里的字段的其他字段
        fields = ['username','email','password','mobile']
    # def clean_username(self):
    #     username = self.cleaned_data.get('username')
    #     result = re.match(r'[a-zA-Z]\w{5}',username)
    #     #username 要以字母开头后面的是字母下划线或者数字加5位数
    #     if not result:
    #        raise ValidationError('用户名必需以字母开头')#如果没有匹配到就抛出异常语句
    #     return username

 #用户登录表单
class LoginForm(Form):
    username = forms.CharField(max_length=14, min_length=6,
                               label='用户名')
    password = forms.CharField(max_length=14, min_length=6,
                               error_messages={'required': '必须填写密码', }, label='密码'
                               )
    def clean_username(self):
        username = self.cleaned_data.get('username')
        if not UserProfile.objects.filter(username=username).exists():
            raise ValidationError('!!!')
        return username

不要忘记在url中配置路由:
我用的是路由分发:

urlpatterns = [
    path('admin/', admin.site.urls),     #后台管理的路由
    path('blog/',include('blog.urls',namespace='blog')),    #app---blog的路由
    path('article/',include('article.urls',namespace='article')),    #app--article的路由
    re_path(r'^media/(?P<path>.*)$',serve,{'document_root':MEDIA_ROOT}),     #静态文件的路由
    re_path(r'^ckeditor/',include('ckeditor_uploader.urls')),# 富文本编辑  加载上传时默认路径

]
#blog的路由配置
  urlpatterns=[
    path('register',user_register,name='register'),   #用户注册
    path('login',user_login,name='login'),  #用户登录
    path('logout',user_logout,name='logout'),  #用户注销
    path('about',user_about,name='about'),  #关于作者
    path('center',user_center,name='center'),  #用户中心
    path('index',user_index,name='index'),  #博客首页
]    

然后写视图函数:

from django.contrib.auth import logout,login,authenticate
from django.contrib.auth.decorators import login_required

from django.contrib.auth.hashers import make_password, check_password
from django.http import JsonResponse
from django.shortcuts import HttpResponse, render, redirect
from django.urls import reverse

from article.models import Article
from blog.form import RegisterForm, LoginForm
from blog.models import UserProfile


# 最初页面
def user_index(request):
    farticles = Article.objects.all().order_by('-click_num') #以少的点击量进行排序
    darticles = Article.objects.all().order_by('-date')[:3]
    return render(request, 'user/index.html',
                  context={'figure_article':farticles[:3],'darticle':darticles})

# 注册页面
def user_register(request):
    if request.method == 'GET':
        rform = RegisterForm(request.POST)
        return render(request, 'user/register.html',context={"rform":rform})
    else:
        rform = RegisterForm(request.POST)  # 使用form获取数据,
        # 想要在前端使用:return render(request, 'user/register.html',context={"rform":rform})
        if rform.is_valid():#进行数据的校验
            # 校验成功从前端取数据
            username = rform.cleaned_data.get('username')
            password = rform.cleaned_data.get('password')
            mobile = rform.cleaned_data.get('mobile')
            email = rform.cleaned_data.get('email')
            if UserProfile.objects.filter(username=username).exists():
                return render(request, 'user/register.html', context={'msg': '用户名已经存在'})
            else:
                # 如果校验成功把数据存入数据库
                password = make_password(password)  # 对密码进行加密
                user = UserProfile.objects.create(username=username, password=password,
                                                  email=email, mobile=mobile)
                if user:
                    return render(request, 'user/login.html')
        return render(request,'user/register.html',context={'msg':'用户名与密码最少6位最大14位,手机号码11位'})
            #不使用form提交数据
            # username =request.POST.get('username')
            # password = request.POST.get('password')
            # mobile = request.POST.get('mobile')
            # email = request.POST.get('email')
            # password = make_password(password)  # 对密码进行加密
            # user = UserProfile.objects.create(username=username, password=password,
            #                                           email=email, mobile=mobile)
            # if user:
            #     return HttpResponse('注册成功')
            # else:
            #     return render(request, 'user/register.html')

#用户登录
def user_login(request):
    if request.method == 'GET':
        return render(request,'user/login.html')
    else:
        lform = LoginForm(request.POST)
        if lform.is_valid():
            username = lform.cleaned_data.get('username')
            password = lform.cleaned_data.get('password')
            #进行数据库的查询
            #方式1
            #user = UserProfile.objects.filter(username=username).first()
            # flag = check_password(password,user.password)  #对密码进行解码,返回布尔值
            # if flag:
            #     #记录登录用户名
            #     request.session['username'] = username
            #     #return redirect(reverse('index'))
                #return render(request, 'index.html')

            # 方式2
            user = authenticate(username=username,password=password)
            if user:
                login(request,user)
                return render(request, 'user/index.html')
        return render(request, 'user/login.html',
                      context={'msg': '登录失败,请检查输入是否正确'})

#注销登录
def user_logout(request):
    #request.session.clear()   #只是删除了字典(session用字典保存)
    # request.session.flush()    #删除了django)_session + cookile + 字典
    #
    logout(request)
    return render(request, 'user/index.html')

#关于我
def user_about(request):
    return render(request, 'user/about.html')

#发送验证码路由,ajax发过来的请求
# def send_code(request):
#     mobile = request.GET('mobile')
#     #发送验证码   第三方
#     json_result = utils_sendmsg(mobile)
#     #取值
#     status = json_result.get('code')
#     data = {}
#     if status == 200:
#         check_code = json_result.get('obj') #obj是真正的验证码
#         #使用session进行缓冲
#         request.session[mobile] = check_code
#         data['status'] = 200
#         data['mag'] = '验证码发送成功'
#     else:
#         data['status'] =500
#         data['mag'] = '验证码发送失败'
#     return JsonResponse(data)


 #忘记密码
 #忘记密码
def user_forget(request):
    if request.method == 'GET':
        return render(request, 'user/forget.html')


#用户的个人中心,用login登录的
@login_required
def user_center(request):
    user = request.user
    if request.method == 'GET':
        user = request.user
        return render(request, 'user/center.html',context={'user':user})
    else:
        username =request.POST.get('username')
        mobile = request.POST.get('mobile')
        email = request.POST.get('email')
        icon = request.FILES.get('icon')
        #在数据库里更改
        user.username = username
        user.mobile = mobile
        user.email = email
        user.icon = icon
        user.save()
        return render(request, 'user/center.html', context={'user': user})

三、文件上传
文件上传需要创建media文件夹
使用的模型是Filefield(任何文件类型)#ImageField(只能是图片)

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR,'media')

使用时需要参数upload_to=‘路径’这个路径就是 MEDIA_ROOT指明的路径
模板中想要应用上传的文件需要在settings里的templates里加入

  'django.template.context_processors.media'

添加路由

re_path(r'^media/(?P<path>.*)$',serve,{'document_root':MEDIA_ROOT}),

这样前端就可以通过{{MEDIA_URL}}来使用

四、文章表
创建app–article,在model里创建文章表和标签表
标签与文章是多对多关系
文章与作者是一对多关系

class Tag(models.Model):
    name = models.CharField(max_length=50,verbose_name='标签',db_index = True)

    def __str__(self):
        return self.name

    class Meta:
        db_table = 'tag'
        verbose_name = '标签表'
        verbose_name_plural = verbose_name

class Article(models.Model):
    title = models.CharField(max_length=100,verbose_name='标题')
    desc = models.CharField(max_length=256, verbose_name='简介')
    content = RichTextUploadingField(verbose_name='内容')
    date = models.DateField(auto_now=True,verbose_name='发表日期')
    click_num = models.IntegerField(default=0,verbose_name='点击量')
    love_num = models.IntegerField(default=0,verbose_name='点赞量')
    image = models.ImageField(upload_to='uploads/article/%Y/%m/&d',verbose_name='文章图片')

    tags = models.ManyToManyField(Tag)
    user = models.ForeignKey(to=UserProfile,on_delete=models.CASCADE)

    def __str__(self):
        return self.title

    class Meta:
        db_table = 'article'
        verbose_name = '文章表'
        verbose_name_plural = verbose_name

写博客是记录博客内容的表在自己创建的forms文件内,继承ModelForm

class ArticleForm(forms.ModelForm):
    class Meta:
        model = Article
        fields = '__all__'
        exclude = ['click_num','love_num','date']

为了是后台管理能够显示出来这些表,需要在admin文件里进行注册

from django.contrib import admin
from article.models import Article,Tag

admin.site.register(Article)
admin.site.register(Tag)
-------------------------------------------
from blog.models import UserProfile

admin.site.register(UserProfile)

五、URL—article

app_name = 'article'

urlpatterns = [
    path('detail',article_detail,name = 'detail'),   #博客内容详情
    path('learn',article_learn,name = 'learn'),    #浏览全部博客
    path('write',article_write,name = 'write'),     #写博客  ]

六、视图函数-------博客

 from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator
from django.shortcuts import render
from article.forms import ArticleForm
from article.models import Article, Tag


#首页浏览 ——查看详细信息
def article_detail(request):
    id = request.GET.get('id')
    article = Article.objects.get(pk = id)
    article.click_num+=1
    article.save()      #增加观看量
    tags_list = article.tags.all()#查询相干文章
    list_about = []#存放文章的列表
    for tag in tags_list:
        for article in tag.article_set.all():
            if article not in list_about and len(list_about)<6:
                list_about.append(article)

    return render(request, 'article/detail.html', context={'article':article,
                                                        'list_about':list_about})


#分页查看所有文章  按标签分类
def article_learn(request):
    tags = Tag.objects.all()
    tid = request.GET.get('tid')
    if tid:
        tag = Tag.objects.get(pk=tid)
        #articles = Article.objects.filter(tags__name=tag.name)
        articles = tag.article_set.all()  #如果进行标签检索
    else:
        articles = Article.objects.all()

    paginator = Paginator(articles,4)        #分页  (articles:要查询的对象列表,4:每页的个数)
    page = request.GET.get('page',1)    #取不到默认为1
    page = paginator.get_page(page)   #返回的是page对象

    return  render(request,'article/learn.html',
                   context={'page':page,'tags':tags,'tid':tid})


#写博客
@login_required
def article_write(request):
    if request.method =="GET":
        aform = ArticleForm()
        return render(request,'article/write.html',context={'form':aform})
    else:
        aform = ArticleForm(request.POST)
        if aform.is_valid():
            data = aform.cleaned_data
            article = Article()
            article.title = data.get('title')
            article.desc = data.get('desc')
            article.content = data.get('content')
            # article. click_num= data.get('click_num')
            # article.love_num = data.get('love_num')
            article.image = data.get('image')               #没保存文章不能添加标签
            article.user = data.get('user')                 #一对多可以直接保存
            article.save()

            article.tags.set(data.get('tags'))             #多对多   没保存文章不能添加标签
            # article.save()
            return render(request, 'article/learn.html')
        else:
            return render(request,'article/write.html')

七、验证登录状态
1.可以利用中间件进行验证
2.因为我继承了AbstractractUser,所有可以使用@login_required装饰器来进行验证
但是一定需要在settings里面加入登录路由

#添加一个登录路由
LOGIN_URL = '/blog/login'

八、使用富文本编辑器

1.下载pip install django-ckeditor
2.在settings里的app加入

  'ckeditor',          #  添加ckeditor富文本编辑器
  'ckeditor_uploader',  # 进行文件上传

   #在最后加入  
   CKEDITOR_UPLOAD_PATH = 'uploads/'  #上传文件的路径   ’依赖MEDTA_ROOT‘

3.然后把STATICFILES_DIR改为STATIC_ROOT
4.在collectstatic #收集静态文件
5.url中加入
re_path(r'^ckeditor/',include('ckeditor_uploader.urls')),#加载上传时默认路径
6.在要使用的字段里改为 RichTextUploadingField()就可以在后台看到
7.前端要使用:

<form action="{% url 'article:write' %}" method="post" enctype="multipart/form-data">
    {% csrf_token %}
        {{ form.media }}
        {{ form.as_p }}
        <input type="submit" value="提交" >
    </form>

还有一些功能未完善

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当前课程中博客项目的实战源码是我在 GitHub上开源项目 My-Blog,目前已有 3000 多个 star:本课程是一个 Spring Boot 技术栈的实战类课程,课程共分为 3 大部分,前面两个部分为基础环境准备和相关概念介绍,第三个部分是 Spring Boot 个人博客项目功能的讲解,通过本课程的学习,不仅仅让你掌握基本的 Spring Boot 开发能力以及 Spring Boot 项目的大部分开发使用场景,同时帮你提前甄别和处理掉将要遇到的技术难点,认真学完这个课程后,你将会对 Spring Boot 有更加深入而全面的了解,同时你也会得到一个大家都在使用的博客系统源码,你可以根据自己的需求和想法进行改造,也可以直接使用它来作为自己的个人网站,这个课程一定会给你带来巨大的收获。作者寄语本课程录制于 2020 年,代码基于 Spring Boot 2.x 版本。到目前为止,Spring Boot 技术栈也有一些版本升级,比如 Spring Boot 2.7 发版、Spring Boot 3.x 版本发布正式版本。对于这些情况,笔者会在本课程实战项目的开源仓库中创建不同的代码分支,保持实战项目的源码更新,保证读者朋友们不会学习过气的知识点。课程特色 课程内容紧贴 Spring Boot 技术栈,涵盖大部分 Spring Boot 使用场景。开发教程详细完整、文档资源齐全、实验过程循序渐进简单明了。实践项目页面美观且实用,交互效果完美。包含从零搭建项目、以及完整的后台管理系统和博客展示系统两个系统的功能开发流程。技术栈新颖且知识点丰富,学习后可以提升大家对于知识的理解和掌握,对于提升你的市场竞争力有一定的帮助。实战项目预览    

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值