Repository: hanyucd/movieweb_python Branch: master Commit: f3206df0b856 Files: 26 Total size: 102.6 KB Directory structure: gitextract_s4e40pa7/ ├── .gitignore ├── README.md └── movieweb/ ├── db.sqlite3 ├── manage.py ├── movieweb/ │ ├── __init__.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py └── videoplay/ ├── __init__.py ├── admin.py ├── forms.py ├── migrations/ │ ├── 0001_initial.py │ └── __init__.py ├── models.py ├── serializers.py ├── static/ │ ├── home_page.css │ ├── user_login.css │ ├── user_regist.css │ ├── video_play.css │ └── video_play.js ├── templates/ │ ├── index.html │ ├── user_login.html │ ├── user_regist.html │ └── video.html ├── tests.py └── views.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # git 提交忽略的文件 *.pyc ================================================ FILE: README.md ================================================ ## 网站相关技术: django 框架搭建整个网站 bootstrap 作为前端样式框架 使用微信 JS-SDK 开发工具包,对接微信分享API,使之视频播放页面支持微信分享 python 用于程序后台逻辑处理 使用 django 自带的数据库 Sqlite3 存储网站数据 > Admin(后台管理): 用户名:root 密码:root ## 项目环境相关依赖: Django 安装: ```bash > $ pip install Django==1.8.13 ``` Django REST framework 安装: ```bash > $ pip install djangorestframework ``` Django REST Swagger 安装: ```bash > $ pip install django-rest-swagger ``` Requests 安装: ```bash > $ pip install requests ``` ## 项目运行: ```bash > $ python manage.py runserver 端口 ``` ## 项目展示: __[视频网站(部分内容)](http://oojestrjh.bkt.clouddn.com/movieweb/index.html)__ > PC 端 __首页:__ ![网站首页](./image/pc_movie01.jpg "首页") __播放页面:__ ![网站播放页面](./image/pc_movie02.jpg "播放页面") > 移动端 ![移动端效果](./image/mobile.jpg "移动端效果") © Movie website. Developer by [hanyu](https://github.com/hanyucd). ================================================ FILE: movieweb/manage.py ================================================ #!/usr/bin/env python import os import sys if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "movieweb.settings") from django.core.management import execute_from_command_line execute_from_command_line(sys.argv) ================================================ FILE: movieweb/movieweb/__init__.py ================================================ ================================================ FILE: movieweb/movieweb/settings.py ================================================ """ Django settings for movieweb project. Generated by 'django-admin startproject' using Django 1.8.13. For more information on this file, see https://docs.djangoproject.com/en/1.8/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/1.8/ref/settings/ """ # Build paths inside the project like this: os.path.join(BASE_DIR, ...) import os BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = '&7!w5(_zz(3ar)hkvkl1kwg=wn&e!5pt#9xs(xjeo0%wm1665c' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'videoplay', 'rest_framework', 'rest_framework_swagger', ) MIDDLEWARE_CLASSES = ( 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', # 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.security.SecurityMiddleware', ) ROOT_URLCONF = 'movieweb.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], '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', ], }, }, ] WSGI_APPLICATION = 'movieweb.wsgi.application' # Database # https://docs.djangoproject.com/en/1.8/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': 'movieweb.db', # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } # Internationalization # https://docs.djangoproject.com/en/1.8/topics/i18n/ LANGUAGE_CODE = 'zh-hans' # LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/1.8/howto/static-files/ STATIC_URL = '/static/' ================================================ FILE: movieweb/movieweb/urls.py ================================================ # -*- coding: UTF-8 -*- """movieweb URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/1.8/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') Including another URLconf 1. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) """ from django.conf.urls import include, url from django.contrib import admin from videoplay.views import index, play, regist, login # 实现swagger code from videoplay import views from rest_framework import renderers, response, schemas from rest_framework.decorators import api_view, renderer_classes from rest_framework.routers import DefaultRouter from rest_framework_swagger.renderers import OpenAPIRenderer, SwaggerUIRenderer @api_view() @renderer_classes([SwaggerUIRenderer, OpenAPIRenderer, renderers.CoreJSONRenderer]) def schema_view(request): generator = schemas.SchemaGenerator(title='Data API') return response.Response(generator.get_schema(request=request)) # Routers(路由)提供了一种简单的方法来自动生成URL配置 router = DefaultRouter() router.register(r'movie', views.SnippetViewSet) urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'^regist/$', regist), url(r'^$', login), url(r'^movie/$', index), url(r'^movie/video_(?P\d{1,2}).html$', play), url(r'^swagger$', schema_view), url(r'^', include(router.urls)), # url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')) ] ================================================ FILE: movieweb/movieweb/wsgi.py ================================================ """ WSGI config for movieweb project. It exposes the WSGI callable as a module-level variable named ``application``. For more information on this file, see https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/ """ import os from django.core.wsgi import get_wsgi_application os.environ.setdefault("DJANGO_SETTINGS_MODULE", "movieweb.settings") application = get_wsgi_application() ================================================ FILE: movieweb/videoplay/__init__.py ================================================ ================================================ FILE: movieweb/videoplay/admin.py ================================================ from django.contrib import admin from videoplay.models import Movie, User, UserComment, MoviePay # Register your models here. admin.site.register(Movie) admin.site.register(User) admin.site.register(UserComment) admin.site.register(MoviePay) ================================================ FILE: movieweb/videoplay/forms.py ================================================ # -*- coding: UTF-8 -*- # 导入表单 from django import forms ''' 用户注册/登录数据 ''' class UserForm(forms.Form): username = forms.CharField(max_length = 20) password = forms.IntegerField() ''' 用户评论数据 ''' class UserCommentForm(forms.Form): user_comment = forms.CharField(max_length = 300) ''' 电影支付数据 ''' class MoviePayForm(forms.Form): movie_pay = forms.IntegerField() ================================================ FILE: movieweb/videoplay/migrations/0001_initial.py ================================================ # -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ ] operations = [ migrations.CreateModel( name='Movie', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('movie', models.CharField(max_length=100)), ], ), migrations.CreateModel( name='MoviePay', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('pay_username', models.CharField(max_length=20)), ('movie_id', models.IntegerField()), ('movie_pay', models.IntegerField()), ], ), migrations.CreateModel( name='User', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('username', models.CharField(max_length=20)), ('password', models.IntegerField()), ], ), migrations.CreateModel( name='UserComment', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('comment_username', models.CharField(max_length=20)), ('user_comment', models.CharField(max_length=300)), ('comment_time', models.CharField(max_length=40)), ], ), ] ================================================ FILE: movieweb/videoplay/migrations/__init__.py ================================================ ================================================ FILE: movieweb/videoplay/models.py ================================================ # -*- coding: UTF-8 -*- from django.db import models # Create your models here. ''' 视频 URL 存数据库 ''' class Movie(models.Model): movie = models.CharField(max_length = 100) def __str__(self): return self.movie ''' 用户名 存数据库 ''' class User(models.Model): username = models.CharField(max_length = 20) password = models.IntegerField() def __str__(self): return '%s | %s' % (self.username, self.password) ''' 用户评论 存数据库 ''' class UserComment(models.Model): comment_username = models.CharField(max_length = 20) user_comment = models.CharField(max_length = 300) comment_time = models.CharField(max_length = 40) def __str__(self): return "%s : %s | %s" % (self.comment_username, self.user_comment, self.comment_time) ''' 用户支付 存数据库 ''' class MoviePay(models.Model): pay_username = models.CharField(max_length = 20) movie_id = models.IntegerField() movie_pay = models.IntegerField() def __str__(self): return "user: %s / movie_id: %d / pay: %d" % (self.pay_username, self.movie_id, self.movie_pay) ================================================ FILE: movieweb/videoplay/serializers.py ================================================ # -*- coding: UTF-8 -*- from rest_framework import serializers from videoplay.models import Movie # Serializers(序列化器)定义了如何展示API class MovieSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Movie fields = ('movie',) ================================================ FILE: movieweb/videoplay/static/home_page.css ================================================ #user { padding-left: 10px; margin-top: 20px } .figures_lists { margin-left: 0; padding: 0; list-style-type: none; } .list_item { display: inline-block; /*float: left;*/ vertical-align: top; margin-bottom: 20px; position: relative; } .label_title { position: absolute; top: 0; left: 0; background-color: #1CBF11; border-radius: 10px; } .label_font { color: #fff; padding: 0 5px; } #my-content { margin: 25px auto; padding: 0 10px; } #my-content:first-child { padding: 0; } .figure_title>a { display: block; } .figure img { width: 80%; } .new_image { position: absolute; top: 0; left: 0; } /*@media 设备类型 and|only|not (设备特性) {样式代码}*/ @media handheld and (max-device-width: 768px) { .nav>li { display: inline-table; margin-right: 10px; } .container { padding-left: 0; padding-right: 0; margin: 0 10px; } .list_item { width: 32%; } } @media screen and (max-width: 768px) { .nav>li { display: inline-block; margin-right: 10px; } .container { padding-left: 0; padding-right: 0; margin: 0 10px; } .list_item { width: 32%; } } ================================================ FILE: movieweb/videoplay/static/user_login.css ================================================ #cont { margin: auto; margin-top: 150px; width: 500px; } a { float: right; } .my_btn { margin-left: 30px; } ================================================ FILE: movieweb/videoplay/static/user_regist.css ================================================ #cont { margin: auto; margin-top: 150px; width: 800px; /*border: 1px solid black;*/ } #btn { padding-left: 5px; } ================================================ FILE: movieweb/videoplay/static/video_play.css ================================================ div.container{ margin-top: 50px; } .my_font { font-size: 20px; font-weight: bolder; } #all_comment { margin-top: 15px; border-bottom: 1px solid #87CEFA; } .single_comment { min-height: 100px; display: flex; margin-bottom: 3px; border-bottom: 1px solid #D8D8D8; } .username { min-width: 100px; margin: auto 0; } .contents { padding: 15px; min-width: 600px; } .comment_time { margin: auto 0; } ================================================ FILE: movieweb/videoplay/static/video_play.js ================================================ // alert('js代码引入成功....') // var my_video = document.getElementById("my_video"); // my_video.ontimeupdate = function() { // var currentTime = my_video.currentTime; // var duration = my_video.duration; // document.getElementById("current_time").innerHTML = currentTime; // document.getElementById('video_duration').innerHTML = duration; // if (currentTime >= 60) { // // my_video.load(); // my_video.pause(); // } // } ================================================ FILE: movieweb/videoplay/templates/index.html ================================================ 小宇视频 {% load staticfiles %}
{% if error %}

☹ 欧漏。你还未登录 or 用户名存储已过期,可重新登录 ……

{% else %}

☺ 登录成功。欢迎用户 {{ username }},来到小宇视频 ……

{% endif %}

================================================ FILE: movieweb/videoplay/templates/user_login.html ================================================ 视频登录界面 {% load staticfiles %}
{% if userName_error %}

没有该用户名 或 用户名错误,请注册 ...

{% endif %} {% if userPassword_error %}

密码错误,请重新输入 ...

{% endif %} {% if userForm_error %}

输入的数据为空 或 输入的数据不合法 ...

{% endif %}
还没账号,立即注册
================================================ FILE: movieweb/videoplay/templates/user_regist.html ================================================ 用户注册界面 {% load staticfiles %}
{% if danger %} {% endif %}

用户注册


================================================ FILE: movieweb/videoplay/templates/video.html ================================================ 视频播放页面 {% load staticfiles %}
{% if video_id < 6 %} {% if pay %}

此电影已购买,可观看完整版...

{% else %}

此电影需要购买,尚可观看1分钟...

{% endif %} {% else %}

此电影可免费观看...

{% endif %}

当前播放时长/秒:

总时长/秒:


用户评论:

全部评论

    {% for comment in comments_list reversed %}
  • {{ comment.comment_username }}

    {{ comment.user_comment }}

    {{ comment.comment_time }}

  • {% endfor %}
  • 匿名用户

    三国吕布,字奉先。

    2016/10/09 | 14:00:30

================================================ FILE: movieweb/videoplay/tests.py ================================================ from django.test import TestCase # Create your tests here. ================================================ FILE: movieweb/videoplay/views.py ================================================ # -*- coding: UTF-8 -*- from django.shortcuts import render # Create your views here. from django.http import HttpResponse, HttpResponseRedirect from django.template import loader, Context from django.shortcuts import render_to_response import time import random import string import hashlib import requests # 导入缓存 from django.core.cache import cache # 导入模型 from videoplay.models import Movie from videoplay.models import User, UserComment, MoviePay # 导入表单 from .forms import UserForm, UserCommentForm, MoviePayForm class Sign: ''' 实例化初始值 ''' def __init__(self, appid, appsecret, url): self.appid = appid # self.access_token = self.get_access_token(appid, appsecret) ''' 缓存access_token ''' self.access_token = cache.get('access_token') if self.access_token == None: cache.set('access_token', self.get_access_token(appid, appsecret), 7050) self.access_token = cache.get('access_token') ''' 缓存jsapi_ticket ''' self.jsapi_ticket = cache.get('jsapi_ticket') if self.jsapi_ticket == None: cache.set('jsapi_ticket', self.get_ticket(self.access_token), 7100) self.jsapi_ticket = cache.get('jsapi_ticket') self.ret = { 'nonceStr': self.__create_nonce_str(), 'jsapi_ticket': self.jsapi_ticket, 'timestamp': self.__create_timestamp(), 'url': url, } # 缓存signature # self.signature = cache.get('signature') # if self.signature == None: # cache.set('signature', self.sign(), 7150) # self.signature = cache.get('signature') ''' 获取随机字符串 ''' def __create_nonce_str(self): return ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(16)) ''' 获取时间戳 ''' def __create_timestamp(self): return int(time.time()) ''' 获取access_token ''' def get_access_token(self, appid, appsecret): url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}'.format(appid,appsecret) r = requests.get(url) data = r.json() access_token = data.get('access_token') return access_token ''' 获取jsapi_ticket ''' def get_ticket(self, access_token, type='jsapi'): url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={}&type={}'.format(access_token, type) r = requests.get(url) data = r.json() ticket = data.get('ticket') return ticket ''' 获取signature ''' def sign(self): string = '&'.join(['%s=%s' % (key.lower(), self.ret[key]) for key in sorted(self.ret)]) self.ret['signature'] = hashlib.sha1(string).hexdigest() return self.ret # return self.ret.get('signature') """ 视频播放页面 """ def play(request, id): # 通过 session 来获取传过来的数据 (用户名) comment_username = request.session.get('comment_username') if request.method == "POST": print request.POST if 'user_comment' in request.POST: ''' 用户评论 ''' # 绑定评论表单 uf_comment = UserCommentForm(request.POST) # 校验提交数据是否合法 if uf_comment.is_valid(): # 如合法,获取数据并赋于变量 user_comment = uf_comment.cleaned_data.get('user_comment') # 获取当前时间 (格式化) comment_time = time.strftime('%Y/%m/%d | %H:%M:%S', time.localtime()) # 存入数据库 UserComment.objects.create(comment_username = comment_username, user_comment = user_comment, comment_time = comment_time) print user_comment print comment_time # 获取当前除域名以外的请求路径 path = request.path print path ''' 重定向到当前页面 ''' return HttpResponseRedirect(path) elif 'movie_pay' in request.POST: ''' 电影支付 ''' movie_id = int(id) # 绑定支付表单 uf_payment = MoviePayForm(request.POST) # 校验提交数据是否合法 if uf_payment.is_valid(): # 获取支付数据 movie_pay = uf_payment.cleaned_data.get('movie_pay') # 存入数据库 MoviePay.objects.create(pay_username = comment_username, movie_id = movie_id, movie_pay = movie_pay) # 获取当前除域名以外的请求路径 path = request.path ''' 重定向到当前页面 ''' return HttpResponseRedirect(path) ''' 微信分享的 code ''' appid, appsecret = 'wx89d78fda8c962552', '41d433fe0e3194e1aff2d607c585be65' # 动态获取当前的url url = 'http://' + request.get_host() + request.get_full_path() sign = Sign(appid, appsecret, url) # 调用签名方法 sign.sign() # 将获取到的字符串类型参数转换为 int video_id = int(id) # 获取(数据库)模型中对应电影的对象 video_source = Movie.objects.get(id = video_id) # 获取数据库中所有的评论对象 | all() 和 filter()函数返回一个记录集 (列表) comments_list = UserComment.objects.all() # 获取数据库中已支付的对象 movie_payment_obj = MoviePay.objects.filter(pay_username = comment_username, movie_id = video_id) # 支付 False:未购买 True: 已购买 pay = False if video_id <= 5: if len(movie_payment_obj) != 0: pay = True else: pay = False # 加载视频播放模板 t = loader.get_template("video.html") c = Context({"user": sign, "video_source": video_source, "video_id": video_id,"movie_payment_obj": len(movie_payment_obj), "pay": pay, "url": url, "comments_list": comments_list}) return HttpResponse(t.render(c)) """ 用户注册 """ def regist(request): if request.method == "POST": # 绑定表单 uf_regist = UserForm(request.POST) # 校验提交数据是否合法 if uf_regist.is_valid(): # 如合法,获取各自的数据并赋于变量 username = uf_regist.cleaned_data.get('username') password = uf_regist.cleaned_data.get('password') # 存入数据库 User.objects.create(username = username, password = password) # 跳转到登录界面 return HttpResponseRedirect('/') else: return render(request, "user_regist.html", {"danger": True}) else: uf_regist = UserForm() # 加载用户注册模板 user_regist = loader.get_template("user_regist.html") return HttpResponse(user_regist.render()) """ 用户登录 """ def login(request): if request.method == 'POST': # 绑定表单 | request.Post:获取表单提交的数据 (类字典对象) uf_login = UserForm(request.POST) # 校验提交数据是否合法 if uf_login.is_valid(): # 如合法后,获取各自的数据并赋于变量 username = uf_login.cleaned_data['username'] password = uf_login.cleaned_data['password'] ''' 异常 用户名不存在 ''' try: User.objects.get(username = username) except User.DoesNotExist: return render_to_response('user_login.html', {"userName_error": True}) # 获取数据库(模型)中对应的对象 user = User.objects.filter(username__exact = username, password__exact = password) # 如果输入的对象匹配数据库中的对象为 True(存在数据库中) if user: # 创建 HTTpResponse 对象(跳转至 /movie 页面) response = HttpResponseRedirect('/movie/') # 设置 cookie 值,有效期 1 小时 response.set_cookie('username', username) # response.set_cookie('username', username, 3600) # request.session['username'] = username /使用 session 来设置 cookie值, 等效同上 return response # 输入的密码不匹配数据库中的密码 执行 elif password != User.objects.get(username = username).password: return render_to_response('user_login.html', {"userPassword_error" : True}) # 如果输入的内容不合法(数据为空) else: return render_to_response('user_login.html', {'userForm_error': True}) else: uf_login = UserForm() # 加载用户登录模板 user_login = loader.get_template("user_login.html") return HttpResponse(user_login.render()) """ 网站首页 """ def index(request): username = request.COOKIES.get('username', None) # username = request.session.get('username', 'anonymity') /使用 session 来获取传来的 cookie值, 等效同上 ''' 设置 session 的数据(传到视频播放页面)''' request.session['comment_username'] = username # 获取用户名成功 执行 if username != None: return render_to_response('index.html', {"username": username}) # 用户名超时 执行 else: return render_to_response('index.html', {'error': True}) """ 实现swagger code """ from rest_framework import viewsets from videoplay.models import Movie from videoplay.serializers import MovieSerializer # ViewSets定义了View的行为 class SnippetViewSet(viewsets.ModelViewSet): queryset = Movie.objects.all() serializer_class = MovieSerializer