项目源码下载: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 © 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> </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 就可以看到新闻类别、新闻列表、广告、轮播图、热门新闻、关注我们。