Skip to content

Commit

Permalink
Merge pull request #178 from weaverse-techtide/yujeong/materials
Browse files Browse the repository at this point in the history
Yujeong/materials 앱
  • Loading branch information
AlbertImKr authored Oct 14, 2024
2 parents b165e7c + 144ecaf commit b971da9
Show file tree
Hide file tree
Showing 5 changed files with 551 additions and 231 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Generated by Django 5.1.1 on 2024-10-14 05:25

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('materials', '0007_alter_image_author'),
]

operations = [
migrations.AlterModelOptions(
name='image',
options={'ordering': ['-created_at']},
),
migrations.AlterModelOptions(
name='video',
options={'ordering': ['-created_at']},
),
migrations.AlterModelOptions(
name='videoeventdata',
options={'ordering': ['-timestamp']},
),
migrations.AddField(
model_name='image',
name='is_deleted',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='video',
name='is_deleted',
field=models.BooleanField(default=False),
),
migrations.AlterField(
model_name='image',
name='image_url',
field=models.ImageField(blank=True, null=True, upload_to='images/', verbose_name='이미지 파일'),
),
migrations.AlterField(
model_name='video',
name='video_url',
field=models.FileField(blank=True, null=True, upload_to='videos/', verbose_name='비디오 파일'),
),
migrations.AlterField(
model_name='videoeventdata',
name='duration',
field=models.FloatField(verbose_name='동영상 전체 길이'),
),
migrations.AlterField(
model_name='videoeventdata',
name='video',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='video_event_datas', to='materials.video', verbose_name='시청 기록의 해당 동영상'),
),
]
82 changes: 56 additions & 26 deletions materials/models.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,15 @@
import uuid

from django.db import models

from accounts.models import CustomUser
from courses.models import Course, Topic


def upload_to(instance, filename):
"""
ImageField를 통해 파일이 업로드될 때 해당 파일의 저장 경로를 동적으로 생성합니다.
- 모델 인스턴스가 save() 호출될 때, 파일이 저장되기 전 upload_to에 정의된 경로를 생성하기 위해 호출됩니다.
- ImageField의 upload_to 인자로 전달됩니다.
- 생성된 경로를 반환하며, 이 경로는 Django가 해당 파일을 저장할 때 사용됩니다.
- (장점) 사용자 접근성을 높이면서 중복 파일 이름 문제를 해결합니다.
"""
ext = filename.split(".")[-1]
return f"images/{uuid.uuid4()}.{ext}"
from django.conf import settings
from django.db import models


class Image(models.Model):
"""
이미지 객체를 위해 작성된 모델입니다.
- 관계: Course(1:1), CustomUser(1:1), CustomUser(1:N)를 갖습니다.
- 삭제: 소프트 삭제를 위해 불린 필드를 갖습니다.
- 생성: 지정한 이미지 파일이 없다면 디폴트 값으로 저장됩니다.
"""

course = models.OneToOneField(
Expand All @@ -45,10 +34,17 @@ class Image(models.Model):
null=True,
blank=True,
)
image_url = models.URLField(verbose_name="이미지 파일")

image_url = models.ImageField(
upload_to="images/", blank=True, null=True, verbose_name="이미지 파일"
)
is_deleted = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

class Meta:
ordering = ["-created_at"]

def __str__(self):
if self.user:
return f"{self.user}'s Image"
Expand All @@ -59,28 +55,59 @@ def __str__(self):
def save(self, *args, **kwargs):

if self.user and not self.image_url:
self.image_url = "images/default_user_image.jpg"
self.image_url = f"{settings.MEDIA_URL}images/default_user_image.jpg"
if self.course and not self.image_url:
self.image_url = "images/default_course_image.jpg"
self.image_url = f"{settings.MEDIA_URL}images/default_user_image.jpg"
super().save(*args, **kwargs)


class Video(models.Model):
"""
동영상 객체를 위해 작성된 모델입니다.
- 관계: Topic(1:1), Course(1:1)를 갖습니다.
- 삭제: 소프트 삭제를 위해 불린 필드를 갖습니다.
- 생성: 지정한 이미지 파일이 없다면 디폴트 값으로 저장됩니다.
"""

topic = models.OneToOneField(
Topic, on_delete=models.CASCADE, related_name="video", null=True, blank=True
)
course = models.OneToOneField(
Course, on_delete=models.CASCADE, related_name="video", null=True, blank=True
)
video_url = models.URLField(verbose_name="비디오 파일")
video_url = models.FileField(
upload_to="videos/", blank=True, null=True, verbose_name="비디오 파일"
)
is_deleted = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

class Meta:
ordering = ["-created_at"]

def __str__(self):
return f"{self.id}"
if self.topic:
return f"{self.topic}'s Video"
elif self.course:
return f"Course Video for {self.course}"
return "Video"

def save(self, *args, **kwargs):
if not self.video_url:
self.video_url = f"{settings.MEDIA_URL}videos/default_video.mp4"

super().save(*args, **kwargs)


class VideoEventData(models.Model):
"""
특정 사용자에 대한 동영상 이벤트 객체를 위해 작성된 모델입니다.
- 관계: Course(1:1), CustomUser(1:1), CustomUser(1:N)를 갖습니다.
- 삭제: 소프트 삭제를 위해 불린 필드를 갖습니다.
- 생성: 지정한 이미지 파일이 없다면 디폴트 값으로 저장됩니다.
- 변환: 동영상 전체 길이와 현재 재생 시점을 분과 초로 변환합니다.
"""

EVENT_CHOICES = [
("pause", "Paused"),
("ended", "Ended"),
Expand All @@ -98,27 +125,30 @@ class VideoEventData(models.Model):
Video,
on_delete=models.CASCADE,
related_name="video_event_datas",
verbose_name="시청 기록의 해당 비디오",
verbose_name="시청 기록의 해당 동영상",
)

event_type = models.CharField(
max_length=20, choices=EVENT_CHOICES, verbose_name="이벤트 유형"
)
duration = models.FloatField(verbose_name="비디오 전체 길이") # 초 단위로 저장
current_time = models.FloatField(verbose_name="현재 재생 위치") # 초 단위로 저장
duration = models.FloatField(verbose_name="동영상 전체 길이")
current_time = models.FloatField(verbose_name="현재 재생 위치")
timestamp = models.DateTimeField(auto_now_add=True, verbose_name="이벤트 발생 시간")

class Meta:
ordering = ["-timestamp"]

def get_duration_in_minutes(self):
"""
분과 초로 변환된 영상 재생 시간을 반환합니다.
분과 초로 변환된 동영상 전체 재생 시간을 반환합니다.
"""
minutes = int(self.duration // 60)
seconds = int(self.duration % 60)
return f"{minutes}{seconds}초"

def get_current_time_in_minutes(self):
"""
분과 초로 변환된 현재 재생 시간을 반환합니다.
분과 초로 변환된 동영상 현재 재생 시점을 반환합니다.
"""
minutes = int(self.current_time // 60)
seconds = int(self.current_time % 60)
Expand Down
Loading

0 comments on commit b971da9

Please sign in to comment.