• python操作三大主流数据库(14)python操作redis之新闻项目实战②新闻数据的展示及修改、删除操作


    python操作三大主流数据库(14)python操作redis之新闻项目实战②新闻数据的展示及修改、删除操作

    项目目录:

    ├── flask_redis_news.py
    ├── forms.py
    ├── init_news.py
    ├── redis_news.py
    ├── static
    │   ├── bootstrap-3.3.7-dist
    │   │   ├── css
    │   │   ├── fonts
    │   │   └── js
    │   ├── bootstrap-3.3.7-dist.zip
    │   ├── datatables.min.css
    │   ├── datatables.min.js
    │   ├── img
    │   │   └── news
    │   ├── index.css
    │   ├── jquery-3.3.1.min.js
    │   └── main.css
    ├── templates
    │   ├── admin
    │   │   ├── add.html
    │   │   ├── admin_base.html
    │   │   ├── index.html
    │   │   └── update.html
    │   ├── cat.html
    │   ├── detail.html
    │   ├── home_base.html
    │   └── index.html

     1.服务端代码flask_redis_news.py

    #coding:utf-8
    
    import sys
    defaultencoding = 'utf-8'
    if sys.getdefaultencoding() != defaultencoding:
        reload(sys)
        sys.setdefaultencoding(defaultencoding)
    import os
    from datetime import datetime
    from werkzeug import secure_filename
    from flask import Flask, request, render_template, redirect, flash, url_for, abort
    from flask_uploads import UploadSet, configure_uploads, IMAGES, patch_request_class
    
    from forms import NewsForm
    from redis_news import RedisNews
    
    app = Flask(__name__)
    app.config['SECRET_KEY'] = 'adfa@4314#31AD23#2'
    app.config['UPLOADED_PHOTOS_DEST'] = "/data/three_db_python/redis_version01/static/img/news"
    query = RedisNews()
    
    photos = UploadSet('photos', IMAGES)
    configure_uploads(app, photos)
    
    patch_request_class(app)  # set maximum file size, default is 16MB
    
    @app.route("/", methods = ['GET'])
    def index():
        ''' 获取新闻列表 '''
        news_list = query.get_all_news()
        return render_template("index.html", news_list = news_list)
    
    @app.route("/cat/<name>/", methods = ['GET'])
    def cat(name):
        ''' 获取新闻列表 '''
        news_list = query.get_news_from_cat(name)
        return render_template("cat.html", news_list = news_list)
    
    @app.route("/detail/<int:pk>/", methods = ['GET'])
    def detail(pk):
        ''' 获取新闻列表 '''
        news_obj = query.get_news_from_id(pk)
        return render_template("detail.html", obj = news_obj)
    
    @app.route("/admin/", methods = ['GET'])
    @app.route("/admin/<int:page>/", methods = ['GET'])
    def admin(page = None):
        ''' 获取后台新闻列表 '''
        if page is None:
            page = 1
        page_data = query.paginate(page, 5)
        return render_template("admin/index.html", page_data = page_data)
    
    @app.route("/admin/add/", methods = ['GET','POST'])
    def admin_add():
        ''' 从后台页面添加新闻 '''
        form = NewsForm()
        news_obj = {}
        # 提交增加
        if form.validate_on_submit():
            # 图片文件名
            filename = photos.save(form.photo.data)
    
            news_obj['title'] = form.title.data
            news_obj['news_type'] = form.news_type.data
            news_obj['img_url'] = form.img_url.data
            news_obj['content'] = form.content.data
            news_obj['created_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            news_obj['updated_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            query.add_new_from_page(news_obj)
            flash('添加成功')
            return redirect(url_for('admin'))
    
        return render_template("admin/add.html", form = form)
    
    @app.route("/admin/update/<int:pk>/", methods = ['GET','POST'])
    def admin_update(pk):
        ''' 获取后台新闻列表 '''
        # 获取新闻
        news_obj = query.get_news_from_id(pk)
        if news_obj is None:
            abort('no this news')
        form = NewsForm(data = news_obj)
        
        # 提交修改
        if form.validate_on_submit():
            news_obj['title'] = form.title.data
            news_obj['news_type'] = form.news_type.data
            news_obj['img_url'] = form.img_url.data
            news_obj['content'] = form.content.data
            news_obj['updated_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    
            query.update_news(pk, news_obj)
    
            flash('新闻修改成功')
            return redirect(url_for('admin'))
        return render_template("admin/update.html", form = form)
    
    @app.route("/admin/delete/<int:pk>/", methods = ['GET','POST'])
    def admin_delete(pk):
        ''' 删除新闻 '''
        news_obj = query.get_news_from_id(pk)
        if news_obj:
            query.delete_news(pk, news_obj)
            return 'yes'
    
        return 'no'
    
    
    if __name__ == "__main__":
        app.run(debug = True,host="0.0.0.0")

    2.辅助类新闻的具体操作redis_news.py

    #coding:utf-8
    
    import math
    import redis
    
    NEWS_FIELDS = (
        "title",
        "img_url",
        "content",
        "is_valid",
        "news_type",
        "created_at",
        "updated_at"
    )
    
    class RedisNews(object):
        def __init__(self):
            # 如果返回是二进制类似 b'3xe6x9cx885xe6x97xa5xe...'需要加decode_responses=True
            try:
                self.r = redis.StrictRedis(host = 'localhost',
                 port=6379,encoding='utf-8',
                  decode_responses=True,
                   db=1)
            except Exception as e:
                print('redis connect faild')
            
        def _news_id(self, int_id):
            ''' 新闻id '''
            return 'news:%d' % int(int_id)
    
        def _news_type(self, news_type):
            ''' 新闻类型 '''
            return 'news_type:%s' % news_type
    
        def _news_list_name(self):
            ''' 新闻列表名称 '''
            return 'news'
    
        def add_new_from_page(self, news_obj):
            ''' 从页面新增新闻数据 '''
    
            # 记录news_id的数字自增1
            int_id = self.r.incr('news_id', amount=1)
            # 获取新闻id
            news_id = self._news_id(int_id)
    
            # 新闻列表中添加
            self.r.lpush(self._news_list_name(), int_id)
    
            # 新闻类型中添加信息
            news_type = news_obj['news_type']
            self.r.sadd(news_type, int_id)
    
            # 新闻内容中添加信息
            self.r.hmset(news_id, news_obj)
    
    
    
        def add_news(self, news_obj):
            ''' 新增新闻数据 '''
            # 获取到新闻的id
            int_id = int(self.r.incr('news_id'))
            # 拼接新闻数据Hash key(news:2)
            news_id = self._news_id(int_id)
    
            # 存储新闻数据(hash)
            rest = self.r.hmset(news_id, news_obj)
    
            # 存储新闻的id list
            self.r.lpush(self._news_list_name(), int(int_id))
    
            # 存储新闻的类别-新闻id(set)
            news_type = _news_type(news_obj['news_type'])
            self.r.sadd(news_type, int_id)
            return rest
    
        def add_news_with_transaction(self, news_obj):
            ''' 使用事务来新增新闻数据 '''
            pipe = self.r.pipeline(transaction=True)
            int_id = self.r.incr('news_id')
            news_id = self._news_id(int_id)
    
            # 使用列表list获取新闻的id
            pipe.lpush(self._news_list_name(), int_id)
    
            # 使用hash来保存新闻具体内容
            pipe.hmset(news_id, news_obj)
    
            # 使用hash来保存新闻分类信息
            news_type = self._news_type(news_obj['news_type'])
            pipe.sadd(news_type, int_id)
    
            rest = pipe.execute()
            return rest
    
        def get_all_news(self):
            ''' 获取所有新闻信息 '''
    
            # 获取id列表
            id_list = self.r.lrange(self._news_list_name(), 0, -1)
            data_list = []
    
            for int_id in id_list:
                # 获取具体新闻内容
                news_id = self._news_id(int_id)
                data = self.r.hgetall(news_id)
                data['id'] = int_id
                # print(data)
                data_list.append(data)
    
            return data_list
    
        def get_news_from_id(self, news_id):
            ''' 根据新闻id获取新闻内容 '''
            news_id = self._news_id(news_id)
    
            # 根据新闻id获取新闻内容
            news_obj = self.r.hgetall(news_id)
            return news_obj
    
        def get_news_from_cat(self, cat_name):
            ''' 根据新闻类型获取新闻内容 '''
            news_list = []
    
            # 获取新闻类型
            news_type = self._news_type(cat_name)
            # print(news_type)
            # 获取新闻类型集合中新闻id的列表
            id_list = self.r.smembers(news_type)
            print(id_list)
            for int_id in id_list:
                # 获取新闻id
                news_id = self._news_id(int_id)
                # 根据新闻id获取新闻内容
                data = self.r.hgetall(news_id)
                data['id'] = int_id
                news_list.append(data)
            return news_list
    
        def update_news(self, pk, news_obj):
            ''' 新闻的修改 '''
            news_id = self._news_id(pk)
    
            # 修改新闻
            rest = self.r.hmset(news_id, news_obj)
            return rest
    
        def delete_news(self, pk, news_obj):
            ''' 
                新闻的删除,物理删除
    
                关于常用的方法可以通过查询redis的命令类型判断是list,string还是hash或者set
                1.命令列表定位到具体命令:http://www.redis.cn/commands.html#hash
                2.找到命令后,查询api的用法http://redis-py.readthedocs.io/en/latest/
    
            '''
    
            # 获取新闻id
            news_id = self._news_id(pk)
            # 从新闻列表中删除新闻id
            self.r.lrem(self._news_list_name(), 0, pk)
            # 从新闻的类型set集合中清理新闻id
            news_type = self._news_type(news_obj['news_type'])
            self.r.srem(news_type, pk)
            # 从新闻的内容hash列表中清理具体的新闻内容NEWS_FIELDS(具体的列信息)
            self.r.hdel(news_id, *NEWS_FIELDS)
    
    
        def paginate(self, page=1, per_page=5):
            ''' 新闻后台分页 '''
            if page is None:
                page = 1
    
            data_list = []
            # 开始页,结束页面
            start = (page - 1)*per_page
            end = page*per_page - 1
    
            # 获取所有新闻列表(计算页码使用)
            list_ids = self.r.lrange(self._news_list_name(), 0, -1)
    
            # 获取新闻列表
            id_list = self.r.lrange(self._news_list_name(), start, end)
            # print('id_list%s' % id_list)
    
            for int_id in id_list:
                news_id = self._news_id(int_id)
                # 根据新闻id获取新闻内容
                data = self.r.hgetall(news_id)
                data['id'] = int_id
                data_list.append(data)
            # print('data_list%s' % data_list)
            return Pagenation(data_list, page, per_page, list_ids)
    
    
        def init_news(self, data_list):
            ''' 批量导入新闻数据 '''
            for news_obj in data_list:
                rest = self.add_news_with_transaction(news_obj)
                print(rest)
    
    
    class Pagenation(object):
        ''' 分页类 '''
        def __init__(self, data_list, now_page, per_page, list_ids):
            self.now_page = now_page
            self.data_list = data_list
            self.per_page = per_page
            self.list_ids = list_ids
    
        @property
        def page(self):
            ''' 当前页 '''
            return self.now_page
    
        @property
        def items(self):
            ''' 返回页面数据 '''
            return self.data_list
    
        @property
        def prev_num(self):
            ''' 上一页 '''
            return self.now_page - 1
    
        @property
        def next_num(self):
            ''' 下一页页码 '''
            return self.now_page + 1
    
        @property
        def has_prev(self):
            ''' 是否有上一页 '''
            return self.now_page > 1
    
        @property
        def has_next(self):
            ''' 是否有下一页 '''
            return self.per_page == len(self.data_list)
    
        def iter_pages(self):
            ''' 页码 '''
            # 获取所有的id长度(即新闻条数)除以每页显示的页面,得到取进一位的整数
            total_page = math.ceil(len(self.list_ids)/self.per_page)
            # print('total_page=%d' % total_page)
            return range(1, total_page)

    3.表单类forms.py

    from flask_wtf import FlaskForm
    from wtforms import StringField, TextAreaField, SubmitField, SelectField
    from flask_wtf.file import FileField, FileRequired, FileAllowed
    from wtforms.validators import DataRequired
    
    class NewsForm(FlaskForm):
        """新闻表单数据验证"""
        title = StringField(label = '新闻标题', validators = [DataRequired('请输入标题')],
            description = '请输入标题',
            render_kw={'required':'required', 'class':'form-control'})
        content = TextAreaField(label = '新闻内容', validators = [DataRequired('请输入新闻内容')],
            description = '请输入新闻内容',
            render_kw={'required':'required', 'class':'form-control'})
        news_type = SelectField('新闻类型', choices = [('推荐','推荐'), ('百家', '百家'),('本地','本地'), ('图片','图片')])
        img_url = StringField(label='新闻图片', description='请输入图片地址',
            render_kw={'required':'required', 'class':'form-control'})
        photo = FileField('图片上传', validators=[FileAllowed(['png', 'JPEG', 'jpg'], '只能上传图片!'), 
            FileRequired('文件未选择!')])
        submit = SubmitField('提交')

    4.前台展示页面

    ①模板home_base.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      
      <link rel="stylesheet" href="{{ url_for('static', filename='bootstrap-3.3.7-dist/css/bootstrap.min.css')}}">
      <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='main.css')}}">
      <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='datatables.min.css')}}">
      <script type="text/javascript" src="{{ url_for('static', filename='jquery-3.3.1.min.js')}}"></script>
      <script type="text/javascript">
            $(document).ready(function() {
                $('#example').DataTable();
            } );
      </script>
      {% block head %}
      <title>首页</title>
      {% endblock %}
    </head>
    <body>
    <div class="container">
        <h1>新闻列表</h1>
      <nav class="navbar navbar-inverse">
          <!-- 页面头部 -->
          <div class="navbar-header">
              <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-menu" aria-expanded="false">
                  <span class="sr-only">Toggle navigation</span>
                  <span class="icon-bar"></span>
                  <span class="icon-bar"></span>
                  <span class="icon-bar"></span>
              </button>
              
          </div>
          <div id="navbar-menu" class="collapse navbar-collapse">
              <ul class="nav navbar-nav">
                  <li class="active"><a href="/">首页</a></li>
                  <li><a href="{{url_for('cat', name='推荐')}}">推荐</a></li>
                  <li><a href="{{url_for('cat', name='百家')}}">百家</a></li>
                  <li><a href="{{url_for('cat', name='本地')}}">本地</a></li>
                  <li><a href="{{url_for('cat', name='图片')}}">图片</a></li>
              </ul>
          </div>
      </nav>
    
    <!-- 新闻内容部分 -->
    {% block content %}
    <!-- 内容区域 -->
    {% endblock %}
    
    </div>
    {% block extrajs %}
    <!-- 其他脚本 -->
    {% endblock %}
    </body>
    </html>

    ②首页index.html

    {% extends 'home_base.html' %}
    {% block content%}
    
    <div id="content" class="row-fluid">
            <div class="col-md-12">
            <table id="example" class="table table-striped table-bordered" cellspacing="0" width="100%">
            <thead>
                <tr>
                    <th>图片</th>
                    <th>简介</th>
                </tr>
            </thead>
            <tbody>
            {% for obj in news_list %}
            <tr>
                  <td>
                  <img width=120 height=60 src="{{ obj.img_url }}" alt="图片">
                  </td>
                  <td>
                  <p>
                    <a href="{{ url_for('detail', pk=obj.id) }}">{{ obj.title }}</a>
                    <small>{{ obj.created_at }}</small>
                  </p>
                  </td>
            </tr>
            {% endfor %}
            </tbody>
            </table>
            </div>
    </div>
    </div>
    {% endblock %}
    {% block extrajs %}
    <script type="text/javascript" src="{{ url_for('static', filename = 'datatables.min.js')}}"></script>
    {% endblock %}

    ③详情页detail.html

    {% extends 'home_base.html' %}
    
      {% block head %}
      <title>新闻详情</title>
      {% endblock %}
    {% block content%}
    
    
    <div id="content" class="row-fluid">
            <div class="col-md-9">
                <h2>新闻详情,来自新闻id> {{obj.id}}</h2>
    
            </div>
    
             <div class="col-md-12">
            <table id="example" class="table table-striped table-bordered" cellspacing="0" width="100%">
            <thead>
                <tr>
                    <th>{{ obj.content }}</th>
                </tr>
            </thead>
    
            <tbody>
    
            <tr>
                  <td>
                  <img width=600 height=500 src="{{ obj.img_url }}" alt="图片">
                  </td>
                  <td>
            </tr>
    
            <tr>
    
                  <td>
                  <p>
                    {{ obj.title }}
                    <small>{{ obj.created_at }}</small>
                  </p>
                  </td>
            </tr>
    
            </tbody>
            </table>
            </div>
    
    
    </div>
    
    </div>
    {% endblock %}
    </body>
    </html>

    ④分类页面cat.html

    {% extends 'home_base.html' %}
    {% block head%}
    <title>{{ name }}</title>
    {% endblock %}
    {% block content%}
    
    <div id="content" class="row-fluid">
            <div class="col-md-12">
            <table id="example" class="table table-striped table-bordered" cellspacing="0" width="100%">
            <thead>
                <tr>
                    <th>图片</th>
                    <th>简介</th>
                </tr>
            </thead>
            <tbody>
            {% for obj in news_list %}
            <tr>
                  <td>
                  <img width=120 height=60 src="{{ obj.img_url }}" alt="图片">
                  </td>
                  <td>
                  <p>
                    <a href="{{ url_for('detail', pk=obj.id) }}">{{ obj.title }}</a>
                    <small>{{ obj.created_at }}</small>
                  </p>
                  </td>
            </tr>
            {% endfor %}
            </tbody>
            </table>
            </div>
    </div>
    </div>
    {% endblock %}
    {% block extrajs %}
    <script type="text/javascript" src="{{ url_for('static', filename = 'datatables.min.js')}}"></script>
    {% endblock %}

    5.后台管理页面

    ①后台模板页面admin/admin_base.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
         <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='bootstrap-3.3.7-dist/css/bootstrap.min.css')}}">
         {% block head %}
         <title>首页</title>
         {% endblock %}
    </head>
    <body>
        <!-- 导航栏 -->
        <div class="container">
            <div class="row">
            <div class="bs-example" data-example-id="default-navbar">
            <nav class="navbar navbar-default">
              <div class="container-fluid">
                <!-- Brand and toggle get grouped for better mobile display -->
                <div class="navbar-header">
                  <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                  </button>
                  <a class="navbar-brand" href="{{ url_for('admin_add')}}">添加新闻</a>
                </div>
    
                <!-- Collect the nav links, forms, and other content for toggling -->
                <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                  <ul class="nav navbar-nav">
                    <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
                    <li><a href="#">Link</a></li>
                    <li class="dropdown">
                      <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
                      <ul class="dropdown-menu">
                        <li><a href="#">Action</a></li>
                        <li><a href="#">Another action</a></li>
                        <li><a href="#">Something else here</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">Separated link</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">One more separated link</a></li>
                      </ul>
                    </li>
                  </ul>
                  <form class="navbar-form navbar-left">
                    <div class="form-group">
                      <input type="text" class="form-control" placeholder="Search">
                    </div>
                    <button type="submit" class="btn btn-default">Submit</button>
                  </form>
                  <ul class="nav navbar-nav navbar-right">
                    <li><a href="#">Link</a></li>
                    <li class="dropdown">
                      <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
                      <ul class="dropdown-menu">
                        <li><a href="#">Action</a></li>
                        <li><a href="#">Another action</a></li>
                        <li><a href="#">Something else here</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">Separated link</a></li>
                      </ul>
                    </li>
                  </ul>
                </div><!-- /.navbar-collapse -->
              </div><!-- /.container-fluid -->
            </nav>
    
            <!-- 新闻内容部分 -->
            {% block content %}
            <!-- 内容区域 -->
            {% endblock %}
        </div>
    {% block extrajs %}
    <!-- 其他脚本 -->
    {% endblock %}
    </body>
    </html>

    ②后台首页admin/index.html

    {% extends 'admin/admin_base.html' %}
    {% block head %}
    <title>新闻后台首页</title>
    {% endblock %}
    {% block content %}
            <!-- 消息闪现 -->
            {% for msg in get_flashed_messages() %}
              <p class="bg-success">{{msg}}</p>
             {% endfor %}
    
            <!-- 表格,存放新闻具体内容 -->
            <table class="table table-hover">
                
                <tr class="info">
                        <th>编号</th>
                        <th>新闻标题</th>
                        <th>类别</th>
                        <th>添加时间</th>
                        <th>操作</th>
                </tr>
                {% for new_obj in page_data.items %}
                <tr class="active">
                    <td>{{ new_obj.id }}</td>
                    <td>{{ new_obj.title }}</td>
                    <td>{{new_obj.types }}</td>
                    <td>{{new_obj.created_at }}</td>
                    <td><a href="{{url_for('admin_update', pk = new_obj.id)}}" class='btn btn-success'>修改</a><a data-url="{{ url_for('admin_delete', pk=new_obj.id) }}" class='btn btn-danger'>删除</a></td>
                </tr>
                {% endfor %}
            </table>
    
            <!-- 分页,默认分页 -->
            
            <nav aria-label="Page navigation">
              <ul class="pagination">
                  {% if page_data.has_prev %}
                <li>
                  <a href="{{ url_for('admin', page=page_data.prev_num) }}" aria-label="Previous">
                    <span aria-hidden="true">&laquo;</span>
                  </a>
                </li>
                {% else %}
                <li class="disabled"><a href="javascipt:;">&raquo;</a></li>
                {% endif %}
                {% for page in page_data.iter_pages() %}
                {% if page == page_data.page %}
                <li class="active">
                    <a href="javascript:;">{{ page }}</a>
                </li>
                {% else %}
                <li>
                    <a href="{{ url_for('admin', page=page) }}">{{ page }}</a>
                </li>
                {% endif %}
               {% endfor %}
    
               {% if page_data.has_next %}
                <li>
                  <a href="{{ url_for('admin', page=page_data.next_num) }}">&raquo;</a>
                </li>
                {% else %}
                <li class="disabled">
                  <a href="javascript:;">&raquo;</a>
                </li>
                {% endif %}
              </ul>
            </nav>
            
            </div>
            </div>
        {% endblock %}
    {% block extrajs %}
    <script type="text/javascript" src="{{ url_for('static', filename='jquery-3.3.1.min.js') }}"></script>
    <script type="text/javascript">
        // 通过ajax异步删除新闻
         $(function(){
             $('.btn-danger').on('click', function(){
                 var _this = $(this)
                 var url = _this.attr('data-url')
                 // 弹框确认是否删除
                 if (confirm('确认删除吗?')){
                     // ajax发送post请求
                     $.post(url, function(res){
                         if(res == 'yes'){
                             // 如果后台删除成功则隐藏该行
                             _this.parents('tr').hide()
                         }else{
                             alert('删除失败');
                         }
                     })
                 }
                 
             })
         })
    </script>
    {% endblock %}
    </body>
    </html>

    ③后台添加页面admin/add.html

    {% extends 'admin/admin_base.html' %}
    {% block head %}
    <title>新闻添加页面</title>
    {% endblock %}
    {% block content %}
        
        <!-- 添加新闻内容 -->
        <form action="/admin/add/" method="post" enctype="multipart/form-data">
            <div class="form-group">
                <label for="exampleInputEmail1">{{ form.title.label.text }}</label>
                <input type="text" name="title" class="form-control" id="exampleInputEmail1" placeholder="news title">
            </div>
            <div class="form-group">
                <label for="exampleInputPassword1">{{ form.news_type.label.text }}</label>
                <div>
                    {{ form.news_type }}
                </div>
            </div>
            <div class="form-group">
                {{ form.photo }}
                {% for error in form.photo.errors %}
                     <span style="color: red;">{{ error }}</span>
                     {% endfor %}
                <p class="help-block">新闻图片上传</p>
            </div>
            <div class="form-group">
                <p class="help-block">新闻图片的路径</p>
                {{ form.img_url }}
            </div>
            <div class="form-group">
                {{ form.content }}
            </div>
    
            <br>
                {{ form.csrf_token }}
                {{ form.submit }}
        </form>
    {% endblock %}
    </body>
    </html>
     

    ④后台新闻更新页面admin/update.html

    {% extends 'admin/admin_base.html' %}
    {% block head %}
    <title>修改新闻</title>
    {% endblock %}
    {% block content %}
    
        <form role='form' class="form-horizontal" method="post">
          <div class="form-group">
            <label for="exampleInputEmail1">{{ form.title.label.text }}</label>
            <div>
            {{form.title}}
            </div>
          </div>
          <div class="form-group">
            <label for="exampleInputPassword1">{{ form.news_type.label.text }}</label>
            <div>
                {{ form.news_type }}
            </div>
          </div>
          <div class="form-group">
            <label for="exampleInputFile">{{ form.img_url.label.text }}</label>
            <input type="file" name="image" id="exampleInputFile">
            {{ form.img_url }}
            <!-- <p class="help-block">新闻图片上传</p> -->
          </div>
          <div class="form-group">
            {{ form.content }}
          </div>
          
          <br>
          {{ form.csrf_token }}
          {{ form.submit }}
    
        </form>
    
    {% endblock %}
    </body>
    </html>
  • 相关阅读:
    k8s 集群多节点 calico指定网卡
    用Python建立最简单的web服务器
    MyISAM与InnoDB两者之间区别与选择,详细总结,性能对比
    转化Excel表格为php配置文件
    dockers的容器删除
    php中csv文件的下载
    Ubuntu下mysql的卸载重装
    centos7的web环境安装配置
    lua随机数函数
    Lua 自定义函数string.split
  • 原文地址:https://www.cnblogs.com/reblue520/p/8549389.html
Copyright © 2020-2023  润新知