Django作业(二)——话题APP

django大作业2-话题APP

要求

编写一个话题APP。

需求:
1.用户登录、注册功能:输入用户名,密码
2.发布话题功能:用户登录后方可发布话题
3.话题评论功能:登录用户可对任意能查看到的话题进行评论(包括自己发布的话题);未登录用户不可发布评论
4.查看话题功能:登录用户可查看话题及评论内容,未登录用户仅能查看话题,话题及评论需要根据时间倒序进行展示(最新的话题及评论在最上)

技术要求:
1.数据库表:用户表、话题-评论表
2.用户注册后跳转至登录页面
3.登录后跳转至话题list页面,话题list页面要包含发布话题按钮及话题输入框
4.评论逻辑:只有话题可以评论(评论不必再有评论),不需要考虑评论嵌套
5.使用中间键判断登录状态

示意图:
话题1:xxxxxx
 评论1:xxxxxx
 评论2:xxxxxx
 评论3:xxxxxx
话题2:xxxxxx
 评论1:xxxxxx
 评论2:xxxxxx
 评论3:xxxxxx
话题3:xxxxxx
 评论1:xxxxxx
 评论2:xxxxxx
 评论3:xxxxxx

注册登录部分

 根据需求一,需要实现用户登录,注册功能,并且通过输入用户名密码进行登录,所以这里首先第一步需要创建用户数据库,而后创建视图函数,完善路由,以及模板渲染,大概步骤是这样。

用户数据库

首先第一步是创建一个用户数据库,这里我取名为Users(数据库中看到的是info_users),其中的元素包括用户姓名,用户密码,以及用于保存登录状态的token,底下写了几个类方法,分别是用于获取全部user实体、获取单个实体、筛选一个实体、创建一个实体。
代码如下:

from django.db import models

# Create your models here.
class Users(models.Model):
    objects = models.Manager()
    user_name = models.CharField(max_length=32, verbose_name="用户名", unique=True)
    user_pwd = models.CharField(max_length=32, verbose_name="密码")
    token = models.CharField(max_length=256, verbose_name="token", null=True)

    class Meta:
        db_table = "info_users"
        verbose_name = "用户表"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.user_name

    @classmethod
    def get_all(cls):
        return Users.objects.all()

    @classmethod
    def get_one(cls, pk):
        return Users.objects.get(pk=pk)

    @classmethod
    def get_list(cls,**kwargs):
        filters = {}
        if kwargs.get("name"):
            filters["name"] = kwargs.get("name")
        if kwargs.get("pwd"):
            filters["pwd"] = kwargs.get("pwd")
        return cls.objects.filter(**filters)

    @classmethod
    def creat_one(cls, user_name, pwd):
        return cls.objects.create(user_name=user_name,
                                  user_pwd=pwd
                                  )

模板及视图函数

注册部分:
首先需要进行用户注册,这里视图函数取名为RegisterView,如果只是显示页面(method=get)只需要返回相应的html即可;如果是需要将注册的数据保存进数据库,此时的method=post,因此需要通过request.POST.get来获取注册的信息,这里get到的变量名称来源于html中的<input name=“变量名">,即通过前端传参至后端,如果这个用户名已注册,则返回”用户名已注册“,否则通过models.py的creat_one模型类方法创建一条数据保存进数据库,实现注册功能。代码如下:

#要导入的包
from django.http import HttpResponse
from django.shortcuts import render, redirect
from django.urls import reverse
from django.views import View
# Create your views here.
from std_proj_temp.settings import PAGE_SIZE
from test2.models import Users, News, comments
from utils.utils import gen_md5
#注册
def RegisterView(request):
    if request.method == 'POST':
        name = request.POST.get("name")
        user = Users.get_list(user_name=name)
        pwd = request.POST.get("pwd")
        # pwd = gen_md5(request.POST.get("pwd"))
        if user:
            return HttpResponse("用户名已存在")
        Users.creat_one(user_name=name,pwd=pwd)
        return redirect(reverse("test2:login"))
    elif request.method == "GET":
        return render(request, "reg.html")

相应的模板如下:

<!DOCTYPE html>
{% load static %}
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册界面</title>
</head>
<body>
<h1 align="center">论坛注册</h1><br>
<form action="{% url 'test2:register' %}" method="POST">
    {% csrf_token %}
    <h3 align="center">用户:<input type="text" name="name"></h3>
  <h3 align="center">密码:<input type="password" name="pwd"></h3>
  <h3 align="center"><input type="submit" value="注册"></h3>
  </form>
  <h3 align="center">已有账号请<a href="{% url 'test2:login' %}"> 登录 </a></h3>
<h3 align="center"><a href="{% url 'test2:critic' %}"> 游客模式 </a></h3>
</body>
</html>

这里如果说不想注册仅浏览,设置了游客模式,直接转到要求的list页面,页面如下:
在这里插入图片描述

最后别忘了完善路由配置。
登录部分:
登录的思路和注册很像,如果method=get那么直接返回页面即可,如果为post,这里需要提取前端input标签中的name和pwd,通过get_list类方法获取对应User数据表中的内容是否一致,如果一致,则能提取到内容,bool(users)就为TRUE,及此时这个用户登录状态正确,此时我们需要做的是对用户的密码进行加密,并且添加token,而后保存数据,而后添加session,session包含name和token,以字典形式保存,而后重定向至论坛主页。
代码如下:

def LoginView(request):
    if request.method == "POST":
        name = request.POST.get("name")
        # pwd = gen_md5(request.POST.get("pwd"))
        pwd = request.POST.get("pwd")#这里如果采用gen_md5后面传入密码会找不到
        filters = {
            "user_name" : name,
            "user_pwd" : pwd,
        }
        users = Users.get_list(**filters)
        if users:
            # print("found!")
            user = users.first()
            user.token = gen_md5(user.user_name) + str(time.time())
            user.save()
            request.session["user_name"] = user.user_name
            request.session["user_token"] = user.token
            return redirect(reverse("test2:critic"))
        else:
            # print(filters)
            return HttpResponse("用户名或密码错误!")
    elif request.method == "GET":
        return render(request, "log_in.html",locals())

登录界面的html同注册界面大同小异,如下:

<!DOCTYPE html>
{% load static %}
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录界面</title>
</head>
<body>
<h1 align="center">论坛登录</h1><br>
<form action="{% url 'test2:login' %}" method="POST">
    {% csrf_token %}
    <h3 align="center">用户:<input type="text" name="name"></h3>
  <h3 align="center">密码:<input type="password" name="pwd"></h3>
  <h3 align="center"><input type="submit" value="登录"></h3>
  </form>
<h3 align="center">没有账号请<a href="{% url 'test2:register' %}"> 注册 </a></h3>
<h3 align="center"><a href="{% url 'test2:critic' %}"> 游客模式 </a></h3>
</body>
</html>

界面显示如下:
在这里插入图片描述
别忘了更新路由配置。

话题发布部分

在实现了登录注册功能后下一步就是展示论坛界面了,同样,这里首先需要创建数据表,而后编写视图函数,并且需要加入分页的功能,同时,游客的登录状态不同,页面展示的功能不同,关于分页,登录状态判断,以及如何关联页面的评论功能如下。

话题-评论表数据库

首先需要创建话题数据库,以及相应的评论数据库,一个topic可以有多个评论,这是典型的一对多模式,话题是一,评论是多,代码如下

#models.py
class News(models.Model):
    # 话题数据
    objects = models.Manager()
    topic_name = models.CharField(max_length=400, verbose_name="新闻名称")
    detail_name = models.CharField(max_length=600, verbose_name="新闻内容")

    class Meta:
        db_table = "news"
        verbose_name = "新闻"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.topic_name

    @classmethod
    def get_all(cls):
        return cls.objects.all()

    @classmethod
    def creat_one(cls, topic_name, detail_name):
        return cls.objects.create(topic_name=topic_name,
                                  detail_name=detail_name
                                  )
    @classmethod
    def get_one(cls,pk):
        try:
            return cls.objects.get(pk=pk)
        except Exception:
            return None


class comments(models.Model):
    # 评论数据
    objects = models.Manager()
    comment_name = models.CharField(max_length=1000, null=True, verbose_name="评论内容")
    topic = models.ForeignKey(News, on_delete=models.CASCADE)
    class Meta:

        db_table = "comments"
        verbose_name = "评论"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.comment_name

    @classmethod
    def get_all(cls):
        return cls.objects.all()

这里关于话题,表的名称起名为News,添加了话题标题(topic_name)与内容(detail_name)两个部分。关于评论,分为了评论内容(comment_name)以及关联的话题(news)的外键,在一对多模式下,只需要多方添加一方的外键即可,用法为models.foreignkey(一方模型名称,级联删除)。

模板及视图函数

# views.py
def critic_show(request):
    if request.method == "GET":
        page_num = request.GET.get("page", 1)
        print("执行get")
        # if request.method == "GET":
        news = News.get_all()  # 所有News的实例
        paginator = Paginator(news, PAGE_SIZE)  # 实例化paginator
        dics = {}
        try:
            data = paginator.page(page_num)
        except InvalidPage:  # 如果页数out of range
            data = paginator.page(1)  # 返回第一页
        # 以上是分页
        # for new in news:
        for new in data:
            critics = list(new.comments_set.all())  # 获取话题下的所有评论
            critics.reverse()  # 倒序
            dics[new] = critics  # 以列表的形式保存
        print(news)
    # comment = comments.get_all()
    # topics = news.topic_name,#话题标题,传入模板
    # news[1].comments_set.all()#获取话题一下所有的评论
        user_token = bool(Users.objects.filter(user_name=request.session.get("user_name")).first().token)
        print(f"!!!!!!!!!!!{user_token}")
        return render(request, "topics.html", locals())
    if request.method == 'POST':
        # 登录用户发表topic部分
        topic_name = request.POST.get("new_topic")
        detail_name = request.POST.get("topic_comment")
        datas = News()
        datas.topic_name = topic_name
        datas.detail_name = detail_name
        datas.save()
        print("已执行post")
        return redirect(reverse("test2:critic"))

这里视图函数取名为critic_show,在此之前我添加了四条话题及评论,分页的限制是两条,在method=get下,首先获取所有的话题实体,而后通过实例化paginator,这里paginator传入的参数PAGE_SIZE在settings.py中,而后try获取页面数,如果超范围则返回第一页。
之前已经通过实例化paginator实例化了news数据对象,因此为了获取话题下的评论,我们只需做一个遍历,这里通过一对多的外键获取话题下所有的评论,即一方数据对象实体.多方数据表名称小写_set.all()来获取,后发表的在上面,因此还需要做一个逆序(因为获取到的数据实体是以queryset的数据类型,这里需要先转化为list而后调用reverse)。
为了传给前端,做了一个字典,key是topic实体,value是话题列表。
为了判断登录状态,还需要加入一个token变量,如果登陆了token不为空,可以发表评论。
在这里插入图片描述

否则发表不了:
在这里插入图片描述

对应的模板如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>话题</title>
</head>
<body>
<h1 align="center">欢迎来到风语论坛</h1><br>
<!--以下展示内容部分-->
{% for key,value in dics.items %}
    <h3 align="center">话题:{{key}}</h3><h4 align="center"><a href="http://127.0.0.1:8000/test2/detail/{{ key.id }}/">详情</a></h4>
    {% for comment in value %}
        <h5 align="center">评论:{{comment}}</h5>
    {% endfor %}
<h3 align="center"><-------------------------------------------------------------------------------------------------------------------><br></h3>
{% endfor %}<br>
<!--判断是否登录部分-->
<h2 align="center">欢迎您发表话题!(只对注册用户开放此功能)</h2>
{% if user_token == False %}
<h3 align="center"><a href="{% url 'test2:login' %}">请登录</a></h3>
{% else %}
<form action="{% url 'test2:critic' %}" method="POST">
    {% csrf_token %}
<h2 align="center"><input type="text" name="new_topic" value="这里发布您的话题名称" style="width:1000px;height: 30px;border-radius:10px" align="center"><br><br>
<input type="text" name="topic_comment" value="这里发布您的话题内容" style="width:1000px;height: 100px;border-radius:10px" align="center"><br><br>
<input type="submit" value="点击发表" align="center"><br></h2>
</form>
<h3 align="center"><a href="{% url 'test2:logout' %}">退出登录</a></h3>
{% endif %}
<!--以下是分页部分-->
<h3 align="center"><a href="{% url 'test2:critic' %}">首页</a>
{% if data.has_previous %}
    <a href="{% url 'test2:critic' %}?page={{ data.previous_page_number }}">上一页</a>
{% else %}
    <a href="javascript:alert('没有上一页了')">上一页</a>
{% endif %}
{% if data.has_next %}
<a href="{% url 'test2:critic' %}?page={{ data.next_page_number }}">下一页</a>
{% else %}
    <a href="javascript:alert('没有下一页了')">下一页</a>
{% endif %}
<a href="{% url 'test2:critic' %}?page={{ paginator.num_pages }}">末页</a></h3>
</body>
</html>

html中对字典的循环,可直接提取key与value,以及forloop遍历次数,还是不一样的。

单个话题评论部分

在主页查看标题点击链接可以查看内容,并且添加评论:
在这里插入图片描述

具体思路为通过在主页html中传递topic_id,获取话题id,而后调用数据库,查找相应数据,展示到界面,通过外键获取关联评论,post下再获取相应的发表评论数据,存进数据库。

模板及视图函数

代码比较简单就不展示了。

联合调试(中间键判断登录)、

在app目录下创建middleware.py

from django.utils.deprecation import MiddlewareMixin

from test2.models import Users


class LoginMiddleWare(MiddlewareMixin):
    def process_request(self,request):
        if "/test2/detail/" in request.path:
            user_name = request.session.get("user_name")  # session中获取用户姓名
            user = Users.objects.filter(user_name=user_name).first()  # 获取对象用户实例
            if not user_name:
                user.token = ""  # 将User数据表中的token置0
                user.save()
                request.session["user_token"] = ""
                request.session["user_id"] = ""  # 清除session
            return None

所要做的工作是判断缓存中还有没有,如果没有删除token,清除缓存,否则什么都不做,返回none。
写完后需要在settings.py中添加中间件类名称:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'test2.middleware.LoginMiddleWare',#添加的类
]

为了更自洽,补充写了注销登录的功能:

def logout(request):
    user_name = request.session.get("user_name")#session中获取用户姓名
    user = Users.objects.filter(user_name=user_name).first()# 获取对象用户实例
    if user:
        user.token = ""# 将User数据表中的token置0
        user.save()
        request.session["user_token"] = ""
        request.session["user_id"] = ""# 清除session
        return HttpResponse("您已退出登录~")

这个视图函数没有具体返回的页面,我们只需要添加他的url,在html中具体的input标签或是a标签中通过“test2:logout”的形式引入即可。
同样,小白不懂JavaScript以及css,所以页面比较朴素

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,下面是一个可能的期末大作业的思路: 1. 需求分析 首先,需要明确期末大作业的具体需求,包括但不限于: - 网站主题:可以是电商、社交、博客等,需要与 Django Web 开发相关。 - 功能模块:需要确定网站的功能模块,例如用户注册、登录、商品展示、购物车、订单管理、评论等等。 - 技术要求:需要确定使用的技术,例如数据库、前端框架、支付接口等等。 2. 数据库设计 在确定网站的功能模块之后,需要进行数据库设计。可以使用 Django 自带的 ORM(对象关系映射)框架,也可以使用第三方的 ORM 框架。需要根据需求设计合理的数据表,并建立数据表之间的关系。 3. 搭建前端页面 在确定网站主题之后,需要使用 HTML、CSS、JavaScript 等技术搭建前端页面。可以使用 Bootstrap 等前端框架简化页面设计,实现响应式布局。 4. 实现后端逻辑 在前端页面搭建完成之后,需要实现后端逻辑。根据需求,使用 Django 框架实现用户注册、登录、商品展示、购物车、订单管理、评论等功能。需要注意安全性问题,如密码加密存储、防止 SQL 注入等。 5. 集成第三方服务 根据需求,需要集成第三方服务,例如支付接口、短信验证码等。需要根据文档或者 SDK,实现相应的接口调用。 6. 测试与部署 在完成开发之后,需要进行测试和部署。可以使用 Django 自带的测试框架进行单元测试和功能测试,确保网站的稳定性和可靠性。在测试通过后,可以使用云服务器等部署方式将网站上线,提供给用户访问。 以上是一个可能的期末大作业的思路,具体实现需要根据具体需求进行调整。希望能对你有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值