項目源碼下載: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 就可以看到新聞類別、新聞列表、廣告、輪播圖、熱門新聞、關注我們。