├── .gitignore ├── dilidili ├── .gitignore ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py ├── dilidili_dev ├── __init__.py ├── admin.py ├── admin_user_urls.py ├── admin_video.py ├── admin_views.py ├── forms.py ├── home_view.py ├── logout_in.py ├── message.py ├── models.py ├── search.py ├── tests.py ├── upload_photo.py ├── users.py ├── video_play.py ├── video_upload.py └── views.py ├── manage.py ├── media └── photos │ └── 001.jpg ├── readme.md ├── static ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.woff2 ├── images │ ├── 0.jpg │ ├── 2233.png │ ├── aa0.jpg │ ├── aa1.jpg │ ├── aa2.jpg │ ├── bg.jpg │ ├── dilidili_logo.png │ ├── dot.png │ ├── favicon.ico │ ├── hehe.jpg │ ├── icons.png │ ├── icons3.png │ ├── icons_home.png │ ├── icons_v.png │ ├── morecomm.gif │ ├── register_bg.jpg │ ├── ui-bg_diagonals-thick_18_b81900_40x40.png │ ├── ui-bg_diagonals-thick_20_666666_40x40.png │ ├── ui-bg_flat_10_000000_40x100.png │ ├── ui-bg_glass_100_f6f6f6_1x400.png │ ├── ui-bg_glass_100_fdf5ce_1x400.png │ ├── ui-bg_glass_65_ffffff_1x400.png │ ├── ui-bg_gloss-wave_35_f6a828_500x100.png │ ├── ui-bg_highlight-soft_100_eeeeee_1x100.png │ ├── ui-bg_highlight-soft_75_ffe45c_1x100.png │ ├── ui-icons_222222_256x240.png │ ├── ui-icons_228ef1_256x240.png │ ├── ui-icons_ef8c08_256x240.png │ ├── ui-icons_ffd27a_256x240.png │ ├── ui-icons_ffffff_256x240.png │ ├── v-play.png │ └── v_ttl.png ├── scripts │ ├── ajax-send.js │ ├── bootstrap.min.js │ ├── bullet-send.js │ ├── comment-send.js │ ├── form-check.js │ ├── home.js │ ├── jquery-ui.min.js │ ├── jquery.min.js │ ├── message.js │ ├── personal-admin.js │ ├── personal-follow.js │ ├── search-main.js │ ├── video-page-action.js │ ├── video-page-admin.js │ ├── video-page-own.js │ ├── video-page-post.js │ ├── video-page-show.js │ ├── video-upload-form.js │ └── video.js ├── styles │ ├── base.css │ ├── bootstrap.min.css │ ├── dd-style.css │ ├── font │ │ ├── vjs.eot │ │ ├── vjs.svg │ │ ├── vjs.ttf │ │ └── vjs.woff │ ├── home.css │ ├── index.css │ ├── jquery-ui.min.css │ ├── message.css │ ├── personal-admin.css │ ├── personal.css │ ├── register.css │ ├── search-result.css │ ├── sendto.css │ ├── upload.css │ ├── video-js.min.css │ └── video.css └── swf │ └── video-js.swf └── templates ├── base.html ├── forms ├── process-photo.html ├── upload-photo.html └── upload-success.html ├── home ├── collection-list.html ├── follow-list.html ├── home.html └── main-content.html ├── index └── index.html ├── message ├── message.html └── sendto.html ├── personal └── personal.html ├── registration ├── login.html └── register.html ├── search ├── search-result.html ├── search.html └── search_bak.html ├── upload └── upload.html └── video ├── video-notfound.html └── video.html /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | 26 | # PyInstaller 27 | # Usually these files are written by a python script from a template 28 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 29 | *.manifest 30 | *.spec 31 | 32 | # Installer logs 33 | pip-log.txt 34 | pip-delete-this-directory.txt 35 | 36 | # Unit test / coverage reports 37 | htmlcov/ 38 | .tox/ 39 | .coverage 40 | .coverage.* 41 | .cache 42 | nosetests.xml 43 | coverage.xml 44 | *,cover 45 | 46 | # Translations 47 | *.mo 48 | *.pot 49 | 50 | # Django stuff: 51 | *.log 52 | 53 | # Sphinx documentation 54 | docs/_build/ 55 | 56 | # PyBuilder 57 | target/ 58 | 59 | #PyCharm file 60 | .idea/ 61 | 62 | #process file 63 | dilidili_dev/migrations/ 64 | 65 | #media files 66 | media/ -------------------------------------------------------------------------------- /dilidili/.gitignore: -------------------------------------------------------------------------------- 1 | dbs.py 2 | -------------------------------------------------------------------------------- /dilidili/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/dilidili/__init__.py -------------------------------------------------------------------------------- /dilidili/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for dilidili project. 3 | 4 | Generated by 'django-admin startproject' using Django 1.8.3. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.8/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/1.8/ref/settings/ 11 | """ 12 | 13 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 14 | import os 15 | 16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = 'a!@7h59kz074@714+nbm14bm)8iyzvt@@jq25^)_cruru&3zf)' 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | DEBUG = True 27 | 28 | ALLOWED_HOSTS = [] 29 | 30 | 31 | # Application definition 32 | 33 | INSTALLED_APPS = ( 34 | 'django_admin_bootstrapped', 35 | 'django.contrib.admin', 36 | 'django.contrib.auth', 37 | 'django.contrib.contenttypes', 38 | 'django.contrib.sessions', 39 | 'django.contrib.messages', 40 | 'django.contrib.staticfiles', 41 | 'django.contrib.sites', 42 | 'easy_thumbnails', 43 | 'image_cropping', 44 | 'dilidili_dev', 45 | ) 46 | 47 | MIDDLEWARE_CLASSES = ( 48 | 'django.contrib.sessions.middleware.SessionMiddleware', 49 | 'django.middleware.common.CommonMiddleware', 50 | 'django.middleware.csrf.CsrfViewMiddleware', 51 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 52 | 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 53 | 'django.contrib.messages.middleware.MessageMiddleware', 54 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 55 | 'django.middleware.security.SecurityMiddleware', 56 | ) 57 | 58 | ROOT_URLCONF = 'dilidili.urls' 59 | 60 | TEMPLATES = [ 61 | { 62 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 63 | 'DIRS': [os.path.join(BASE_DIR, 'templates')], 64 | 'APP_DIRS': True, 65 | 'OPTIONS': { 66 | 'context_processors': [ 67 | 'django.template.context_processors.debug', 68 | 'django.template.context_processors.request', 69 | 'django.contrib.auth.context_processors.auth', 70 | 'django.contrib.messages.context_processors.messages', 71 | ], 72 | }, 73 | }, 74 | ] 75 | 76 | WSGI_APPLICATION = 'dilidili.wsgi.application' 77 | 78 | 79 | # Database 80 | # https://docs.djangoproject.com/en/1.8/ref/settings/#databases 81 | 82 | from .dbs import databases 83 | DATABASES = databases 84 | 85 | 86 | # Internationalization 87 | # https://docs.djangoproject.com/en/1.8/topics/i18n/ 88 | 89 | LANGUAGE_CODE = 'en-us' 90 | 91 | TIME_ZONE = 'UTC' 92 | 93 | USE_I18N = True 94 | 95 | USE_L10N = True 96 | 97 | USE_TZ = True 98 | 99 | 100 | # Static files (CSS, JavaScript, Images) 101 | # https://docs.djangoproject.com/en/1.8/howto/static-files/ 102 | 103 | TEMPLATE_DIRS = ( 104 | os.path.join(BASE_DIR, 'templates'), 105 | ) 106 | 107 | AUTH_USER_MODEL = 'dilidili_dev.User' 108 | 109 | MEDIA_ROOT = os.path.join(BASE_DIR, 'media') 110 | 111 | # STATIC_ROOT = os.path.join(BASE_DIR, 'static') 112 | 113 | MEDIA_URL = '/media/' 114 | 115 | STATIC_URL = '/static/' 116 | 117 | STATICFILES_DIRS = ( 118 | os.path.join(BASE_DIR, 'static'), 119 | ) 120 | 121 | from easy_thumbnails.conf import Settings as thumbnail_settings 122 | THUMBNAIL_PROCESSORS = ( 123 | 'image_cropping.thumbnail_processors.crop_corners', 124 | ) + thumbnail_settings.THUMBNAIL_PROCESSORS 125 | 126 | SITE_ID = 1 127 | -------------------------------------------------------------------------------- /dilidili/urls.py: -------------------------------------------------------------------------------- 1 | """dilidili URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/1.8/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Add an import: from blog import urls as blog_urls 14 | 2. Add a URL to urlpatterns: url(r'^blog/', include(blog_urls)) 15 | """ 16 | from django.conf.urls import include, url 17 | from django.contrib import admin 18 | import dilidili.settings as settings 19 | 20 | urlpatterns = [ 21 | url(r'^$', 'dilidili_dev.views.index'), 22 | url(r'^category/(?P[0-9]+)', 'dilidili_dev.views.category_index'), 23 | url(r'^admin/', include(admin.site.urls)), 24 | url(r'^register/', 'dilidili_dev.views.register'), 25 | url(r'^logout/', 'dilidili_dev.logout_in.logout'), 26 | url(r'^login/', 'dilidili_dev.logout_in.login'), 27 | url(r'^personal/(?P[0-9]+)/', include('dilidili_dev.admin_user_urls')), 28 | url(r'^video/(?P[0-9]+)/', include([ 29 | url(r'^$', 'dilidili_dev.video_play.video_play'), 30 | url(r'^remove/$', 'dilidili_dev.admin_video.remove'), 31 | url(r'^togglepublish/$', 'dilidili_dev.admin_video.togglepublish') 32 | ])), 33 | url(r'^video-add-play/$', 'dilidili_dev.views.video_play_add'), 34 | url(r'^video-add-bullet/$', 'dilidili_dev.video_play.video_bullet_add'), 35 | url(r'^video-add-comment/$', 'dilidili_dev.video_play.video_comment_add'), 36 | url(r'^video-get-bullet/$', 'dilidili_dev.video_play.video_bullet_get'), 37 | url(r'^video-get-comment/$', 'dilidili_dev.video_play.get_video_comment'), 38 | url(r'^video-del-comment/$', 'dilidili_dev.video_play.del_video_comment'), 39 | url(r'^video-set-collcetion/$', 'dilidili_dev.video_play.set_collection'), 40 | url(r'^video-set-like/$', 'dilidili_dev.video_play.set_like'), 41 | url(r'^video-add-money/$', 'dilidili_dev.video_play.add_money'), 42 | url(r'^home/', include([ 43 | url(r'^$', 'dilidili_dev.views.home'), 44 | url(r'^following/$', 'dilidili_dev.home_view.following'), 45 | url(r'^follower/$', 'dilidili_dev.home_view.follower'), 46 | url(r'^collection/$', 'dilidili_dev.home_view.collection'), 47 | url(r'^center/$', 'dilidili_dev.home_view.center') 48 | ])), 49 | url(r'^upload/$', 'dilidili_dev.views.upload'), 50 | url(r'^upload-photo/$', 'dilidili_dev.upload_photo.upload_photo'), 51 | url(r'^upload-success/$', 'dilidili_dev.upload_photo.upload_success'), 52 | url(r'^process-photo/$', 'dilidili_dev.upload_photo.process_img', name='process-photo'), 53 | url(r'^search/$', 'dilidili_dev.search.search_mainpage'), 54 | url(r'^search/request/$', 'dilidili_dev.search.search'), 55 | url(r'^search/resulthtml/$', 'dilidili_dev.search.search_html'), 56 | url(r'^inbox/$', 'dilidili_dev.message.inbox'), 57 | url(r'^unread-msg/$', 'dilidili_dev.message.get_unread_num'), 58 | url(r'^sendto/(?P[0-9]+)/$', 'dilidili_dev.message.sendto'), 59 | url(r'^del-msg/(?P[0-9]+)/(?P[0-9]+)/$', 'dilidili_dev.message.del_msg'), 60 | url(r'^media/(?P.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}), 61 | ] 62 | -------------------------------------------------------------------------------- /dilidili/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for dilidili project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dilidili.settings") 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /dilidili_dev/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/dilidili_dev/__init__.py -------------------------------------------------------------------------------- /dilidili_dev/admin.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.contrib import admin 3 | from django.contrib.auth.models import Group 4 | from django.contrib.auth.admin import UserAdmin 5 | from django.contrib.auth.forms import ReadOnlyPasswordHashField 6 | from django.utils.html import format_html 7 | 8 | from dilidili_dev.users import User 9 | from dilidili_dev.models import * 10 | 11 | 12 | class UserCreationForm(forms.ModelForm): 13 | """A form for creating new users. Includes all the required 14 | fields, plus a repeated password.""" 15 | password1 = forms.CharField(label='Password', widget=forms.PasswordInput) 16 | password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput) 17 | 18 | class Meta: 19 | model = User 20 | fields = ('username', 'name', 'email', 'describe', 'image') 21 | 22 | def clean_password2(self): 23 | # Check that the two password entries match 24 | password1 = self.cleaned_data.get("password1") 25 | password2 = self.cleaned_data.get("password2") 26 | if password1 and password2 and password1 != password2: 27 | raise forms.ValidationError("Passwords don't match") 28 | return password2 29 | 30 | def save(self, commit=True): 31 | # Save the provided password in hashed format 32 | user = super(UserCreationForm, self).save(commit=False) 33 | user.set_password(self.cleaned_data["password1"]) 34 | if commit: 35 | user.save() 36 | return user 37 | 38 | 39 | class UserChangeForm(forms.ModelForm): 40 | """A form for updating users. Includes all the fields on 41 | the user, but replaces the password field with admin's 42 | password hash display field. 43 | """ 44 | password = ReadOnlyPasswordHashField() 45 | 46 | class Meta: 47 | model = User 48 | fields = ('username', 'password', 'email', 'id', 'describe', 'money', 'is_active', 'is_admin') 49 | 50 | def clean_password(self): 51 | # Regardless of what the user provides, return the initial value. 52 | # This is done here, rather than on the field, because the 53 | # field does not have access to the initial value 54 | return self.initial["password"] 55 | 56 | 57 | class MyUserAdmin(UserAdmin): 58 | # The forms to add and change user instances 59 | form = UserChangeForm 60 | add_form = UserCreationForm 61 | 62 | # The fields to be used in displaying the User model. 63 | # These override the definitions on the base UserAdmin 64 | # that reference specific fields on auth.User. 65 | list_display = ('id', 'username', 'name', 'email', 'is_admin', 'view_page', ) 66 | list_filter = ('is_admin',) 67 | fieldsets = ( 68 | (None, {'fields': ('name', 'username', 'password')}), 69 | ('Personal info', {'fields': ('describe', 'email', 'money', 'image', 'cropping')}), 70 | ('Permissions', {'fields': ('is_admin', 'is_active', 'can_comment', 'can_upload', 'can_bullet')}), 71 | ) 72 | # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin 73 | # overrides get_fieldsets to use this attribute when creating a user. 74 | add_fieldsets = ( 75 | (None, { 76 | 'classes': ('wide',), 77 | 'fields': ('username', 'password1', 'password2', 'email', 'name', 'describe', 'image')} 78 | ), 79 | ) 80 | search_fields = ('username',) 81 | ordering = ('id', 'username',) 82 | filter_horizontal = () 83 | 84 | def view_page(self, obj): 85 | return format_html('View', obj.get_absolute_url()) 86 | view_page.allow_tags = True 87 | 88 | 89 | # Now register the new UserAdmin... 90 | admin.site.register(User, MyUserAdmin) 91 | admin.site.unregister(Group) 92 | 93 | class VideoAdmin(admin.ModelAdmin): 94 | list_display = ('id', 'name', 'tag', 'time', 'status', 'published', 'view_link',) 95 | list_filter = ('status', ) 96 | ordering = ('-time', 'id',) 97 | search_fields = ('name', 'describe',) 98 | fieldsets = [ 99 | ('Basic info', {'fields': ['name', 'describe', 'tag', 'category_set']}), 100 | ('Files', {'fields': ['video', 'image']}), 101 | ('Status', {'fields': ['status']}) 102 | ] 103 | actions = ['mark_as_invalid', 'make_published'] 104 | 105 | def view_link(self, obj): 106 | return format_html('View', obj.get_absolute_url()) 107 | view_link.allow_tags = True 108 | 109 | def published(self, obj): 110 | return obj.status == 0 111 | published.boolean = True 112 | 113 | def make_published(self, request, queryset): 114 | queryset.update(status=0) 115 | make_published.short_description = "发布选中的视频" 116 | 117 | def mark_as_invalid(self, request, queryset): 118 | queryset.update(status=2) 119 | mark_as_invalid.short_description = "标记为审核不通过" 120 | 121 | 122 | admin.site.register(Video, VideoAdmin) 123 | -------------------------------------------------------------------------------- /dilidili_dev/admin_user_urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import include, url 2 | 3 | urlpatterns = [ 4 | url(r'^$', 'dilidili_dev.views.personal'), 5 | url(r'^togglefollow/$', 'dilidili_dev.views.user_toggle_follow'), 6 | url(r'^admin/', include([ 7 | url(r'^toggleupload/$', 'dilidili_dev.admin_views.toggle_user_upload'), 8 | url(r'^togglecomment/$', 'dilidili_dev.admin_views.toggle_user_comment'), 9 | url(r'^togglebullet/$', 'dilidili_dev.admin_views.toggle_user_bullet'), 10 | ])), 11 | ] 12 | -------------------------------------------------------------------------------- /dilidili_dev/admin_video.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from django.http import HttpResponse, HttpResponseRedirect, Http404, JsonResponse, HttpResponseForbidden 3 | from django.core.urlresolvers import reverse 4 | from django.views.decorators.http import require_http_methods 5 | from dilidili_dev.models import Video 6 | from django.contrib import auth 7 | from dilidili_dev.users import User 8 | 9 | @require_http_methods(["GET"]) 10 | def remove(request, video_id): 11 | if not request.user.is_authenticated(): 12 | return HttpResponseForbidden() 13 | try: 14 | video = Video.objects.get(pk=video_id) 15 | except Video.DoesNotExist: 16 | return Http404("Video not found") 17 | if request.user.pk != video.owner.pk: 18 | return HttpResponseForbidden() 19 | else: 20 | video.delete() 21 | return HttpResponseRedirect("/home/") 22 | 23 | 24 | @require_http_methods(["POST"]) 25 | def togglepublish(request, video_id): 26 | if not request.user.is_authenticated() or not request.user.is_admin: 27 | return HttpResponseForbidden() 28 | try: 29 | video = Video.objects.get(pk=video_id) 30 | except Video.DoesNotExist: 31 | return Http404("Video not found") 32 | video.status = 0 if video.status != 0 else 2 33 | video.save() 34 | return HttpResponse() 35 | 36 | -------------------------------------------------------------------------------- /dilidili_dev/admin_views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from django.http import HttpResponse, HttpResponseRedirect, Http404, JsonResponse, HttpResponseForbidden 3 | from django.core.urlresolvers import reverse 4 | from django.views.decorators.http import require_http_methods 5 | from dilidili_dev.models import * 6 | from django.contrib import auth 7 | from dilidili_dev.users import User 8 | 9 | @require_http_methods(["POST"]) 10 | def toggle_user_upload(request, user_id): 11 | if not request.user.is_authenticated() or not request.user.is_admin: 12 | return HttpResponseForbidden() 13 | else: 14 | try: 15 | user = User.objects.get(pk=user_id) 16 | except User.DoesNotExist: 17 | raise Http404("User does not exist") 18 | user.can_upload = not user.can_upload 19 | user.save() 20 | return HttpResponse() 21 | 22 | 23 | @require_http_methods(["POST"]) 24 | def toggle_user_comment(request, user_id): 25 | if not request.user.is_authenticated() or not request.user.is_admin: 26 | return HttpResponseForbidden() 27 | else: 28 | try: 29 | user = User.objects.get(pk=user_id) 30 | except User.DoesNotExist: 31 | raise Http404("User does not exist") 32 | user.can_comment = not user.can_comment 33 | user.save() 34 | return HttpResponse() 35 | 36 | 37 | @require_http_methods(["POST"]) 38 | def toggle_user_bullet(request, user_id): 39 | if not request.user.is_authenticated() or not request.user.is_admin: 40 | return HttpResponseForbidden() 41 | else: 42 | try: 43 | user = User.objects.get(pk=user_id) 44 | except User.DoesNotExist: 45 | raise Http404("User does not exist") 46 | user.can_bullet = not user.can_bullet 47 | user.save() 48 | return HttpResponse() 49 | -------------------------------------------------------------------------------- /dilidili_dev/forms.py: -------------------------------------------------------------------------------- 1 | __author__ = 'Yue Dayu' 2 | from django import forms 3 | from .users import User 4 | 5 | class ImageForm(forms.ModelForm): 6 | class Meta: 7 | model = User 8 | fields = ('image', 'cropping',) 9 | -------------------------------------------------------------------------------- /dilidili_dev/home_view.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from django.http import HttpResponseRedirect, Http404, JsonResponse, HttpResponseForbidden 3 | from django.core.urlresolvers import reverse 4 | from django.views.decorators.http import require_http_methods 5 | from dilidili_dev.models import * 6 | from django.contrib import auth 7 | from dilidili_dev.users import User 8 | 9 | @require_http_methods(["GET"]) 10 | def following(request): 11 | if not request.user.is_authenticated(): 12 | return HttpResponseForbidden() 13 | else: 14 | return render(request, "home/follow-list.html", 15 | context={ 16 | 'follow_set': request.user.follow_users.all(), 17 | 'empty_msg': '你没有关注的人', 18 | }) 19 | 20 | 21 | @require_http_methods(["GET"]) 22 | def follower(request): 23 | if not request.user.is_authenticated(): 24 | return HttpResponseForbidden() 25 | else: 26 | return render(request, "home/follow-list.html", 27 | context={ 28 | 'follow_set': request.user.following_users.all(), 29 | 'empty_msg': '还没有关注你的人', 30 | }) 31 | 32 | @require_http_methods(["GET"]) 33 | def collection(request): 34 | if not request.user.is_authenticated(): 35 | return HttpResponseForbidden() 36 | else: 37 | return render(request, "home/collection-list.html", 38 | context={ 39 | 'video_set': request.user.collection_videos.all().order_by('-time'), 40 | 'empty_msg': '你还没有收藏的视频' 41 | }) 42 | 43 | 44 | @require_http_methods(["GET"]) 45 | def center(request): 46 | if not request.user.is_authenticated(): 47 | return HttpResponseForbidden() 48 | else: 49 | return render(request, "home/main-content.html", 50 | context={ 51 | 'home_video_set': request.user.video_set.all().order_by('-time'), 52 | 'home_video_collection': request.user.collection_videos.all().order_by('-time') 53 | }) 54 | -------------------------------------------------------------------------------- /dilidili_dev/logout_in.py: -------------------------------------------------------------------------------- 1 | __author__ = 'Yue Dayu' 2 | 3 | from django.http import HttpResponseRedirect 4 | from django.contrib import auth 5 | from django.contrib.auth.decorators import login_required 6 | from django.shortcuts import render 7 | 8 | 9 | @login_required 10 | def logout(request): 11 | auth.logout(request) 12 | return HttpResponseRedirect('/') 13 | 14 | 15 | def login(request, error_msg=""): 16 | if request.user.is_authenticated(): 17 | return HttpResponseRedirect("/") 18 | if request.method == 'POST': 19 | username = request.POST.get('username', '') 20 | password = request.POST.get('password', '') 21 | user = auth.authenticate(username=username, password=password) 22 | if user is not None: 23 | # print(dir(user)) 24 | if user.is_active: 25 | auth.login(request, user) 26 | return HttpResponseRedirect('/home/') 27 | else: 28 | return render(request, "registration/login.html", {'error': "该用户已经被禁止登陆", 29 | 'username': username}) 30 | else: 31 | return render(request, "registration/login.html", {'error': "用户名或密码不正确", 32 | 'username': username}) 33 | else: 34 | return render(request, "registration/login.html", context=error_msg or {}) 35 | -------------------------------------------------------------------------------- /dilidili_dev/message.py: -------------------------------------------------------------------------------- 1 | __author__ = 'Yue Dayu' 2 | 3 | from django.shortcuts import render 4 | from django.http import HttpResponseRedirect 5 | from .users import User 6 | from .models import Message 7 | from django.http import Http404, JsonResponse 8 | from django.views.decorators.http import require_http_methods 9 | 10 | 11 | def inbox(request): 12 | if request.user.is_authenticated(): 13 | sendmsg = Message.objects.filter(user_from=request.user).order_by('-time') 14 | receivemsg = Message.objects.filter(user_to=request.user).order_by('-time') 15 | userlist = [] 16 | for x in sendmsg: 17 | userlist.append(x.user_to) 18 | for x in receivemsg: 19 | userlist.append(x.user_from) 20 | userlist = {}.fromkeys(userlist).keys() 21 | res_list = [] 22 | for x in userlist: 23 | temp = { 24 | 'user': x, 25 | 'num': receivemsg.filter(user_from=x, status=False).count() 26 | } 27 | res_list.append(temp) 28 | return render(request, 'message/message.html', {'list': res_list}) 29 | else: 30 | return HttpResponseRedirect('/login/') 31 | 32 | 33 | def sendto(request, user_id): 34 | if request.user.is_authenticated(): 35 | try: 36 | to_user = User.objects.get(id=user_id) 37 | if to_user == request.user: 38 | return HttpResponseRedirect('/inbox/') 39 | if request.method == 'POST': 40 | if request.POST['content'] and request.POST['content'] != "": 41 | m = Message(user_from=request.user, 42 | user_to=to_user, 43 | content=request.POST['content']) 44 | m.save() 45 | return HttpResponseRedirect('/sendto/' + str(user_id)) 46 | sendmsg = Message.objects.filter(user_from=request.user, user_to=to_user).order_by('-time') 47 | receivemsg = Message.objects.filter(user_to=request.user, user_from=to_user).order_by('-time') 48 | for x in receivemsg: 49 | x.status = True 50 | x.save() 51 | msg = sendmsg | receivemsg 52 | except User.DoesNotExist: 53 | raise Http404("User does not exist") 54 | return render(request, 'message/sendto.html', {'to_user': to_user, 55 | 'msg_set': msg}) 56 | else: 57 | return HttpResponseRedirect('/login/') 58 | 59 | 60 | def del_msg(request, user_id, msg_id): 61 | if request.user.is_authenticated(): 62 | try: 63 | msg = Message.objects.get(pk=msg_id) 64 | if msg.user_from == request.user and msg.user_to.id == int(user_id): 65 | msg.delete() 66 | return HttpResponseRedirect('/sendto/' + str(user_id)) 67 | except Message.DoesNotExist: 68 | raise Http404("Message does not exist") 69 | else: 70 | return HttpResponseRedirect('/login/') 71 | 72 | 73 | @require_http_methods(['POST']) 74 | def get_unread_num(request): 75 | if request.user.is_authenticated(): 76 | user = request.user 77 | num = Message.objects.filter(user_to=user, status=False).count() 78 | return JsonResponse(data={'num': num}) 79 | else: 80 | return JsonResponse(data={'num': 0}) 81 | -------------------------------------------------------------------------------- /dilidili_dev/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from dilidili_dev.users import User 3 | from dilidili import settings 4 | import os 5 | 6 | # models 7 | # 视频模型 8 | class Video(models.Model): 9 | name = models.CharField(max_length=100) 10 | video = models.FileField(upload_to='videos') 11 | image = models.ImageField( 12 | upload_to='images', 13 | default=os.path.join('photos', '001.jpg').replace('\\', '/') 14 | ) 15 | describe = models.CharField(max_length=200) 16 | tag = models.CharField(max_length=84, default="", 17 | blank=True) # 标签 18 | category_set = models.ManyToManyField('Category', blank=True) 19 | play = models.IntegerField(default=0) # 播放次数 20 | money = models.IntegerField(default=0) # 硬币数量 21 | owner = models.ForeignKey('User') 22 | time = models.DateTimeField(auto_now=False, auto_now_add=True) # 时间 23 | status = models.IntegerField(default=0) # 视频状态 24 | 25 | def __str__(self): 26 | return self.name 27 | 28 | def get_absolute_url(self): 29 | return '/video/%u' % self.pk 30 | 31 | 32 | # 弹幕 33 | class Bullet(models.Model): 34 | video = models.ForeignKey('Video') 35 | user = models.ForeignKey('User') 36 | time = models.IntegerField(default=0) # 视频的帧数 37 | send_date = models.DateTimeField(auto_now=False, auto_now_add=True) # 发送时间 38 | content = models.CharField(max_length=200) 39 | color = models.CharField(max_length=10) # 颜色 40 | 41 | 42 | # 评论 43 | class Comment(models.Model): 44 | video = models.ForeignKey('Video') 45 | user = models.ForeignKey('User') 46 | content = models.CharField(max_length=400) 47 | time = models.DateTimeField(auto_now=False, auto_now_add=True) 48 | 49 | 50 | # 私信 51 | class Message(models.Model): 52 | user_from = models.ForeignKey('User', related_name="msg_send") 53 | user_to = models.ForeignKey('User', related_name="msg_receive") 54 | content = models.CharField(max_length=400) 55 | status = models.BooleanField(default=False) # 已读未读 56 | time = models.DateTimeField(auto_now=False, auto_now_add=True) # 发送时间 57 | 58 | 59 | # 分类 60 | class Category(models.Model): 61 | name = models.CharField(max_length=40) 62 | 63 | def __str__(self): 64 | return self.name 65 | 66 | def get_absolute_url(self): 67 | return '/category/%u' % self.pk 68 | 69 | 70 | # 专辑 71 | class Album(models.Model): 72 | image = models.ImageField() 73 | money = models.IntegerField(default=0) # 专辑创建以来的硬币数 74 | owner = models.ForeignKey('User') 75 | time = models.DateTimeField(auto_now=False, auto_now_add=True) # 上传时间 76 | name = models.CharField(max_length=40) 77 | describe = models.CharField(max_length=200) 78 | video_list = models.ManyToManyField('Video', through="AlbumVideo") 79 | 80 | 81 | # 视频--专辑关系 82 | class AlbumVideo(models.Model): 83 | album = models.ForeignKey('Album') 84 | video = models.ForeignKey('Video') 85 | video_number = models.IntegerField() # 视频在专辑中的序号 86 | 87 | 88 | # 最佳视频 89 | class BestVideo(models.Model): 90 | date = models.DateTimeField(auto_now=False, auto_now_add=True) 91 | video = models.ForeignKey('Video') 92 | -------------------------------------------------------------------------------- /dilidili_dev/search.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from django.core import serializers 3 | from django.http import HttpResponseRedirect, Http404, JsonResponse, HttpResponseBadRequest, QueryDict 4 | from django.views.decorators.http import require_http_methods 5 | from dilidili_dev.models import * 6 | 7 | 8 | def get_search_objects(request): 9 | data = request.GET.copy() 10 | sortby = data.pop("order_by")[0] if "order_by" in data else "?" 11 | offset = int(data.pop("offset")[0] if "offset" in data else "0") 12 | limitto = int(data.pop("limit_to")[0] if "limit_to" in data else "100") 13 | objects = Video.objects.all().filter(**data.dict()).order_by(sortby)[offset : offset+limitto] 14 | return objects 15 | 16 | # for ajax GET, return JSON 17 | @require_http_methods(["GET"]) 18 | def search(request): 19 | return JsonResponse(serializers.serialize('json', get_search_objects(request)), safe=False) 20 | 21 | 22 | @require_http_methods(["GET"]) 23 | def search_mainpage(request): 24 | return render(request, 'search/search.html', 25 | context = { 'category_set': Category.objects.all(), 'title_contain': request.GET["title_include"] }) 26 | 27 | 28 | @require_http_methods(["GET"]) 29 | def search_html(request): 30 | return render(request, "search/search-result.html", 31 | context = { 'video_set': get_search_objects(request) }) 32 | -------------------------------------------------------------------------------- /dilidili_dev/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /dilidili_dev/upload_photo.py: -------------------------------------------------------------------------------- 1 | __author__ = 'Yue Dayu' 2 | from django.shortcuts import render 3 | from .forms import ImageForm 4 | from django.views.decorators.http import require_http_methods 5 | 6 | 7 | def upload_photo(request): 8 | return render(request, 'forms/upload-photo.html') 9 | 10 | 11 | @require_http_methods(["POST"]) 12 | def process_img(request): 13 | user = request.user 14 | if request.method == "POST": 15 | form = ImageForm(request.POST, request.FILES) 16 | if form.is_valid(): 17 | user.image = form.files['image'] 18 | user.save() 19 | form = ImageForm(instance=user) 20 | return render(request, 'forms/process-photo.html', {'form': form}) 21 | else: 22 | return render(request, 'forms/upload-photo.html', {'error': '请重新上传一张图像。'}) 23 | 24 | 25 | @require_http_methods(["POST"]) 26 | def upload_success(request): 27 | user = request.user 28 | if request.method == "POST": 29 | form = ImageForm(request.POST) 30 | if form.is_valid(): 31 | form = ImageForm(request.POST, instance=user) 32 | form.save() 33 | return render(request, 'forms/upload-success.html') 34 | else: 35 | return render(request, 'forms/upload-photo.html', {'error': '发生错误,请重新上传。'}) 36 | -------------------------------------------------------------------------------- /dilidili_dev/users.py: -------------------------------------------------------------------------------- 1 | __author__ = 'Yue Dayu' 2 | 3 | from django.db import models 4 | from django.contrib.auth.models import BaseUserManager, AbstractBaseUser 5 | import os 6 | from dilidili import settings 7 | from image_cropping.fields import ImageRatioField, ImageCropField 8 | # from dilidili_dev.models import Video 9 | 10 | 11 | class UserManager(BaseUserManager): 12 | def create_user(self, username, email, name, password, image=None, describe=None): 13 | if not username: 14 | raise ValueError('Users must have an username') 15 | 16 | user = self.model( 17 | email=UserManager.normalize_email(email), 18 | username=username, 19 | name=name, 20 | describe=describe, 21 | money=100, 22 | is_admin=False) 23 | if image: 24 | user.image = image 25 | user.is_active = True 26 | user.set_password(password) 27 | user.save(using=self._db) 28 | return user 29 | 30 | def create_superuser(self, username, email, password, name='admin', describe='describe'): 31 | user = self.create_user( 32 | email=email, 33 | username=username, 34 | name=name, 35 | describe=describe, 36 | password=password) 37 | user.is_admin = True 38 | user.save(using=self._db) 39 | return user 40 | 41 | 42 | class User(AbstractBaseUser): 43 | id = models.AutoField(primary_key=True, unique=True) 44 | username = models.CharField(max_length=50, unique=True, db_index=True) 45 | email = models.EmailField(max_length=254, unique=True) 46 | name = models.CharField(max_length=50, db_index=True, unique=True) 47 | image = ImageCropField( 48 | upload_to='photos/', 49 | default=os.path.join('photos', '001.jpg').replace('\\', '/') 50 | ) 51 | cropping = ImageRatioField('image', '200x200', allow_fullsize=True) 52 | describe = models.CharField(max_length=254, db_index=True) 53 | money = models.IntegerField(default=100) 54 | is_active = models.BooleanField(default=True) 55 | is_admin = models.BooleanField(default=False) 56 | # Permissions 57 | can_comment = models.BooleanField(default=True) 58 | can_upload = models.BooleanField(default=True) 59 | can_bullet = models.BooleanField(default=True) 60 | 61 | follow_users = models.ManyToManyField("User", related_name="following_users") 62 | like_videos = models.ManyToManyField("Video", related_name="like_videos") 63 | collection_videos = models.ManyToManyField("Video", related_name="collection_videos") 64 | 65 | objects = UserManager() 66 | 67 | USERNAME_FIELD = 'username' 68 | REQUIRED_FIELDS = ['email'] 69 | 70 | def get_full_name(self): 71 | return self.name 72 | 73 | def get_short_name(self): 74 | return self.name 75 | 76 | @property 77 | def is_staff(self): 78 | return self.is_admin 79 | 80 | def __str__(self): 81 | return self.username 82 | 83 | def has_perm(self, perm, obj=None): 84 | "Does the user have a specific permission?" 85 | # Simplest possible answer: Yes, always 86 | return True 87 | 88 | def has_module_perms(self, app_label): 89 | "Does the user have permissions to view the app `app_label`?" 90 | # Simplest possible answer: Yes, always 91 | return True 92 | 93 | def get_absolute_url(self): 94 | return '/personal/%u' % self.pk 95 | -------------------------------------------------------------------------------- /dilidili_dev/video_play.py: -------------------------------------------------------------------------------- 1 | __author__ = 'Yue Dayu' 2 | 3 | from django.shortcuts import render 4 | from .models import Video 5 | from django.http import Http404, JsonResponse 6 | from django.views.decorators.http import require_http_methods 7 | from .models import Bullet, Comment 8 | from easy_thumbnails.files import get_thumbnailer 9 | 10 | 11 | def video_play(request, video_id): 12 | try: 13 | video = Video.objects.get(pk=video_id) 14 | except Video.DoesNotExist: 15 | raise Http404("Video does not exist") 16 | if (not request.user.is_authenticated() or not request.user.is_admin) and video.status != 0: 17 | return render(request, "video/video-notfound.html") 18 | return render(request, 'video/video.html', {'video': video}) 19 | 20 | 21 | @require_http_methods(['POST']) 22 | def video_bullet_add(request): 23 | if request.user.is_authenticated() and request.user.can_bullet: 24 | try: 25 | video = Video.objects.get(pk=request.POST['id']) 26 | user = request.user 27 | time = request.POST['time'] 28 | content = request.POST['content'] 29 | color = request.POST['color'] 30 | b = Bullet(video=video, 31 | user=user, 32 | time=time, 33 | content=content, 34 | color=color) 35 | b.save() 36 | except Video.DoesNotExist: 37 | return JsonResponse(data={'res': False, 38 | 'error': '发送失败!'}) 39 | return JsonResponse(data={'res': True}) 40 | else: 41 | return JsonResponse(data={'res': False, 42 | 'error': '用户没有权限!'}) 43 | 44 | 45 | @require_http_methods(['POST']) 46 | def video_bullet_get(request): 47 | try: 48 | start = float(request.POST['last']) 49 | video = Video.objects.get(pk=request.POST['id']) 50 | b_set = Bullet.objects.filter(video=video).order_by("-send_date") 51 | new_list = [] 52 | max = start 53 | for x in b_set: 54 | if x.send_date.timestamp() <= start: 55 | break 56 | if x.send_date.timestamp() > max: 57 | max = x.send_date.timestamp() 58 | temp = { 59 | 'content': x.content, 60 | 'color': x.color, 61 | 'send_date': str(x.send_date.year) + "-" + str(x.send_date.month) + "-" + str(x.send_date.day), 62 | 'time': x.time 63 | } 64 | new_list.append(temp) 65 | result = { 66 | 'res': True, 67 | 'list': new_list, 68 | 'max': max 69 | } 70 | return JsonResponse(data=result) 71 | except Video.DoesNotExist: 72 | return JsonResponse(data={'res': False}) 73 | 74 | 75 | @require_http_methods(['POST']) 76 | def video_comment_add(request): 77 | if request.user.is_authenticated() and request.user.can_comment: 78 | try: 79 | video = Video.objects.get(pk=request.POST['id']) 80 | user = request.user 81 | content = request.POST['content'] 82 | c = Comment(video=video, 83 | user=user, 84 | content=content) 85 | c.save() 86 | except Video.DoesNotExist: 87 | return JsonResponse(data={'res': False, 88 | 'error': '发送失败!'}) 89 | return JsonResponse(data={'res': True}) 90 | else: 91 | return JsonResponse(data={'res': False, 92 | 'error': '用户没有权限!'}) 93 | 94 | 95 | @require_http_methods(['POST']) 96 | def get_video_comment(request): 97 | try: 98 | video = Video.objects.get(pk=request.POST['id']) 99 | c_set = Comment.objects.filter(video=video).order_by('-time') 100 | new_list = [] 101 | if not request.user.is_authenticated(): 102 | flag = False 103 | else: 104 | flag = True 105 | for x in c_set: 106 | thumbnail_url = get_thumbnailer(x.user.image).get_thumbnail({ 107 | 'size': (200, 200), 108 | 'box': x.user.cropping, 109 | 'crop': True, 110 | 'detail': True, 111 | }).url 112 | if flag: 113 | if x.user == request.user or request.user.is_admin: 114 | flag = True 115 | else: 116 | flag = False 117 | temp = { 118 | 'user_id': x.user.id, 119 | 'user_name': x.user.name, 120 | 'user_image': thumbnail_url, 121 | 'can_del': flag, 122 | 'comment_id': x.pk, 123 | 'comment_context': x.content, 124 | 'comment_time': 125 | str(x.time.month) + '月' + str(x.time.day) + '日 ' + str(x.time.hour) + ':' + str(x.time.minute) 126 | } 127 | new_list.append(temp) 128 | result = { 129 | 'res': True, 130 | 'list': new_list 131 | } 132 | return JsonResponse(data=result) 133 | except Video.DoesNotExist: 134 | return JsonResponse(data={'res': False}) 135 | 136 | 137 | @require_http_methods(['POST']) 138 | def del_video_comment(request): 139 | comment_id = int(request.POST['id']) 140 | if request.user.is_authenticated(): 141 | try: 142 | comment = Comment.objects.get(pk=comment_id) 143 | if request.user == comment.user or request.user.is_admin: 144 | comment.delete() 145 | return JsonResponse(data={'res': True}) 146 | else: 147 | return JsonResponse(data={'res': False}) 148 | except Comment.DoesNotExist: 149 | return JsonResponse(data={'res': False}) 150 | else: 151 | return JsonResponse(data={'res': False}) 152 | 153 | 154 | @require_http_methods(['POST']) 155 | def set_collection(request): 156 | if request.user.is_authenticated(): 157 | try: 158 | video = Video.objects.get(pk=request.POST['id']) 159 | user = request.user 160 | if video in user.collection_videos.all(): 161 | flag = False 162 | user.collection_videos.remove(video) 163 | else: 164 | flag = True 165 | user.collection_videos.add(video) 166 | return JsonResponse(data={'res': True, 167 | 'flag': flag}) 168 | except Video.DoesNotExist: 169 | return JsonResponse(data={'res': False}) 170 | else: 171 | return JsonResponse(data={'res': False}) 172 | 173 | 174 | @require_http_methods(['POST']) 175 | def set_like(request): 176 | if request.user.is_authenticated(): 177 | try: 178 | video = Video.objects.get(pk=request.POST['id']) 179 | user = request.user 180 | if video in user.like_videos.all(): 181 | flag = False 182 | user.like_videos.remove(video) 183 | else: 184 | flag = True 185 | user.like_videos.add(video) 186 | return JsonResponse(data={'res': True, 187 | 'flag': flag}) 188 | except Video.DoesNotExist: 189 | return JsonResponse(data={'res': False}) 190 | else: 191 | return JsonResponse(data={'res': False}) 192 | 193 | 194 | @require_http_methods(['POST']) 195 | def add_money(request): 196 | if request.user.is_authenticated(): 197 | try: 198 | video = Video.objects.get(pk=request.POST['id']) 199 | user = request.user 200 | if user.money > 0: 201 | user.money -= 1 202 | user.save() 203 | video.money += 1 204 | money = video.money 205 | video.save() 206 | video.owner.money += 1 207 | video.owner.save() 208 | return JsonResponse(data={'res': True, 209 | 'video_money': money}) 210 | else: 211 | return JsonResponse(data={'res': False, 212 | 'error': "硬币不足"}) 213 | except Video.DoesNotExist: 214 | return JsonResponse(data={'res': False, 215 | 'error': "视频不存在"}) 216 | else: 217 | return JsonResponse(data={'res': False, 218 | 'error': "用户未登录"}) 219 | -------------------------------------------------------------------------------- /dilidili_dev/video_upload.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from .models import Video 3 | 4 | 5 | class VideoUploadForm(forms.ModelForm): 6 | class Meta: 7 | model = Video 8 | fields = ['name', 'describe', 'video', 'image', 'tag', 'category_set'] 9 | widgets = { 10 | 'category_set': forms.CheckboxSelectMultiple 11 | } 12 | 13 | -------------------------------------------------------------------------------- /dilidili_dev/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from django.http import HttpResponseRedirect, Http404, JsonResponse, HttpResponseForbidden, HttpResponse 3 | from django.core.urlresolvers import reverse 4 | from django.views.decorators.http import require_http_methods 5 | from dilidili_dev.admin import UserCreationForm 6 | from dilidili_dev.video_upload import VideoUploadForm 7 | from dilidili_dev.models import * 8 | from django.contrib import auth 9 | from dilidili_dev.users import User 10 | 11 | 12 | def register(request): 13 | if request.user.is_authenticated(): 14 | return HttpResponseRedirect("/home/") 15 | if request.method == 'POST': 16 | form = UserCreationForm(request.POST, request.FILES) 17 | if form.is_valid() and request.POST['password1'] and len(request.POST['password1']) >= 6: 18 | form.save() 19 | user = auth.authenticate(username=request.POST['username'], password=request.POST['password1']) 20 | auth.login(request, user) 21 | return HttpResponseRedirect("/home/") 22 | else: 23 | username = request.POST['username'] if request.POST['username'] else "" 24 | password1 = request.POST['password1'] if request.POST['password1'] else "" 25 | password2 = request.POST['password2'] if request.POST['password2'] else "" 26 | name = request.POST['name'] if request.POST['name'] else "" 27 | email = request.POST['email'] if request.POST['email'] else "" 28 | describe = request.POST['describe'] if request.POST['describe'] else "" 29 | error_msg = "错误" 30 | if not username: 31 | error_msg = "请输入用户名" 32 | elif not (password1 and password2): 33 | error_msg = "请输入密码" 34 | elif not name: 35 | error_msg = "请输入昵称" 36 | elif not email: 37 | error_msg = "请输入邮箱" 38 | elif not describe: 39 | error_msg = "请输入个人描述" 40 | elif password1 != password2: 41 | error_msg = "两次密码不一致" 42 | elif len(password1) < 6: 43 | error_msg = "密码长度小于6位" 44 | elif User.objects.filter(username=username): 45 | error_msg = "用户名已经存在" 46 | username = "" 47 | elif User.objects.filter(email=email): 48 | error_msg = "邮箱已经注册" 49 | email = "" 50 | elif User.objects.filter(name=name): 51 | error_msg = "昵称已经被使用" 52 | name = "" 53 | return render(request, "registration/register.html", {'error': error_msg, 54 | 'username': username, 55 | 'name': name, 56 | 'email': email, 57 | 'describe': describe}) 58 | return render(request, "registration/register.html") 59 | 60 | 61 | @require_http_methods(["GET"]) 62 | def index(request): 63 | return render(request, "index/index.html", 64 | context={ 65 | 'popular_video_set': Video.objects.filter(status=0).order_by("-play")[:12], 66 | }) 67 | 68 | 69 | @require_http_methods(["GET"]) 70 | def personal(request, user_id): 71 | try: 72 | user = User.objects.get(pk=user_id) 73 | except User.DoesNotExist: 74 | raise Http404("User does not exist") 75 | return render(request, 'personal/personal.html', {'pageuser': user, 76 | 'video_set': user.video_set.all().filter(status=0).order_by("-time"), 77 | 'collection_set': user.collection_videos.all().filter(status=0).order_by("-time")}) 78 | 79 | 80 | @require_http_methods(["GET"]) 81 | def home(request): 82 | if request.user.is_authenticated(): 83 | return render(request, 'home/home.html', {'home_video_set': request.user.video_set.all().order_by("-time"), 84 | 'home_video_collection': request.user.collection_videos.all().order_by("-time")}) 85 | else: 86 | return render(request, "registration/login.html", {'error': "请登陆"}) 87 | 88 | 89 | @require_http_methods(["GET", "POST"]) 90 | def upload(request): 91 | if request.user.is_authenticated(): 92 | if not request.user.can_upload: 93 | return render(request, 'home/home.html', {'error': "您已被封禁,不能上传视频" }) 94 | 95 | if request.method == 'GET': 96 | return render(request, 'upload/upload.html', {'form': VideoUploadForm(initial={'name': "", 'describe': "", 'tag': ""})}) 97 | else: 98 | form = VideoUploadForm(request.POST, request.FILES) 99 | if form.is_valid(): 100 | video = form.save(commit=False) 101 | video.status = 4 102 | video.owner = request.user 103 | video.save() 104 | form.save_m2m() 105 | return HttpResponseRedirect("/home/") 106 | else: 107 | return render(request, 'upload/upload.html', {'error': form.errors, 'form': form }) 108 | else: 109 | return render(request, "registration/login.html", {'error': "请登陆"}) 110 | 111 | 112 | @require_http_methods(['POST']) 113 | def video_play_add(request): 114 | try: 115 | video = Video.objects.get(pk=request.POST['id']) 116 | video.play += 1 117 | video.save() 118 | except Video.DoesNotExist: 119 | return JsonResponse(data={'res': False}) 120 | return JsonResponse(data={'res': True}) 121 | 122 | 123 | @require_http_methods(["POST"]) 124 | def user_toggle_follow(request, user_id): 125 | if not request.user.is_authenticated() or request.user.pk == user_id: 126 | return HttpResponseForbidden() 127 | try: 128 | user = User.objects.get(pk=user_id) 129 | except User.DoesNotExist: 130 | raise Http404("User not found") 131 | 132 | if user in request.user.follow_users.all(): 133 | request.user.follow_users.remove(user) 134 | else: 135 | request.user.follow_users.add(user) 136 | 137 | return HttpResponse() 138 | 139 | 140 | @require_http_methods(["GET"]) 141 | def category_index(request, category_id): 142 | try: 143 | category = Category.objects.get(pk=category_id) 144 | except Category.DoesNotExist: 145 | raise Http404("Category not found") 146 | 147 | return render(request, "index/index.html", 148 | context={'category': category, 'category_set_ordered': category.video_set.all().order_by('-play')}) 149 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dilidili.settings") 7 | 8 | from django.core.management import execute_from_command_line 9 | 10 | execute_from_command_line(sys.argv) 11 | -------------------------------------------------------------------------------- /media/photos/001.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/media/photos/001.jpg -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ###代码结构说明: 2 | 3 | 目录`dilidili_dev/`: 4 | 5 | `admin.py` 用户注册表单定义,重写的admin 6 | 7 | `logout_in.py` 用户登陆、退出的view 8 | 9 | `users.py` 用户及管理员model 10 | 11 | 目录`templates\`: 模板 12 | 13 | 目录`static\`: 静态文件,包括引用的css, javascript,图片等 14 | 15 | 目录`media\`: 储存上传的文件,包括头像图片、视频 16 | 17 | `dilidili\dbs.py` 数据库设置。由于个人的数据库设置不同,将此文件从`setting.py`分离出。 18 | -------------------------------------------------------------------------------- /static/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /static/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /static/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /static/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /static/images/0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/0.jpg -------------------------------------------------------------------------------- /static/images/2233.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/2233.png -------------------------------------------------------------------------------- /static/images/aa0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/aa0.jpg -------------------------------------------------------------------------------- /static/images/aa1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/aa1.jpg -------------------------------------------------------------------------------- /static/images/aa2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/aa2.jpg -------------------------------------------------------------------------------- /static/images/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/bg.jpg -------------------------------------------------------------------------------- /static/images/dilidili_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/dilidili_logo.png -------------------------------------------------------------------------------- /static/images/dot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/dot.png -------------------------------------------------------------------------------- /static/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/favicon.ico -------------------------------------------------------------------------------- /static/images/hehe.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/hehe.jpg -------------------------------------------------------------------------------- /static/images/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/icons.png -------------------------------------------------------------------------------- /static/images/icons3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/icons3.png -------------------------------------------------------------------------------- /static/images/icons_home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/icons_home.png -------------------------------------------------------------------------------- /static/images/icons_v.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/icons_v.png -------------------------------------------------------------------------------- /static/images/morecomm.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/morecomm.gif -------------------------------------------------------------------------------- /static/images/register_bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/register_bg.jpg -------------------------------------------------------------------------------- /static/images/ui-bg_diagonals-thick_18_b81900_40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/ui-bg_diagonals-thick_18_b81900_40x40.png -------------------------------------------------------------------------------- /static/images/ui-bg_diagonals-thick_20_666666_40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/ui-bg_diagonals-thick_20_666666_40x40.png -------------------------------------------------------------------------------- /static/images/ui-bg_flat_10_000000_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/ui-bg_flat_10_000000_40x100.png -------------------------------------------------------------------------------- /static/images/ui-bg_glass_100_f6f6f6_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/ui-bg_glass_100_f6f6f6_1x400.png -------------------------------------------------------------------------------- /static/images/ui-bg_glass_100_fdf5ce_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/ui-bg_glass_100_fdf5ce_1x400.png -------------------------------------------------------------------------------- /static/images/ui-bg_glass_65_ffffff_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/ui-bg_glass_65_ffffff_1x400.png -------------------------------------------------------------------------------- /static/images/ui-bg_gloss-wave_35_f6a828_500x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/ui-bg_gloss-wave_35_f6a828_500x100.png -------------------------------------------------------------------------------- /static/images/ui-bg_highlight-soft_100_eeeeee_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/ui-bg_highlight-soft_100_eeeeee_1x100.png -------------------------------------------------------------------------------- /static/images/ui-bg_highlight-soft_75_ffe45c_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/ui-bg_highlight-soft_75_ffe45c_1x100.png -------------------------------------------------------------------------------- /static/images/ui-icons_222222_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/ui-icons_222222_256x240.png -------------------------------------------------------------------------------- /static/images/ui-icons_228ef1_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/ui-icons_228ef1_256x240.png -------------------------------------------------------------------------------- /static/images/ui-icons_ef8c08_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/ui-icons_ef8c08_256x240.png -------------------------------------------------------------------------------- /static/images/ui-icons_ffd27a_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/ui-icons_ffd27a_256x240.png -------------------------------------------------------------------------------- /static/images/ui-icons_ffffff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/ui-icons_ffffff_256x240.png -------------------------------------------------------------------------------- /static/images/v-play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/v-play.png -------------------------------------------------------------------------------- /static/images/v_ttl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/images/v_ttl.png -------------------------------------------------------------------------------- /static/scripts/ajax-send.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Yue Dayu on 2015/8/4. 3 | */ 4 | 5 | ;(function () { 6 | $(document).ready(function () { 7 | $.ajaxSetup({ 8 | beforeSend: function (xhr, settings) { 9 | function getCookie(n) { 10 | var cookieValue = null; 11 | if (document.cookie && document.cookie != '') { 12 | var cookies = document.cookie.split(';'); 13 | for (var i = 0; i < cookies.length; i++) { 14 | var cookie = jQuery.trim(cookies[i]); 15 | if (cookie.substring(0, n.length + 1) == (n + '=')) { 16 | cookieValue = decodeURIComponent(cookie.substring(n.length + 1)); 17 | break; 18 | } 19 | } 20 | } 21 | return cookieValue; 22 | } 23 | 24 | if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) { 25 | xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken')); 26 | } 27 | } 28 | }); 29 | }); 30 | })(); 31 | -------------------------------------------------------------------------------- /static/scripts/bullet-send.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Yue Dayu on 2015/8/5. 3 | */ 4 | 5 | ; 6 | (function () { 7 | var send_btn = $('#send-bullet'); 8 | var input = $('#input-bullet'); 9 | var player = videojs('video'); 10 | var video_id = $('#video-id').html(); 11 | 12 | function show_error(msg) { 13 | var error = document.createElement('div'); 14 | error.setAttribute('class', 'alert alert-danger alert-dismissible'); 15 | error.setAttribute('role', 'alert'); 16 | error.innerHTML = " \ 18 | Error!" + msg + ""; 19 | document.getElementById('show-bullet-error').innerHTML = ""; 20 | document.getElementById('show-bullet-error').appendChild(error); 21 | } 22 | 23 | function hexFromRGB(r, g, b) { 24 | var hex = [ 25 | r.toString(16), 26 | g.toString(16), 27 | b.toString(16) 28 | ]; 29 | $.each(hex, function (nr, val) { 30 | if (val.length === 1) { 31 | hex[nr] = "0" + val; 32 | } 33 | }); 34 | return hex.join("").toUpperCase(); 35 | } 36 | 37 | function refreshSwatch() { 38 | var red = $("#red").slider("value"), 39 | green = $("#green").slider("value"), 40 | blue = $("#blue").slider("value"), 41 | hex = hexFromRGB(red, green, blue); 42 | $("#swatch").css("background-color", "#" + hex); 43 | } 44 | 45 | $(function () { 46 | $("#red, #green, #blue").slider({ 47 | orientation: "horizontal", 48 | range: "min", 49 | max: 255, 50 | value: 127, 51 | slide: refreshSwatch, 52 | change: refreshSwatch 53 | }); 54 | $("#red").slider("value", 255); 55 | $("#green").slider("value", 140); 56 | $("#blue").slider("value", 60); 57 | }); 58 | 59 | function check() { 60 | str = input.val(); 61 | if (str == "") { 62 | show_error("请输入内容"); 63 | input.focus(); 64 | return false; 65 | } else if (str.length > 200) { 66 | show_error("输入内容太长"); 67 | input.focus(); 68 | return true; 69 | } 70 | return true; 71 | } 72 | 73 | send_btn.click(function () { 74 | if (check()) { 75 | var red = $("#red").slider("value"), 76 | green = $("#green").slider("value"), 77 | blue = $("#blue").slider("value"), 78 | hex = hexFromRGB(red, green, blue); 79 | $.post('/video-add-bullet/', { 80 | id: video_id, 81 | time: parseInt(player.currentTime() * 1000), 82 | content: input.val(), 83 | color: "#" + hex 84 | }, function(data) { 85 | if (data['res'] == false) { 86 | show_error(data['error']); 87 | } 88 | }); 89 | input.val(""); 90 | } 91 | }); 92 | })(); -------------------------------------------------------------------------------- /static/scripts/comment-send.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YueDayu/dilidili/09fa5bfbd516228465e4083204f46e0570926302/static/scripts/comment-send.js -------------------------------------------------------------------------------- /static/scripts/form-check.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Yue Dayu on 2015/8/4. 3 | */ 4 | function show_error(msg) { 5 | var error = document.createElement('div'); 6 | error.setAttribute('class', 'alert alert-danger alert-dismissible'); 7 | error.setAttribute('role', 'alert'); 8 | error.innerHTML = " \ 10 | Error!" + msg + ""; 11 | document.getElementById('show-error').innerHTML = ""; 12 | document.getElementById('show-error').appendChild(error); 13 | } 14 | 15 | function validate_required(field, alerttxt) { 16 | with (field) { 17 | if (value == null || value == "") { 18 | show_error(alerttxt); 19 | return false 20 | } 21 | else { 22 | return true 23 | } 24 | } 25 | } 26 | 27 | function check_password(field) { 28 | with (field) { 29 | if (value == null || value == "") { 30 | show_error("请填写密码"); 31 | return false; 32 | } else if (value.length < 6) { 33 | show_error("密码长度太短"); 34 | return false; 35 | } 36 | return true; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /static/scripts/home.js: -------------------------------------------------------------------------------- 1 | ;(function () { 2 | window.click_collection = function(event) { 3 | $.get("collection/", function(data) { 4 | var infopanel = $("