class AuthorizedUpload(models.Model): folder = models.ForeignKey(Folder, on_delete=models.CASCADE, related_name='authorized_uploads') creator = models.ForeignKey(User, on_delete=models.CASCADE, related_name='authorized_uploads', editable=False) created = CreationDateTimeField() @property def expires(self): return self.created + timedelta( days=settings.DKC_AUTHORIZED_UPLOAD_EXPIRATION_DAYS) @property def signature(self): return signing.dumps({'scope': 'authorized_upload', 'id': self.id}) def verify_signature(self, signature: str) -> None: """Verify the signature associated with this instance. Raises `BadSignature` if message tampering occurred, or if the scope of the signed message does not match this feature, or if the signed ID does not match the ID of this instance. """ signed_obj = signing.loads(signature) if signed_obj.get('scope') != 'authorized_upload': raise signing.BadSignature('Invalid signed scope.') if signed_obj.get('id') != self.id: raise signing.BadSignature('Invalid signed ID.')
class Idea(Model): name = CharField(max_length=100, verbose_name=_('Name')) slug = AutoSlugField(populate_from='name', verbose_name=_('Slug')) created_at = CreationDateTimeField(verbose_name=_('Date Created')) modified_at = ModificationDateTimeField( verbose_name=_('Date Modified')) description = TextField(max_length=300, verbose_name=_('Description')) is_public = BooleanField(default=False, verbose_name=_('Is Public')) is_published = BooleanField(default=False, verbose_name=_('Pusblish Now')) views = PositiveIntegerField(default=0, verbose_name=_('Amount of Views')) # relations # license = ForeignKey(to=License, related_name='ideas', verbose_name=_('Licenses')) # patent = ForeignKey(to=Patent, related_name='ideas', verbose_name=_('Patents')) user = ForeignKey(to=User, related_name='ideas', verbose_name=_('Author')) categories = ManyToManyField(to=Category, related_name='ideas', verbose_name=_('Category')) class Meta: db_table = 'idea' verbose_name = _('Idea') verbose_name_plural = _('Ideas') def __unicode__(self): return u"%s" % self.name
class Article(models.Model): """ 文章内容 """ from apps.resource.models import Resource title = models.CharField(verbose_name='标题', max_length=256, db_index=True) url = models.URLField(verbose_name='原始地址', max_length=256) content = models.TextField(verbose_name='文章内容', blank=True) pub_time = models.DateTimeField(verbose_name='发布时间', default=timezone.now) category = models.ForeignKey(to=ArticleCategory, verbose_name='分类', on_delete=models.SET_NULL, blank=True, null=True) tag = models.ManyToManyField(to=ArticleTag, verbose_name='标签', blank=True) source = models.ForeignKey(to=Resource, verbose_name='订阅源', on_delete=models.CASCADE) hash = models.CharField(verbose_name='文章哈希', max_length=512, default='', db_index=True) created = CreationDateTimeField(verbose_name='创建时间') updated = ModificationDateTimeField(verbose_name='更新时间') def __str__(self): return self.title class Meta: verbose_name = '文章' verbose_name_plural = verbose_name unique_together = ('title', 'hash')
class UploadBatch(models.Model): class Meta: verbose_name = 'upload batch' verbose_name_plural = 'upload batches' dataset = models.ForeignKey(Dataset, on_delete=models.CASCADE, related_name='upload_batches') created = CreationDateTimeField() @property def is_complete(self) -> bool: return self.pending_uploads.count() == 0
class ArticleTag(models.Model): """ 文章标签 """ name = models.CharField(verbose_name='标签', max_length=64) created = CreationDateTimeField(verbose_name='创建时间') updated = ModificationDateTimeField(verbose_name='更新时间') class Meta: verbose_name = '文章标签' verbose_name_plural = verbose_name def __str__(self): return self.name
class ResourceCategory(models.Model): """ 订阅源分类 """ name = models.CharField(verbose_name='分类名称', max_length=64) description = models.TextField(verbose_name='描述', default='暂无') created = CreationDateTimeField(verbose_name='创建时间') updated = ModificationDateTimeField(verbose_name='更新时间') def __str__(self): return self.name class Meta: verbose_name = '订阅源分类' verbose_name_plural = verbose_name
class Proxy(models.Model): """ 代理 """ name = models.CharField(verbose_name='名称', max_length=128) addr = models.CharField(verbose_name='地址', max_length=128, unique=True) created = CreationDateTimeField(verbose_name='创建时间') updated = ModificationDateTimeField(verbose_name='更新时间') def __str__(self): return self.addr class Meta: verbose_name = '代理' verbose_name_plural = verbose_name
class ArticleCategory(models.Model): """ 文章分类 """ name = models.CharField(verbose_name='分类', max_length=64) is_default = models.BooleanField(verbose_name='是否默认分类', default=False) created = CreationDateTimeField(verbose_name='创建时间') updated = ModificationDateTimeField(verbose_name='更新时间') class Meta: verbose_name = '文章分类' verbose_name_plural = verbose_name def __str__(self): return self.name
class TranscriptionApproval(models.Model): """ A record of a user indicating we are allowed to transcribe the podcast. """ APPROVAL_TYPE_CHOICES = [ ('user', 'User'), ('staff', 'Staff'), ('owner', 'Owner'), ] podcast = models.ForeignKey('Podcast', related_name='approvals') created = CreationDateTimeField() user = models.ForeignKey('auth.User', blank=True, null=True) approval_type = models.CharField( max_length=5, choices=APPROVAL_TYPE_CHOICES) # TODO: rename to 'type' notes = models.TextField(blank=True, null=True)
class SpiderEvent(models.Model): """ 爬虫事件 """ MESSAGE_LEVEL_CHOICE = ((0, 'DEBUG'), (1, 'INFO'), (2, 'WARNING'), (3, 'ERROR'), (4, 'CRITICAL')) spider = models.ForeignKey(Spider, on_delete=models.CASCADE, verbose_name='爬虫') message = models.TextField(verbose_name='事件信息', default='') level = models.IntegerField(verbose_name='事件等级', choices=MESSAGE_LEVEL_CHOICE) created = CreationDateTimeField(verbose_name='创建时间') updated = ModificationDateTimeField(verbose_name='更新时间') class Meta: verbose_name = '爬虫事件' verbose_name_plural = verbose_name
class RssFetch(models.Model): """A fetch of the RSS feed of a podcast. @startuml [*] --> not_fetched not_fetched --> fetching fetching --> fetched fetching --> failed not_fetched --> fetched fetched --> [*] failed --> [*] @enduml """ podcast = models.ForeignKey(Podcast, related_name='fetches') created = CreationDateTimeField() fetched = models.DateTimeField(blank=True, null=True) body = models.BinaryField(blank=True, null=True) state = FSMField(default='not_fetched', protected=True) @transition(state, 'not_fetched', 'fetched', save=True) def load_rss(self, body=None, filename=None): if body is not None: self.body = body elif filename is not None: with open(filename, 'rb') as f: self.body = f.read() else: raise TypeError('Specify either `body` or `filename`.') self.fetched = datetime_now() @transition(state, 'not_fetched', 'fetching', save=True) def start(self): self.fetched = datetime_now() @transition(state, 'fetching', 'fetched', save=True) def finish(self, body): self.body = body @transition(state, 'fetching', 'failed', save=True) def fail(self): pass
class Spider(models.Model): """ 爬虫 """ name = models.CharField(verbose_name='名称', max_length=128) description = models.TextField(verbose_name='描述', default='暂无') filename = models.CharField(verbose_name='文件名', max_length=256) author = models.CharField(verbose_name='作者', max_length=32) is_enabled = models.BooleanField(verbose_name='是否启用', default=True) is_default = models.BooleanField(verbose_name='是否默认', default=False) created = CreationDateTimeField(verbose_name='创建时间') updated = ModificationDateTimeField(verbose_name='更新时间') def __str__(self): return self.name class Meta: verbose_name = '爬虫' verbose_name_plural = verbose_name
class Authorization(models.Model): """ 认证 """ AUTH_TYPE_CHOICES = ((0, '账号'), (1, 'Cookie'), (2, '请求头')) name = models.CharField(verbose_name='认证名称', max_length=64) type = models.PositiveSmallIntegerField(verbose_name='认证类型', choices=AUTH_TYPE_CHOICES, default=0) username = models.CharField(verbose_name='账号', max_length=128, default='', blank=True) password = models.CharField(verbose_name='密码', max_length=128, default='', blank=True) cookie = models.CharField(verbose_name='Cookie', max_length=512, default='', blank=True) auth_header = models.CharField(verbose_name='认证请求头', max_length=128, default='', blank=True) auth_value = models.CharField(verbose_name='认证Token', max_length=128, default='', blank=True) created = CreationDateTimeField(verbose_name='创建时间') updated = ModificationDateTimeField(verbose_name='更新时间') def __str__(self): return self.name class Meta: verbose_name = '认证' verbose_name_plural = verbose_name
class Note(models.Model): campaign = models.ForeignKey( blank=False, db_index=True, null=False, on_delete=models.CASCADE, related_name="notes", to="campaign.Campaign", verbose_name=_("campaign"), ) topic = models.CharField( db_index=True, blank=False, null=False, max_length=TOPIC_MAX_LENGTH, verbose_name=_("topic"), ) json = JSONField( blank=True, null=True, verbose_name=_("json"), ) text = models.TextField( blank=True, null=True, verbose_name=_("text"), ) created_on = CreationDateTimeField( db_index=True, editable=False, verbose_name=_("created_on"), )
class Resource(models.Model): """ 订阅源 """ from apps.spider.models import Spider from apps.article.models import ArticleCategory, ArticleTag # 刷新状态 REFRESH_STATUS_CHOICES = enums.ResourceRefreshStatus.choices() RESOURCE_LEVEL_CHOICES = ( (0, '公开'), (1, '个人'), (2, '保密'), (3, '绝密'), ) name = models.CharField(verbose_name='名称', max_length=128) link = models.URLField(verbose_name='链接', max_length=512) description = models.TextField(verbose_name='描述', default='暂无') author = models.CharField(verbose_name='作者', max_length=64, default='Admin') spider_type = models.ForeignKey(to=Spider, verbose_name='爬虫类型', on_delete=models.SET_NULL, blank=True, null=True) refresh_gap = models.PositiveSmallIntegerField(verbose_name='刷新间隔', default=60) # 单位 小时 refresh_status = models.PositiveSmallIntegerField( verbose_name='刷新状态', choices=REFRESH_STATUS_CHOICES) last_refresh_time = models.DateTimeField(verbose_name='上次刷新时间') auth = models.ForeignKey(to=Authorization, verbose_name='认证', on_delete=models.SET_NULL, blank=True, null=True) proxy = models.ForeignKey(to=Proxy, verbose_name='代理', on_delete=models.SET_NULL, blank=True, null=True) category = models.ForeignKey(to=ResourceCategory, verbose_name='分类', on_delete=models.SET_NULL, blank=True, null=True) default_category = models.ForeignKey(ArticleCategory, verbose_name='文章默认分类', on_delete=models.SET_NULL, blank=True, null=True) default_tag = models.ForeignKey(ArticleTag, verbose_name='文章默认标签', on_delete=models.SET_NULL, blank=True, null=True) level = models.PositiveSmallIntegerField(verbose_name='等级', choices=RESOURCE_LEVEL_CHOICES) is_enabled = models.BooleanField(verbose_name='是否开启', default=True) created = CreationDateTimeField(verbose_name='创建时间') updated = ModificationDateTimeField(verbose_name='更新时间') def __str__(self): return self.name class Meta: verbose_name = '订阅源' verbose_name_plural = verbose_name