parent
b09c5c4ad2
commit
59fb4e8c99
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 28 KiB |
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 528 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,6 @@
|
||||
from django.contrib import admin
|
||||
from .models import *
|
||||
|
||||
# Register your models here.)
|
||||
admin.site.register(Classification)
|
||||
admin.site.register(Video)
|
@ -0,0 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class VideoConfig(AppConfig):
|
||||
name = 'video'
|
@ -0,0 +1,12 @@
|
||||
from django import forms
|
||||
from comment.models import Comment
|
||||
|
||||
class CommentForm(forms.ModelForm):
|
||||
content = forms.CharField(error_messages={'required': '不能为空',},
|
||||
widget=forms.Textarea(attrs = {'placeholder': '请输入评论内容' })
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Comment
|
||||
fields = ['content']
|
||||
|
@ -0,0 +1,110 @@
|
||||
import os
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
from django.dispatch import receiver
|
||||
|
||||
|
||||
class VideoQuerySet(models.query.QuerySet):
|
||||
|
||||
def get_count(self):
|
||||
return self.count()
|
||||
|
||||
def get_published_count(self):
|
||||
return self.filter(status=0).count()
|
||||
|
||||
def get_not_published_count(self):
|
||||
return self.filter(status=1).count()
|
||||
|
||||
def get_published_list(self):
|
||||
return self.filter(status=0).order_by('-create_time')
|
||||
|
||||
def get_search_list(self, q):
|
||||
if q:
|
||||
return self.filter(title__contains=q).order_by('-create_time')
|
||||
else:
|
||||
return self.order_by('-create_time')
|
||||
|
||||
def get_recommend_list(self):
|
||||
return self.filter(status=0).order_by('-view_count')[:4]
|
||||
|
||||
|
||||
class Classification(models.Model):
|
||||
list_display = ("title",)
|
||||
title = models.CharField(max_length=100,blank=True, null=True)
|
||||
status = models.BooleanField(default=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
class Meta:
|
||||
db_table = "v_classification"
|
||||
|
||||
class Video(models.Model):
|
||||
STATUS_CHOICES = (
|
||||
('0', '发布中'),
|
||||
('1', '未发布'),
|
||||
)
|
||||
title = models.CharField(max_length=100,blank=True, null=True)
|
||||
desc = models.CharField(max_length=255,blank=True, null=True)
|
||||
classification = models.ForeignKey(Classification, on_delete=models.CASCADE, null=True)
|
||||
file = models.FileField(max_length=255)
|
||||
cover = models.ImageField(upload_to='cover/',blank=True, null=True)
|
||||
status = models.CharField(max_length=1 ,choices=STATUS_CHOICES, blank=True, null=True)
|
||||
view_count = models.IntegerField(default=0, blank=True)
|
||||
liked = models.ManyToManyField(settings.AUTH_USER_MODEL,
|
||||
blank=True, related_name="liked_videos")
|
||||
collected = models.ManyToManyField(settings.AUTH_USER_MODEL,
|
||||
blank=True, related_name="collected_videos")
|
||||
create_time = models.DateTimeField(auto_now_add=True, blank=True, max_length=20)
|
||||
|
||||
objects = VideoQuerySet.as_manager()
|
||||
class Meta:
|
||||
db_table = "v_video"
|
||||
|
||||
def increase_view_count(self):
|
||||
self.view_count += 1
|
||||
self.save(update_fields=['view_count'])
|
||||
|
||||
def switch_like(self, user):
|
||||
if user in self.liked.all():
|
||||
self.liked.remove(user)
|
||||
else:
|
||||
self.liked.add(user)
|
||||
|
||||
def count_likers(self):
|
||||
return self.liked.count()
|
||||
|
||||
def user_liked(self, user):
|
||||
if user in self.liked.all():
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
|
||||
def switch_collect(self, user):
|
||||
if user in self.collected.all():
|
||||
self.collected.remove(user)
|
||||
|
||||
else:
|
||||
self.collected.add(user)
|
||||
|
||||
def count_collecters(self):
|
||||
return self.collected.count()
|
||||
|
||||
def user_collected(self, user):
|
||||
if user in self.collected.all():
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
|
||||
|
||||
@receiver(models.signals.post_delete, sender=Video)
|
||||
def auto_delete_file_on_delete(sender, instance, **kwargs):
|
||||
"""
|
||||
删除FileField文件
|
||||
"""
|
||||
if instance.file:
|
||||
if os.path.isfile(instance.file.path):
|
||||
os.remove(instance.file.path)
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,41 @@
|
||||
from datetime import date, datetime
|
||||
from django.utils.timezone import is_aware, utc
|
||||
|
||||
from django import template
|
||||
register = template.Library()
|
||||
|
||||
@register.filter
|
||||
def time_since(value, default="刚刚"):
|
||||
if not isinstance(value, date): # datetime is a subclass of date
|
||||
return value
|
||||
now = datetime.now(utc if is_aware(value) else None)
|
||||
diff = now - value
|
||||
periods = (
|
||||
(diff.days / 365, "年"),
|
||||
(diff.days / 30, "个月"),
|
||||
(diff.days / 7, "周"),
|
||||
(diff.days, "天"),
|
||||
(diff.seconds / 3600, "小时"),
|
||||
(diff.seconds / 60, "分钟"),
|
||||
(diff.seconds, "秒"),
|
||||
)
|
||||
for period, singular in periods:
|
||||
if int(period) > 0:
|
||||
return "%d%s前" % (period, singular)
|
||||
return default
|
||||
|
||||
@register.simple_tag
|
||||
def user_liked_class(video, user):
|
||||
liked = video.user_liked(user)
|
||||
if liked == 0:
|
||||
return "red"
|
||||
else:
|
||||
return "grey"
|
||||
|
||||
@register.simple_tag
|
||||
def user_collected_class(video, user):
|
||||
collected = video.user_collected(user)
|
||||
if collected == 0:
|
||||
return "red"
|
||||
else:
|
||||
return "grey"
|
@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
@ -0,0 +1,11 @@
|
||||
from django.urls import path
|
||||
from . import views
|
||||
|
||||
app_name = 'video'
|
||||
urlpatterns = [
|
||||
path('index', views.IndexView.as_view(), name='index'),
|
||||
path('search/', views.SearchListView.as_view(), name='search'),
|
||||
path('detail/<int:pk>/', views.VideoDetailView.as_view(), name='detail'),
|
||||
path('like/', views.like, name='like'),
|
||||
path('collect/', views.collect, name='collect'),
|
||||
]
|
@ -0,0 +1,100 @@
|
||||
from django.http import JsonResponse
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.views import generic
|
||||
from django.views.decorators.http import require_http_methods
|
||||
|
||||
from helpers import get_page_list, ajax_required
|
||||
from .forms import CommentForm
|
||||
from .models import Video, Classification
|
||||
|
||||
|
||||
class IndexView(generic.ListView):
|
||||
model = Video
|
||||
template_name = 'video/index.html'
|
||||
context_object_name = 'video_list'
|
||||
paginate_by = 12
|
||||
c = None
|
||||
|
||||
def get_context_data(self, *, object_list=None, **kwargs):
|
||||
context = super(IndexView, self).get_context_data(**kwargs)
|
||||
paginator = context.get('paginator')
|
||||
page = context.get('page_obj')
|
||||
page_list = get_page_list(paginator, page)
|
||||
classification_list = Classification.objects.filter(status=True).values()
|
||||
context['c'] = self.c
|
||||
context['classification_list'] = classification_list
|
||||
context['page_list'] = page_list
|
||||
return context
|
||||
|
||||
def get_queryset(self):
|
||||
self.c = self.request.GET.get("c", None)
|
||||
if self.c:
|
||||
classification = get_object_or_404(Classification, pk=self.c)
|
||||
return classification.video_set.all().order_by('-create_time')
|
||||
else:
|
||||
return Video.objects.filter(status=0).order_by('-create_time')
|
||||
|
||||
|
||||
class SearchListView(generic.ListView):
|
||||
model = Video
|
||||
template_name = 'video/search.html'
|
||||
context_object_name = 'video_list'
|
||||
paginate_by = 8
|
||||
q = ''
|
||||
|
||||
def get_queryset(self):
|
||||
self.q = self.request.GET.get("q", "")
|
||||
return Video.objects.filter(title__contains=self.q).filter(status=0)
|
||||
|
||||
def get_context_data(self, *, object_list=None, **kwargs):
|
||||
context = super(SearchListView, self).get_context_data(**kwargs)
|
||||
paginator = context.get('paginator')
|
||||
page = context.get('page_obj')
|
||||
page_list = get_page_list(paginator, page)
|
||||
context['page_list'] = page_list
|
||||
context['q'] = self.q
|
||||
return context
|
||||
|
||||
|
||||
class VideoDetailView(generic.DetailView):
|
||||
model = Video
|
||||
template_name = 'video/detail.html'
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
obj = super().get_object()
|
||||
obj.increase_view_count()
|
||||
return obj
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(VideoDetailView, self).get_context_data(**kwargs)
|
||||
form = CommentForm()
|
||||
recommend_list = Video.objects.get_recommend_list()
|
||||
context['form'] = form
|
||||
context['recommend_list'] = recommend_list
|
||||
return context
|
||||
|
||||
@ajax_required
|
||||
@require_http_methods(["POST"])
|
||||
def like(request):
|
||||
if not request.user.is_authenticated:
|
||||
return JsonResponse({"code": 1, "msg": "请先登录"})
|
||||
video_id = request.POST['video_id']
|
||||
video = Video.objects.get(pk=video_id)
|
||||
user = request.user
|
||||
video.switch_like(user)
|
||||
return JsonResponse({"code": 0, "likes": video.count_likers(), "user_liked": video.user_liked(user)})
|
||||
|
||||
|
||||
@ajax_required
|
||||
@require_http_methods(["POST"])
|
||||
def collect(request):
|
||||
if not request.user.is_authenticated:
|
||||
return JsonResponse({"code": 1, "msg": "请先登录"})
|
||||
video_id = request.POST['video_id']
|
||||
video = Video.objects.get(pk=video_id)
|
||||
user = request.user
|
||||
video.switch_collect(user)
|
||||
return JsonResponse({"code": 0, "collects": video.count_collecters(), "user_collected": video.user_collected(user)})
|
||||
|
||||
|
||||
|
@ -1 +0,0 @@
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,7 +1,6 @@
|
||||
from django.contrib import admin
|
||||
from .models import *
|
||||
|
||||
|
||||
# Register your models here.)
|
||||
admin.site.register(Classification)
|
||||
admin.site.register(Video)
|
||||
|
@ -1,6 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
|
||||
class VideoConfig(AppConfig):
|
||||
name = 'video'
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in new issue