class Option(models.TimestampModel, models.I18NModel, models.OrderedModel): key = models.CharField( max_length=255, db_index=True, verbose_name=_('key'), ) required = models.BooleanField( default=False, verbose_name=_('required'), ) default = models.BooleanField( default=False, verbose_name=_('default value'), ) label = models.TextField(verbose_name=_('label'), ) description = models.TextField( null=True, blank=True, verbose_name=_('description'), ) error_message = models.TextField( blank=True, default='', verbose_name=_('error message'), ) class Meta: ordering = ('ordering', ) unique_together = ('ordering', 'key') verbose_name = _('option') verbose_name_plural = _('options') def __str__(self): return self.key
class Email(models.TimestampModel): from_email = models.StringField(default=_get_default_from_email, verbose_name=_("from email")) to_emails = models.StringField(blank=True, verbose_name=_("to emails")) cc_emails = models.StringField(blank=True, verbose_name=_("cc emails")) bcc_emails = models.StringField(blank=True, verbose_name=_("bcc emails")) all_recipients = models.TextField(blank=True, verbose_name=_("recipients")) headers = models.TextField(blank=True, verbose_name=_("headers")) subject = models.StringField(verbose_name=_("subject")) body = models.TextField(verbose_name=_("body")) raw = models.TextField(blank=True, verbose_name=_("raw message")) class Meta: verbose_name = _("email") verbose_name_plural = _("emails") def __str__(self): return _( 'Email from "%(from_email)s" to "%(to_emails)s" sent at %(sent_at)s about "%(subject)s"' ) % { "from_email": self.from_email, "to_emails": self.to_emails, "sent_at": self.created_at, "subject": self.subject, } @property def attachment_count(self): if not hasattr(self, "attachment_count_cache"): self.attachment_count_cache = self.attachments.count() return self.attachment_count_cache
class OptionTranslation(models.TranslationModel): parent = models.ForeignKey( Option, db_index=True, on_delete=models.CASCADE, related_name='translations', verbose_name=_('option'), ) label = models.TextField(verbose_name=_('label'), ) description = models.TextField( null=True, blank=True, verbose_name=_('description'), ) error_message = models.TextField( blank=True, default='', verbose_name=_('error message'), ) class Meta: unique_together = ('parent', 'language') verbose_name = _('translation') verbose_name_plural = _('translations') def __str__(self): return "%s %s translation" % (self.language, self.parent)
class TermsOfServiceTranslation(models.TranslationModel): parent = models.ForeignKey( TermsOfService, db_index=True, on_delete=models.CASCADE, related_name='translations', verbose_name=_('TermsOfService'), ) label = models.TextField( blank=True, default='', verbose_name=_('label'), ) title = models.CharField( max_length=255, blank=True, default='', verbose_name=_('legal title'), help_text=_('legal tos title'), ) text = models.TextField( blank=True, default='', verbose_name=_('legal text'), help_text=_('legal tos text'), ) human_title = models.CharField( max_length=255, blank=True, default='', verbose_name=_('human title'), help_text=_('human readable tos title'), ) human_text = models.TextField( blank=True, default='', verbose_name=_('human text'), help_text=_('human readable tos text'), ) changelog = models.TextField( blank=True, default='', verbose_name=_('changelog'), help_text=_('difference(s) from previous version'), ) class Meta: unique_together = (('language', 'parent'), ('human_title', 'human_text')) verbose_name = _('TermsOfService Translation') verbose_name_plural = _('TermsOfService Translations') def __str__(self): return self.title
class PostModelTranslation(models.TranslationModel): title = models.StringField(blank=True, verbose_name=_("Title")) slug = models.SlugField(blank=True, verbose_name=_("Slug field")) abstract = models.TextField(verbose_name=_("Abstract"), blank=True, help_text=_("A brief description")) text = models.TextField(blank=True, verbose_name=_("Body")) class Meta: abstract = True def save(self, *args, **kwargs): self.slug = slugify(self.title) super().save(*args, **kwargs)
class EmailTemplateTranslation(models.TranslationModel): parent = models.ForeignKey( EmailTemplate, on_delete=models.CASCADE, related_name="translations", verbose_name=_("parent"), ) subject = models.StringField(verbose_name=_("subject")) body = models.TextField(verbose_name=_("body")) body_html = models.TextField(blank=True, verbose_name=_("body")) class Meta: unique_together = [("language", "parent")] verbose_name = _("mail translation") verbose_name_plural = _("mail translations") def __str__(self): return "%(name)s [%(lang)s]" % { "name": self.parent.name, "lang": self.language[:2], }
class Campaign(models.TimestampModel): name = models.CharField( max_length=255, unique=True, verbose_name=_("Name"), ) description = models.TextField( blank=True, verbose_name=_("Description"), ) class Meta: ordering = ["name"] verbose_name = _("Campaign") verbose_name_plural = _("Campaigns") def __str__(self): return self.name
class EmailTemplate(models.TimestampModel, models.I18NModel): objects = EmailTemplateManager() from_email = models.StringField(default=_get_default_from_email, verbose_name=_("from email")) default_to = models.StringField( blank=True, verbose_name=_("default to"), help_text=_("comma separated value"), ) default_cc = models.StringField( blank=True, verbose_name=_("default cc"), help_text=_("comma separated value"), ) default_bcc = models.StringField( blank=True, verbose_name=_("default bcc"), help_text=_("comma separated value"), ) default_reply_to = models.StringField( blank=True, verbose_name=_("default reply_to"), help_text=_("comma separated value"), ) name = models.StringField(unique=True, db_index=True, verbose_name=_("name")) subject = models.StringField(verbose_name=_("subject")) body = models.TextField(verbose_name=_("body")) body_html = models.TextField(blank=True, verbose_name=_("html body")) noreply = models.BooleanField( default=False, verbose_name=_("no reply"), help_text=_("should add a Reply-to with noreply@domain header"), ) notes = models.TextField(blank=True, verbose_name=_("notes")) class Meta: ordering = ["name"] verbose_name = _("email template") verbose_name_plural = _("email templates") def __str__(self): return self.name def create( self, request=None, from_email=None, to=None, cc=None, bcc=None, reply_to=None, context=None, attachments=None, alternatives=None, fail_silently=True, auth_user=None, auth_password=None, connection=None, headers=None, noreply=False, language=None, subject=None, body=None, ): # NOQA site = Site.objects.get_current() subject_template = Template( self.translate( language=language).subject if subject is None else subject) body_template = Template( self.translate(language=language).body if body is None else body) context = {} if context is None else context context = Context(context) if request is None else RequestContext( request, context) connection = connection or get_connection( username=auth_user, password=auth_password, fail_silently=fail_silently, ) if isinstance(to, str): to = [to] elif self.default_to: to = self.default_to.split(",") if isinstance(cc, str): cc = [cc] elif self.default_cc: cc = self.default_cc.split(",") if isinstance(bcc, str): bcc = [bcc] elif self.default_bcc: bcc = self.default_bcc.split(",") if isinstance(reply_to, str): reply_to = [reply_to] elif self.default_reply_to: reply_to = self.default_reply_to.split(",") headers = headers = {} if headers is None else headers noreply = noreply or self.noreply if noreply and not reply_to and "Reply-to" not in headers: reply_to = ["noreply@%s" % site.domain] kwargs = { "subject": subject_template.render(context).replace("\n", ""), "body": body_template.render(context), "from_email": self.from_email if from_email is None else from_email, "to": to, "cc": cc, "bcc": bcc, "reply_to": reply_to, "headers": headers, "connection": connection, "attachments": attachments, "alternatives": alternatives, } email = EmailMultiAlternatives(**kwargs) if self.body_html: body_html_template = Template( self.translate(language=language).body_html) email.attach_alternative(body_html_template.render(context), "text/html") return email def send( self, request=None, from_email=None, to=None, cc=None, bcc=None, reply_to=None, context=None, attachments=None, alternatives=None, fail_silently=True, auth_user=None, auth_password=None, connection=None, headers=None, noreply=False, language=None, subject=None, body=None, ): # NOQA email = self.create( request=request, from_email=from_email, to=to, cc=cc, bcc=bcc, reply_to=reply_to, context=context, attachments=attachments, alternatives=alternatives, auth_user=auth_user, auth_password=auth_password, connection=connection, headers=headers, noreply=noreply, language=language, subject=subject, body=body, ) email.send(fail_silently=fail_silently) return email
class TermsOfService(models.TimestampModel, models.I18NModel): DRAFT = 'draft' PUBLISHED = 'published' REVIEW = 'review' STATUS_CHOICES = ( (DRAFT, _('Draft')), (REVIEW, _('Review')), (PUBLISHED, _('Published')), ) objects = TermsOfServiceManager() status = models.StatusField( choices=STATUS_CHOICES, default=DRAFT, help_text=_('If should be displayed or not.'), ) version = models.CharField( max_length=15, unique=True, db_index=True, verbose_name=_('version'), ) date_begin = models.DateTimeField( blank=True, null=True, verbose_name=_('date begin'), help_text=_('When TOS begins to be effective.'), ) date_end = models.DateTimeField( blank=True, null=True, verbose_name=_('Date end'), help_text=_('When TOS ends to be effective.'), ) label = models.TextField( blank=True, default='', verbose_name=_('label'), ) title = models.CharField( max_length=255, blank=True, default='', verbose_name=_('Title'), ) text = models.TextField( blank=True, default='', verbose_name=_('Default text'), ) human_title = models.CharField( max_length=255, blank=True, default='', verbose_name=_('human title'), help_text=_('human readable tos title'), ) human_text = models.TextField( blank=True, default='', verbose_name=_('human text'), help_text=_('human readable tos text'), ) changelog = models.TextField( blank=True, default='', verbose_name=_('changelog'), help_text=_('difference(s) from previous version'), ) options = models.ManyToManyField( Option, blank=True, verbose_name=_('options'), ) class Meta: ordering = ("-date_begin", "-version") verbose_name = _('TermsOfService') verbose_name_plural = _('TermsOfService') def __str__(self): return 'Terms of Service %(version)s %(from)s [%(status)s]' % { 'from': self.date_begin, 'version': self.version, 'status': self.get_status_display(), } @property def active(self): current = TermsOfService.objects.current return self.id == current.id def get_absolute_url(self): return reverse('tos-detail', kewarg={'slug': self.translate().slug}) absolute_url = property(get_absolute_url) def get_preview_url(self): return reverse('tos-preview', kwargs={ 'slug': self.translate().slug, 'token': self.uuid }) preview_url = property(get_preview_url) def save(self, *args, **kwargs): now = timezone.now() if not self.date_begin and self.status == TermsOfService.PUBLISHED: self.date_begin = now super().save(*args, **kwargs) def publish(self, *args, **kwargs): self.status = TermsOfService.PUBLISHED self.save(*args, **kwargs) def unpublish(self, *args, **kwargs): self.status = TermsOfService.DRAFT self.save(*args, **kwargs) @property def prev(self): try: tos = TermsOfService.objects.published()[1] except IndexError: raise TermsOfService.DoesNotExist() return tos
class CommentModel(models.TimestampModel): """ A user comment about some object. """ objects = CommentManager() site = models.ForeignKey( Site, default=get_current_site, on_delete=models.CASCADE, related_name="comments", verbose_name=_("site"), ) parent = models.ForeignKey( "self", blank=True, null=True, on_delete=models.SET_NULL, related_name="children", verbose_name=_("parent comment"), ) user = models.ForeignKey( settings.AUTH_USER_MODEL, blank=True, null=True, on_delete=models.SET_NULL, related_name="%(app_label)s_%(class)s_comments", verbose_name=_("user"), ) user_name = models.CharField(max_length=255, blank=True, verbose_name=_("user's name")) user_email = models.EmailField(max_length=255, blank=True, verbose_name=_("user's email address")) user_url = models.URLField(blank=True, verbose_name=_("user's URL")) comment = models.TextField(max_length=settings.MAX_LENGTH, verbose_name=_("comment")) notify_by_email = models.BooleanField(default=True, verbose_name=_("notify by email for updates")) ip_address = models.GenericIPAddressField(blank=True, null=True, verbose_name=_("IP address")) is_public = models.BooleanField( default=True, help_text=_("Uncheck this box to make the comment effectively disappear from the site."), verbose_name=_("is public"), ) is_removed = models.BooleanField( default=False, help_text=_( "Check this box if the comment is inappropriate. A " '"This comment has been removed" message will be displayed instead.' ), verbose_name=_("is removed"), ) class Meta: abstract = True ordering = ["created_at"] permissions = [("can_moderate", "Can moderate comments")] verbose_name = _("comment") verbose_name_plural = _("comments") def __str__(self): return "{name}: {comment}...".format(name=self.name, comment=self.comment[:50]) @property def name(self): return self.userinfo["name"] @name.setter def name(self, val): if self.user_id: raise AttributeError(_("This comment was posted by an authenticated user and thus the name is read-only.")) self.user_name = val @property def email(self): return self.userinfo["email"] @email.setter def email(self, val): if self.user_id: raise AttributeError(_("This comment was posted by an authenticated user and thus the email is read-only.")) self.user_email = val @property def url(self): return self.userinfo["url"] @url.setter def url(self, val): self.user_url = val @property def userinfo(self): if not hasattr(self, "_userinfo"): userinfo = {"name": self.user_name, "email": self.user_email, "url": self.user_url} if self.user_id: u = self.user if u.email: userinfo["email"] = u.email # If the user has a full name, use that for the user name. # However, a given user_name overrides the raw user.username, # so only use that if this comment has no associated name. if u.get_full_name(): userinfo["name"] = self.user.get_full_name() elif not self.user_name: userinfo["name"] = u.get_username() self._userinfo = userinfo return self._userinfo
class PostModel(models.TimestampModel, models.OrderedModel, models.I18NModel): STATUS_DRAFT = "draft" STATUS_PUBLISHED = "published" STATUS_CHOICES = [ (STATUS_DRAFT, _("Draft")), (STATUS_PUBLISHED, _("Published")), ] objects = PostModelManager() uuid = models.StringField( max_length=36, blank=True, verbose_name=_("uuid field"), help_text=_("for preview."), ) status = models.StatusField( choices=STATUS_CHOICES, default=STATUS_DRAFT, help_text=_("If should be displayed or not."), ) owner = models.ForeignKey( settings.AUTH_USER_MODEL, blank=True, null=True, on_delete=models.CASCADE, related_name="%(app_label)s_%(class)s_owned", verbose_name=_("owned by"), help_text=_("Post owner."), ) users = models.ManyToManyField( settings.AUTH_USER_MODEL, blank=True, related_name="%(app_label)s_%(class)s_visible", verbose_name=_("Visible only to"), help_text=_( "Post visible to these users, if empty is visible to all users."), ) event_date = models.DateTimeField( blank=True, null=True, verbose_name=_("Post date"), help_text=_("Date which post refers to."), ) pub_date_begin = models.DateTimeField( blank=True, null=True, verbose_name=_("Publication date begin"), help_text=_("When post publication date begins."), ) pub_date_end = models.DateTimeField( blank=True, null=True, verbose_name=_("Publication date end"), help_text=_("When post publication date ends."), ) title = models.StringField(unique=True, verbose_name=_("Title")) slug = models.SlugField(unique=True, verbose_name=_("Slug field")) abstract = models.TextField( blank=True, verbose_name=_("Abstract"), help_text=_("A brief description of the post"), ) text = models.TextField(blank=True, verbose_name=_("Default text")) note = models.TextField(blank=True, verbose_name=_("Note")) class Meta: abstract = True unique_together = [("title", "slug")] def __str__(self): return self.title def save(self, *args, **kwargs): self.slug = slugify(self.title) now = timezone.now() if not self.event_date and self.status == PostModel.STATUS_PUBLISHED: self.event_date = now if not self.pub_date_begin and self.status == PostModel.STATUS_PUBLISHED: self.pub_date_begin = now if not self.uuid: self.uuid = uuid1() super().save(*args, **kwargs) @property def next(self): return (self._meta.model.objects.filter( status=self.status, pub_date_begin__gt=self.pub_date_begin).order_by( "pub_date_begin").first()) @property def prev(self): return (self._meta.model.objects.filter( status=self.status, pub_date_begin__lt=self.pub_date_begin).order_by( "pub_date_begin").first())
class Log(models.Model): NOTSET = "notset" DEBUG = "debug" INFO = "info" WARNING = "warning" ERROR = "error" CRITICAL = "critical" objects = LogManager() user = models.ForeignKey( settings.AUTH_USER_MODEL, blank=True, null=True, verbose_name=_("user"), ) timestamp = models.CreationDateTimeField( null=True, blank=True, verbose_name=_("timestamp"), ) level = models.CharField( max_length=255, default=NOTSET, choices=( (NOTSET, _("Not set")), (DEBUG, _("Debug")), (INFO, _("Info")), (WARNING, _("Warning")), (ERROR, _("Error")), (CRITICAL, _("Critical")), ), verbose_name=_("level"), ) content_type = models.ForeignKey( ContentType, blank=True, null=True, verbose_name=_("content type"), ) object_id = models.TextField( default="", blank=True, #null=True, verbose_name=_("object id"), ) object_repr = models.CharField( max_length=255, default="", blank=True, verbose_name=_("object repr"), ) message = models.TextField( default="", blank=True, verbose_name=_("message"), ) realm = models.TextField( blank=True, null=True, verbose_name=_("realm"), help_text=_("realm"), ) class Meta: ordering = ["-timestamp"] verbose_name = _("log") verbose_name_plural = _("logs") def __str__(self): msg = ugettext("{timestamp} {level} {message}") return msg.format( timestamp=self.timestamp, level=self.level, message=self.message[:255], )