-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathmodels.py
More file actions
145 lines (116 loc) · 4.71 KB
/
models.py
File metadata and controls
145 lines (116 loc) · 4.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
"""
Models per docs/Schema.md — cppa_youtube_script_tracker section.
Tables:
- YouTubeChannel: publisher channel (e.g. CppCon, C++Now); channel_id is PK
- YouTubeVideo: individual video metadata + transcript state; video_id is PK
- YouTubeVideoSpeaker: M2M join between YouTubeVideo and cppa_user_tracker.YoutubeSpeaker
- CppaTags: C++ community tag vocabulary
- YouTubeVideoTags: M2M join between YouTubeVideo and CppaTags
"""
from django.db import models
class YouTubeChannel(models.Model):
"""Publishing channel a video was uploaded to (e.g. CppCon, C++Now).
channel_id is the YouTube channel ID and serves as the primary key.
"""
channel_id = models.CharField(max_length=64, primary_key=True)
channel_title = models.CharField(max_length=255, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ["channel_title"]
verbose_name = "YouTube channel"
verbose_name_plural = "YouTube channels"
def __str__(self) -> str:
return self.channel_title or self.channel_id
class YouTubeVideo(models.Model):
"""YouTube video metadata and transcript download state.
video_id is the YouTube video ID and serves as the primary key.
"""
video_id = models.CharField(max_length=32, primary_key=True)
channel = models.ForeignKey(
YouTubeChannel,
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="videos",
db_column="channel_id",
)
title = models.CharField(max_length=512, blank=True)
description = models.TextField(blank=True)
published_at = models.DateTimeField(null=True, blank=True, db_index=True)
duration_seconds = models.IntegerField(default=0)
view_count = models.IntegerField(null=True, blank=True)
like_count = models.IntegerField(null=True, blank=True)
comment_count = models.IntegerField(null=True, blank=True)
search_term = models.CharField(max_length=255, blank=True)
has_transcript = models.BooleanField(default=False)
transcript_path = models.CharField(max_length=1024, blank=True)
scraped_at = models.DateTimeField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ["-published_at"]
verbose_name = "YouTube video"
verbose_name_plural = "YouTube videos"
def __str__(self) -> str:
return self.title or self.video_id
class YouTubeVideoSpeaker(models.Model):
"""M2M join: links a YouTubeVideo to a YoutubeSpeaker profile."""
video = models.ForeignKey(
YouTubeVideo,
on_delete=models.CASCADE,
related_name="video_speakers",
db_column="video_id",
)
speaker = models.ForeignKey(
"cppa_user_tracker.YoutubeSpeaker",
on_delete=models.CASCADE,
related_name="video_appearances",
db_column="speaker_id",
)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
constraints = [
models.UniqueConstraint(
fields=["video", "speaker"], name="unique_video_speaker"
)
]
ordering = ["video", "speaker"]
verbose_name = "YouTube video speaker"
verbose_name_plural = "YouTube video speakers"
def __str__(self) -> str:
return f"video={self.video_id} speaker={self.speaker_id}" # type: ignore[attr-defined]
class CppaTags(models.Model):
"""C++ community tag vocabulary (e.g. 'concurrency', 'templates', 'modules')."""
tag_name = models.CharField(max_length=128, unique=True, db_index=True)
class Meta:
ordering = ["tag_name"]
verbose_name = "CPPA tag"
verbose_name_plural = "CPPA tags"
def __str__(self) -> str:
return self.tag_name
class YouTubeVideoTags(models.Model):
"""M2M join: links a YouTubeVideo to a CppaTags entry."""
youtube_video = models.ForeignKey(
YouTubeVideo,
on_delete=models.CASCADE,
related_name="video_tags",
db_column="youtube_video_id",
)
cppa_tag = models.ForeignKey(
CppaTags,
on_delete=models.CASCADE,
related_name="tagged_videos",
db_column="cppa_tag_id",
)
class Meta:
constraints = [
models.UniqueConstraint(
fields=["youtube_video", "cppa_tag"], name="unique_video_tag"
)
]
ordering = ["youtube_video", "cppa_tag"]
verbose_name = "YouTube video tag"
verbose_name_plural = "YouTube video tags"
def __str__(self) -> str:
return f"video={self.youtube_video_id} tag={self.cppa_tag_id}" # type: ignore[attr-defined]