Django前后端分离开发-新闻管理系统(五)

项目源码下载:https://github.com/Cherish-sun/NEWS/tree/master

前端系统架构图

前后端系统架构图

一、创建前端项目和应用

django-admin.py startproject newsapi
python manage.py startapp article

将static和templates文件夹拷贝到我们的项目中。
并在setting的APP里,添加article

INSTALLED_APPS = [
    ...
    'artcile',
]

setting里添加 配置静态文件

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static').replace('', '/')
STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static'),)

web前端的工作原理是,请求后端对应的url,对url进行解析,传给html模板,返回给浏览器(用户)

1.基本方法-urlopen

urllib.request.urlopen(url,data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)

  • url: 需要打开的网址
  • data:Post提交的数据
  • timeout:设置网站的访问超时时间
    直接用urllib.request模块的urlopen()获取页面,page的数据格式为bytes类型,需要decode()解码,转换成str类型。
    from urllib import request
    response = request.urlopen(r'http://python.org/') # <http.client.HTTPResponse object at 0x00000000048BC908> HTTPResponse类型
    page = response.read()
    page = page.decode('utf-8')
    urlopen返回对象提供方法:
  • read() , readline() ,readlines() , fileno() , close() :对HTTPResponse类型数据进行操作
  • info():返回HTTPMessage对象,表示远程服务器返回的头信息
  • getcode():返回Http状态码。如果是http请求,200请求成功完成;404网址未找到
  • geturl():返回请求的url
2.使用Request

urllib.request.Request(url,data=None, headers={}, method=None)
使用request()来包装请求,再通过urlopen()获取页面。
url = r'http://www.lagou.com/zhaopin/Python/?labelWords=label'
headers = {
'User-Agent': r'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) '
r'Chrome/45.0.2454.85 Safari/537.36 115Browser/6.0.3',
'Referer': r'http://www.lagou.com/zhaopin/Python/?labelWords=label',
'Connection': 'keep-alive' }
req = request.Request(url, headers=headers)
page = request.urlopen(req).read()
page = page.decode('utf-8')
用来包装头部的数据:

  • User-Agent :这个头部可以携带如下几条信息:浏览器名和版本号、操作系统名和版本号、默认语言
  • Referer:可以用来防止盗链,有一些网站图片显示来源http://***.com,就是检查Referer来鉴定的
  • Connection:表示连接状态,记录Session的状态。

二、views.py

1、导入包

from urllib import request, parse

try:
    import json
except ImportError:
    import simplejson as json
from django.shortcuts import render
from urllib.parse import urljoin

# Create your views here.

PAGESIZE = 5

2、引入所有API

category_url = 'http://127.0.0.1:8005/category/'
articles_url = 'http://127.0.0.1:8005/articleList/'
hotarticles_url = 'http://127.0.0.1:8005/hot_articleList/'
ad_url = 'http://127.0.0.1:8005/ad/'
items_url = 'http://127.0.0.1:8005/item/'

3、定义公用获取解析API方法

# 读取api数据
def getdata(url, data=None):
    # url = r'http://xxx/xxx/xxxx?'
    headers = {
        'User-Agent': r'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) '
                  r'Chrome/45.0.2454.85 Safari/537.36 115Browser/6.0.3',
        'Referer': r'',
        'Connection': 'keep-alive',
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*',
    }
    # data = {
    #     'first': 'true',
    #     'pn': 1,
    #     'kd': 'Python'
    #     }
    # urlencode()主要作用就是将url附上要提交的数据。
    # 经过urlencode()转换后的data数据为?first=true?pn=1?kd=Python,最后提交的url为
    # http://xxxxx/xx/xx?first=true?pn=1?kd=Python
    try:
        if data:
            # data = parse.urlencode(data).encode('utf8')
            # data 参数如果要传必须传 bytes (字节流)类型的,如果是一个字典,可以先用 urllib.parse.urlencode() 编码。
            # data = bytes(parse.urlencode(data), encoding="utf8")
            data = '?' + parse.urlencode(data)
            # 使用request()来包装请求,再通过urlopen()获取页面。
            url = urljoin(url, data)
            req = request.Request(url=url, headers=headers, method='GET')
        else:
            req = request.Request(url=url, headers=headers)

        reponsedata = request.urlopen(req, timeout=10).read()
        reponsedata = reponsedata.decode('utf-8')
        returndata = json.loads(reponsedata)
    except Exception as e:
        print(e)
        returndata = {'result': e, 'code': e, 'msg': '请求api数据错误!', 'data': '{}', 'redirect_url': ''}
    return returndata

4、新闻分类、热门新闻、广告定义成全局变量,分别调用getdata函数


全局变量
# 实现全局变量
def globl_init(request):
    # 取新闻分类
    # #category_list = Category.objects.all()
    category_list = getdata(category_url)
    # 取热门新闻
    # hot_articles = Article.objects.filter(is_active=True)[0:5]
    hot_articles = getdata(hotarticles_url)
    # 取广告数据
    ad_list = getdata(ad_url)
    user = request.user
    return locals()

全局变量要想在每个页面都生效,必须配置setting里

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'artcile.views.globl_init', # 新增
            ],
        },
    },
]

5、实现首页功能

def index(request):
    data = {
        "ordering": '-id',
    }
    article_data = getdata(articles_url, data)
    article_list = article_data["results"]

    user = []
    return render(request, 'index.html', locals())
# 文章详情页
def article(request):
    pass

# 搜索
def search(request):
    pass    


# 分类页
def category(request):
    pass
locals作用:不需要把结果(article_list )封装成上下文、local()自动将将结果作为上下文数据,并渲染到模板里

6、模板文件index.html

index.html继承了及基础base.html文件,基础文件包括栏目导航、内容部分(包括左边轮播,左边新闻列表、右边广告、右边热门新闻、右边广告、右边关注我们)、页脚部分

{% load staticfiles %}
{% load dictfilter %}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
<title></title>
<meta name="keywords" content="" />
<meta name="description" content="" />
<link href="{% static 'css/base.css' %}" rel="stylesheet">
{% block custom_css %}{% endblock %}
<script type="text/javascript" src="{% static 'js/jquery-1.11.1.min.js' %}"></script>
<script type="text/javascript" src="{% static 'js/slide.js' %}"></script>
<script type="text/javascript" src="{% static 'js/jquery.cookie.js' %}"></script>
{% block custom_js %}{% endblock %}

</head>
<body>
  <!--栏目导航-->
<div class="header">
    <div class="layout logo">
        <a href="http://www.careeru.cn/" class="logoimg"><img src="/static/images/careeru.png" class="logoimg"></a>
        <ul class="nav">
            <li class="cur"><a href="/">首页</a></li>
           {% for category in category_list %}
                {% if category|key:"id" == categoryid %}
                   <li class="columnnav  cur">
                {% else %}
                   <li class="columnnav">
                {% endif %}
                     <a href="{% url 'category' %}?cid={{category|key:"id" }}">{{category|key:"title" }}</a>
                   </li>

           {% endfor %}

        </ul>
        <div  class="userlogin">
           <div  id="logined" style="display: none">
             <span id="navlogout"><a href="javascript:void(0)">注销</a></span>
             <span id="navprofile"></span>
          </div>
          <div  id="nologin">
              <span id="navregister"><a class="curegister" href="javascript:;">注册</a></span>
              <span id="navlogin"><a class="ulogin" href="javascript:;" data-status="nologin">登录</a>    </span>
          </div>
     </div>
        <form  action="{% url 'search' %}" id="Search" name="search_box" method="get" target="_blank" >
            <input id="searchKey" title="请输入关键词" name="query"  autocomplete="off"  type="text">
            <input id="searchBtn" value=""  onclick="" aria-pressed="false" type="submit">
        </form>

    </div>
</div>
<!--内容部分-->
 <div class="layout">
      <!--左边部分-->
     {% with  ads=ad_list %}
      <div class="main">
          <!--左边轮播广告部分-->
          <div  class="ad">
                <div class="ad-inner ">
                    <div class="item active">
                          <!--广告大图片-->
                        <ul class="slidebox" id="" style="display: block;">
                            <div class="ad_slide">
                                    <ul id="slidelist" class="slideshow">
                                        {% for ad in ads %}

                                            <li style="display: block;">
                                                <a href="{{ ad.adurl }}" target="_blank" class="ad_imga">
                                                    <img src="{{ ad.pic }}"  width="880" height="300"></a>
                                            </li>
                                        {% endfor %}
                                    </ul>

                             </div>
                        </ul>
                    </div>
                </div>
          </div>
          <!--左边新闻列表部分-->
          {% block left_content %}{% endblock %}
      </div>
      <!--右边部分-->
      <div class="side">
          <!--广告-->
        <div class="author_ad ad_div">
                    <div  class="ad slide">
                            <div class="ad-inner star_div">
                                 {% for ad in ads %}
                                        {% if ad.adlocation == 'a2' %}
                                            <div class="item active">
                                                <a href="{{ ad.adurl }}" target="_blank">
                                                    <img src="{{ ad.pic }}" alt="" style="width:300px;height:300px;">
                                                </a>
                                            </div>
                                        {% endif %}
                                 {% endfor %}
                             </div>
                    </div>
        </div>
        <!--热门新闻-->

        <div class="hot module">
          <h3 class="subtitle">热门新闻</h3>
            <ul  class="article_lists">
                {% for hotactile in hot_articles %}
                  <li>
                     <i class="top3">{{ forloop.counter }}</i>
                     <a href="{% url 'article' %}?id={{ hotactile.id }}">{{ hotactile.title | slice:'15'}}</a>
                  </li>
                {% endfor %}

            </ul>
        </div>

        <!--广告-->
        <div class="ad2">
           <ul>
                {% for ad in ads %}
                     {% if ad.adlocation == 'a3' %}
                       <a href="{{ ad.adurl }}" target="_blank">
                         <li><img src="{{ ad.pic }}" width="300" ></li>
                       </a>
                      {% endif %}
                {% endfor %}
          </ul>
        </div>
        <!--关注我们-->
        <div class="follow">
         <div class="subtitle">关注我们</div>
          <div class="side_list">
             <img src="/static/images/careerqq0.8.png" >
          </div>

          <!--ms-main end -->
        </div>
      </div>
      {% endwith %}
      {%include 'loginlayer.html' %}
</div>
  <!--页脚部分-->
<footer>
  <p class="ft-copyright"></p>
 <div role="contentinfo" bosszone="footer" class="tcopyright" id="tcopyright">

    <div class="en">Copyright &copy; 2010- 2018 Careeru.cn All Rights Reserved</div>
    <div>
        <a rel="nofollow" target="_blank" href="/">可锐职场出品</a>
    </div>
</div>
</footer>
<script type="text/javascript">
   if ($.cookie('user')) {
       $('#nologin').css('display', 'none');
       $('#logined').css('display', 'block');
       $('#navprofile').html($.cookie('user'));
   };
</script>
</body>
</html>

我们看下栏目导航

 <ul class="nav">
        <li class="cur"><a href="/">首页</a></li>
       {% for category in category_list %}
            {% if category|key:"id" == categoryid %}
               <li class="columnnav  cur">
            {% else %}
               <li class="columnnav">
            {% endif %}
                 <a href="{% url 'category' %}?cid={{category|key:"id" }}">{{category|key:"title" }}</a>
               </li>
       {% endfor %}
    </ul>

首先取出分类数据,由于category_list数据是字典,我们需要写一个过滤器。
在article同级目录下新建python包命名为templatetags,在里面新建python文件命名为dictfilter.py

from django import template

register = template.Library()
@register.filter
def key(d, key_name):
    value = 0
    try:
        value = d[key_name]
    except KeyError:
        value = 0
    return value

这里我们往key里传入一个字典和一个键名,就能取出相应的值。
那么在index.html只需要写左边新闻列表部分

{% extends 'base.html' %}
{% load staticfiles %}
{% block left_content %}
    <div class="article_div module">
        <ul id="new_div">
        {% if  article_list %}
          {% for article in article_list %}
              <li class="news">
                <div>
                    <div class="flag">推荐</div>
                    <a href="{% url 'article' %}?id={{ article.id }}" target="_blank">
                    <img  src="{{ article.pic }} " class="pic"></a>
                    <div class="detail">
                        <div class="dtitle">
                            <a  href="{% url 'article' %}?id={{ article.id }}" target="_blank"><h2>{{ article.id }}-{{ article.title }}</h2></a>
                        </div>
                        <div class="desc">{{ article.content|striptags|safe|slice:"80" }}</div>
                        <div class="info">
                            <img src="/static/images/neter.jpg" class="img_small"><span>{{ article.author.username }}</span>
                            <div class="pv">
                               <span class="push-time">{{ article.publish_date |date:"Y-m-d H:i:s"}}</span><span class="column">
                               <a href="/">{{ article.item.title }}</a>&nbsp;</span>
                            </div>
                        </div>
                    </div>
                </div>
            </li>
           {% endfor %}
        {% else %}
         <div><img style="width:200px;padding-left:280px; " src="/static/images/nodata1.png"></div>
        {% endif %}
         </ul>
    </div>
    {% include 'page.html' %}
{% endblock %}

7、配置urls

from django.contrib import admin
from django.urls import path, re_path
from artcile.views import *

urlpatterns = [
    path('admin/', admin.site.urls),
    re_path(r'^$', index, name='index'),
    path('category/', category, name='category'),
    path('article/', article, name='article'),
    path('search/', search, name='search'),
  ]

这时打开浏览器:http://127.0.0.1:8000 就可以看到新闻类别、新闻列表、广告、轮播图、热门新闻、关注我们。


效果图
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容