class MatchAvailability(models.Model): """ Represents a member's availability (either playing or umpiring) for a specific match """ member = models.ForeignKey(Member, on_delete=models.CASCADE, related_name="availabilities") """ The member that this availability relates to """ match = models.ForeignKey(Match, on_delete=models.CASCADE, related_name="availabilities") """ The match that this availability relates to """ playing_availability = models.CharField(choices=AVAILABILITY, max_length=20, null=True, blank=True) """ The member's availability to play this match """ umpiring_availability = models.CharField(choices=AVAILABILITY, max_length=20, null=True, blank=True) """ The member's availability to umpire this match """ comment = models.TextField( null=True, blank=True, help_text="Any additional details about this availability") playing_availability_changed = MonitorField(monitor='playing_availability') """ Automatically updated to the current datetime when the playing availability field is changed """ umpiring_availability_changed = MonitorField( monitor='umpiring_availability') """ Automatically updated to the current datetime when the umpiring availability field is changed """ objects = MatchAvailabilityQuerySet.as_manager() class Meta: """ Meta-info on the MatchAvailability model.""" app_label = 'availability' verbose_name_plural = 'match availabilities' def clean(self): if self.playing_availability == AVAILABILITY.available and self.umpiring_availability == AVAILABILITY.available: raise ValidationError("You cannot play and umpire the same match!") def __str__(self): return "{} - {}".format(self.member, self.match) @property def can_play(self): """ Returns true if the member can play this match """ return self.playing_availability == AVAILABILITY.available @property def can_umpire(self): """ Returns true if the member can umpire this match """ return self.umpiring_availability == AVAILABILITY.available
class EmailMessage(Base): STATUS = Choices(_('Created'), _('Scheduled'), _('Sent'), _('Opened'), _('Clicked')) status = StatusField(verbose_name=_('Status')) widget = models.ForeignKey('widgets.Widget', null=True) leed = models.ForeignKey('widgets.Leed', null=True) subject = models.CharField(max_length=50, null=True) text = models.CharField(max_length=500, null=True) html = models.CharField(max_length=1000, null=True) status_changed = MonitorField(monitor='status') scheduled_at = MonitorField(monitor='status', when=['Sent'], verbose_name=_('Email scheduled at')) sent_at = MonitorField(monitor='status', when=['Scheduled'], verbose_name=_('Email sent at')) opened_at = MonitorField(monitor='status', when=['Opened'], verbose_name=_('Email opened at')) clicked_at = MonitorField(monitor='status', when=['Clicked'], verbose_name=_('Email clicked at')) def get_absolute_url(self): return reverse('widgets:email_detail', kwargs={'pk': self.pk})
class StudentsWork(TimeStampedModel): courseevent = models.ForeignKey(CourseEvent) workers = models.ManyToManyField(settings.AUTH_USER_MODEL, verbose_name="Team", related_name='teammembers') homework = models.ForeignKey(ClassLesson, verbose_name="Aufgabe") title = models.CharField( verbose_name="Titel", max_length=100) text = models.TextField( verbose_name="Text") comments = models.TextField( verbose_name="Kommentare", blank=True) feedback_spice = enum.EnumField(FeedbackSpice, default=FeedbackSpice.MEDIUM) published = models.BooleanField(verbose_name="veröffentlichen", default=False) published_at = MonitorField(monitor='published', when=[True]) publish_count = models.IntegerField(default=0) republished_at = MonitorField(monitor='publish_count') objects = StudentsWorkManager() class Meta: verbose_name = _("Teilnehmer-Arbeit") verbose_name_plural = _("Teilnehmer-Arbeiten") def __unicode__(self): return self.title def team(self): """ Returns all the accounts of users who are students in the courseevent """ return self.workers.all().order_by('username').prefetch_related('teammembers') def team_display(self): """ Returns all the accounts of users who are students in the courseevent """ teachers = self.team namesstring = "" for worker in self.workers.all(): if namesstring != "": namesstring += ", " namesstring += worker.get_full_name() return namesstring def workers_emails(self): return self.workers.all().values_list('email', flat=True, ) def comment_count(self): return Comment.objects.filter(studentswork=self).count() def team_size(self): return self.team.count()
class Mesa(models.Model): ESTADOS_ = ('EN ESPERA', 'ABIERTA', 'CERRADA', 'ESCRUTADA') ESTADOS = Choices(*ESTADOS_) estado = StatusField(choices_name='ESTADOS', default='EN ESPERA') hora_abierta = MonitorField(monitor='estado', when=['ABIERTA']) hora_cerrada = MonitorField(monitor='estado', when=['CERRADA']) hora_escrutada = MonitorField(monitor='estado', when=['ESCRUTADA']) eleccion = models.ForeignKey('Eleccion') numero = models.PositiveIntegerField() es_testigo = models.BooleanField(default=False) circuito = models.ForeignKey(Circuito) # lugar_votacion = models.ForeignKey(LugarVotacion, verbose_name='Lugar de votacion', null=True, related_name='mesas') url = models.URLField(blank=True, help_text='url al telegrama') foto_del_acta = models.ImageField(upload_to=path_foto_acta, null=True, blank=True) electores = models.PositiveIntegerField(null=True, blank=True) taken = models.DateTimeField(null=True) def get_absolute_url(self): return reverse('detalle-mesa', args=( self.eleccion.id, self.numero, )) @property def asignacion_actual(self): return self.asignacion.order_by('-ingreso').last() @property def computados(self): return self.votomesaoficial_set.aggregate(Sum('votos'))['votos__sum'] @property def tiene_reporte(self): return self.votomesareportado_set.aggregate(Sum('votos'))['votos__sum'] @property def foto_o_attachment(self): from adjuntos.models import Attachment try: return self.foto_del_acta or self.attachment.file except Attachment.DoesNotExist: return None @property def proximo_estado(self): if self.estado == 'ESCRUTADA': return self.estado pos = Mesa.ESTADOS_.index(self.estado) return Mesa.ESTADOS_[pos + 1] def __str__(self): return f"Mesa {self.numero}"
class Command(TimeStampedModel): STATUS = Choices( (0, 'created', 'Created'), (1, 'sent', 'Sent'), (2, 'completed', 'Completed'), (3, 'error', 'Error'), ) COMMAND_TYPES = Choices( (0, 'change_setting', 'Change Setting'), (1, 'launch_payload', 'Launch Payload'), (2, 'uninstall', 'Uninstall'), ) implant = models.ForeignKey(Implant) uuid = UUIDField(auto=True) status = models.IntegerField(choices=STATUS, default=STATUS.created) sent_at = MonitorField(monitor='status', when=[STATUS.sent], blank=True, null=True) resolved_at = MonitorField(monitor='status', when=[STATUS.completed, STATUS.error], blank=True, null=True) command_type = models.IntegerField(choices=COMMAND_TYPES) argument = models.TextField(blank=True) def __unicode__(self): return '{command} for {implant}'.format( command=self.get_command_type_display(), implant=self.implant) def mark_sent(self): logger.info( 'Command {uuid} ({implant} - {type}) marked as sent'.format( uuid=self.uuid, implant=self.implant, type=self.get_command_type_display())) self.status = self.STATUS.sent self.save() def resolve(self, error=False): if error: self.status = self.STATUS.error logger.info( 'Command {uuid} ({implant} - {type}) marked as error'.format( uuid=self.uuid, implant=self.implant, type=self.get_command_type_display())) else: self.status = self.STATUS.completed logger.info( 'Command {uuid} ({implant} - {type}) marked as completed'. format(uuid=self.uuid, implant=self.implant, type=self.get_command_type_display())) self.save()
class Course(TimeStampedModel): STATUS = Choices((0, "writing", "writing"), (1, "finished", "finished"),) LEVEL = Choices( (0, "introductory", "入门"), (1, "intermediate", "进阶"), (2, "advanced", "高级"), ) title = models.CharField(_("title"), max_length=150) slug = models.SlugField(_("slug"), unique=True) description = models.TextField(_("description"), blank=True) brief = models.CharField(_("brief"), max_length=200, blank=True) cover = models.ImageField(_("cover"), upload_to="courses/covers/") cover_thumbnail = ImageSpecField( source="cover", format="JPEG", processors=[ResizeToFill(540, 300)], options={"quality": 90}, ) cover_caption = models.CharField(_("cover_caption"), max_length=100, blank=True) status = models.IntegerField(_("status"), choices=STATUS, default=STATUS.writing) status_changed = MonitorField(_("status_changed"), monitor="status") level = models.IntegerField(_("level"), choices=LEVEL, default=LEVEL.introductory) level_changed = MonitorField(_("level_changed"), monitor="level") rank = models.IntegerField(_("rank"), default=0) creator = models.ForeignKey( settings.AUTH_USER_MODEL, verbose_name=_("creator"), on_delete=models.CASCADE ) category = models.ForeignKey( Category, verbose_name=_("category"), on_delete=models.SET_NULL, blank=True, null=True, ) class Meta: ordering = ("rank", "-created") verbose_name = _("course") verbose_name_plural = _("courses") def __str__(self): return self.title def get_absolute_url(self): return reverse("courses:course_detail", kwargs={"slug": self.slug}) @cached_property def first_material(self): return self.material_set.order_by("rank", "created").first() @cached_property def rich_content(self): return generate_rich_content(self.description)
class CourseEventParticipation(TimeStampedModel): courseevent = models.ForeignKey(CourseEvent) user = models.ForeignKey(settings.AUTH_USER_MODEL) hidden = models.BooleanField(verbose_name=_('versteckt'), default=False) hidden_status_changed = MonitorField(monitor='hidden') notification_forum = enum.EnumField(NotificationSettings, default=NotificationSettings.ALL) notification_work = enum.EnumField(NotificationSettings, default=NotificationSettings.ALL) objects = ParticipationManager() class Meta: verbose_name = _("Kurs-Teilnehmer") verbose_name_plural = _("Kurs-Teilnehmer") unique_together = ('user', 'courseevent') def __unicode__(self): return u'%s / %s' % (self.courseevent, self.user) @cached_property def course(self): return self.courseevent.course def hide(self): self.hidden = True self.save() def unhide(self): self.hidden = False self.save()
class Fragment(Commentable, Votable, models.Model): STATUS = Choices('OPEN', 'CLOSED') user = models.ForeignKey( User, on_delete=models.CASCADE, ) title = models.CharField(max_length=256) content = models.CharField(max_length=2048) tags = models.ManyToManyField(Tag) status = StatusField(choices=STATUS, default=STATUS.OPEN) date_created = models.DateTimeField(auto_now_add=True, editable=False) date_modified = models.DateTimeField(auto_now=True, editable=False) date_closed = MonitorField(monitor='status', when=[STATUS.CLOSED], default=None, null=True, blank=True, editable=False) def __str__(self): return f"{ self.pk } { self.title[:10] if len(self.title) > 10 else self.title }" def get_answer_count(self): return self.answer_set.count()
class Task(Uuidable, Orderable, Authorable, models.Model): name = models.CharField(_("nombre"), max_length=2000, blank=False) user_story = models.ForeignKey( UserStory, verbose_name=_("historia de usuario"), related_name="tasks", blank=False, null=False, on_delete=models.CASCADE, ) weight = models.PositiveSmallIntegerField( _("peso"), blank=False, null=False, default=1, validators=[MinValueValidator(1)]) done = models.BooleanField(_("finalizada"), default=False) done_changed = MonitorField(_("último cambio en finalizada"), monitor="done") order_with_respect_to = ("user_story", ) def __str__(self): return f"{self.user_story} / {self.order}.{self.name} / {self.done}" class Meta(Orderable.Meta): verbose_name = _("tarea") verbose_name_plural = _("tareas") constraints = [ models.UniqueConstraint(fields=["name", "user_story"], name="unique_task") ]
class ExporterChunk(TimeStampedModel): STATUS_CHOICES = Choices(("created", _("created")), ("processing", _("processing")), ("success", _("success")), ("error", _("error"))) exporter = models.ForeignKey(Exporter, related_name="chunks") page = models.IntegerField() file = models.FileField(blank=True, null=True, default=None, storage=default_storage) status = models.CharField(max_length=16, choices=STATUS_CHOICES, default=STATUS_CHOICES.created) done_at = MonitorField(monitor='status', when=['success', 'error'], default=None, null=True) objects = ExporterChunkManager() def set_status(self, status): """ Sets the status to one of the choices """ if status not in self.STATUS_CHOICES: raise ExporterStatusException("Invalid status.") self.status = status self.save()
class Product(TimeStampedModel): description = FroalaField(blank=True) # price with currency price = models.DecimalField(max_digits=12, decimal_places=2, null=True, blank=True, verbose_name=_('Verkaufspreis')) currency = enum.EnumField(Currency, default=Currency.EUR) price_changed = MonitorField(monitor='price', verbose_name=_("letzte Preisänderung am")) display_nr = models.IntegerField(default=1) # product type product_type = enum.EnumField(Producttype, default=Producttype.OTHER) objects = ProductManager() class Meta: abstract = True def __unicode__(self): return "%s: %s" % (self.name)
class StatusModel(models.Model): """ An abstract base class model with a ``status`` field that automatically uses a ``STATUS`` class attribute of choices, a ``status_changed`` date-time field that records when ``status`` was last modified, and an automatically-added manager for each status that returns objects with that status only. """ status = StatusField(_('status')) status_changed = MonitorField(_('status changed'), monitor='status') def save(self, *args, **kwargs): """ Overriding the save method in order to make sure that status_changed field is updated even if it is not given as a parameter to the update field argument. """ if ('update_fields' in kwargs and 'status' in kwargs['update_fields'] and 'status_changed' not in kwargs['update_fields']): kwargs['update_fields'] += ['status_changed'] super().save(*args, **kwargs) class Meta: abstract = True
class SubjectTaskStatusModel(StatusModel): """Abstract class that tracks the various states a subject might be in relation to either an experiment or a battery""" STATUS = Choices("not-started", "started", "completed", "failed") status = StatusField(default="not-started") started_at = MonitorField(monitor="status", when=["started"]) completed_at = MonitorField(monitor="status", when=["completed"]) failed_at = MonitorField(monitor="status", when=["failed"]) @property def completed(self): return self.status == self.STATUS.completed class Meta: abstract = True
class Organization(DjangoOrganization, TimeStampedModel): # Stripe data subscription_stripe_customer_id = models.CharField(max_length=255, default="") subscription_stripe_checkout_session_id = models.CharField( max_length=255, default="" ) subscription_stripe_subscription_id = models.CharField(max_length=255, default="") # Subscription data SUBSCRIPTION_CHOICES = Choices("free", "basic") subscription_type = StatusField(choices_name="SUBSCRIPTION_CHOICES", default="free") # Differs from the creation date of the organization, tracks when the subscription is changed subscription_date = MonitorField(monitor="subscription_type") # Organization data contact_email = models.EmailField(max_length=254, unique=True) description = models.TextField() currency = models.CharField( choices=CURRENCY_CHOICES, default=CURRENCY_CHOICES.euro, max_length=255 ) @property def stats(self): # TODO: fix circulair import # To prevent a circular import reference, we import these here from organization.models.inventory import Product, Location, Mutation return { "product_count": Product.objects.for_organization(self).count(), "location_count": Location.objects.for_organization(self).count(), "mutation_count": Mutation.objects.for_organization(self).count(), } def __str__(self): return self.name
class User(AbstractUser): HAPPINESS_CHOICES = Choices( (1, "Unhappy", _("Unhappy")), (3, "Neutral", _("Neutral")), (5, "Very Happy", _("Very Happy")), ) # First Name and Last Name do not cover name patterns around the globe name = CharField(_("Name of User"), blank=True, max_length=255) timezone = TimeZoneField(_("Timezone of User"), blank=True, default="UTC") happiness_level = IntegerField(choices=HAPPINESS_CHOICES, default=HAPPINESS_CHOICES.Neutral) happiness_level_changed = MonitorField(monitor="happiness_level", blank=True, null=True) team = ForeignKey("users.Team", on_delete=SET_NULL, blank=True, null=True) def __str__(self): return f"{self.username} ({self.id})" def get_absolute_url(self): return reverse("users:detail", kwargs={"username": self.username}) @property def can_change_happiness_level(self): if not self.happiness_level_changed: return user_tz_now = datetime.now(self.timezone) return user_tz_now - self.happiness_level_changed > timedelta(days=1)
class TrainingResult(models.Model): """Training result information obtained once deployed a model""" STATUS = Choices('created', 'deployed', 'stopped', 'finished') """Sets its default value to the first item in the STATUS choices:""" status = StatusField() status_changed = MonitorField(monitor='status') deployment = models.ForeignKey(Deployment, default=None, related_name='results', on_delete=models.CASCADE) model = models.ForeignKey(MLModel, related_name='trained', on_delete=models.CASCADE) train_loss = models.DecimalField(max_digits=15, decimal_places=10, blank=True, null=True) train_metrics = models.TextField(blank=True) val_loss = models.DecimalField(max_digits=15, decimal_places=10, blank=True, null=True) val_metrics = models.TextField(blank=True) trained_model = models.FileField(upload_to=settings.TRAINED_MODELS_DIR, blank=True) class Meta(object): ordering = ('-status_changed', )
class Inference(models.Model): """Training result information obtained once deployed a model""" INPUT_FORMAT = Choices('RAW', 'AVRO') STATUS = Choices('deployed', 'stopped') """Sets its default value to the first item in the STATUS choices:""" status = StatusField() status_changed = MonitorField(monitor='status') model_result = models.ForeignKey(TrainingResult, null=True, related_name='inferences', on_delete=models.SET_NULL) replicas = models.IntegerField(default=1) input_format = StatusField(choices_name='INPUT_FORMAT') input_config = models.TextField(blank=True) input_topic = models.TextField(blank=True) output_topic = models.TextField(blank=True) time = models.DateTimeField(default=now, editable=False) limit = models.DecimalField(max_digits=15, decimal_places=10, blank=True, null=True) output_upper = models.TextField(blank=True) class Meta(object): ordering = ('-time', )
class Exporter(TimeStampedModel): """ Exporter model handles the initial creation of the exportation. All the info needed for the exportation comes from here """ STATUS_CHOICES = Choices(("created", _("created")), ("processing", _("processing")), ("done", _("done")), ("error", _("error"))) uuid = models.UUIDField(default=uuid4) email = models.EmailField() content_type = models.ForeignKey(ContentType) query = models.FileField(blank=True, null=True, default=None, storage=default_storage) attrs = jsonfield.JSONField(blank=True, null=True, default=None) limit_per_task = models.IntegerField(default=100) total = models.IntegerField(editable=False) file = models.FileField(blank=True, null=True, default=None, storage=default_storage) status = models.CharField(max_length=16, choices=STATUS_CHOICES, default=STATUS_CHOICES.created) done_at = MonitorField(monitor='status', when=['done', 'error'], default=None, null=True) objects = ExporterManager() def set_status(self, status): """ Sets the status to one of the status choices """ if status not in self.STATUS_CHOICES: raise ExporterStatusException("Invalid status.") self.status = status self.save() @property def chunks_is_successful(self): """ Check if its chunks are completed succesful """ return self.chunks.filter(status=ExporterChunk.STATUS_CHOICES.success ).count() == self.chunks.all().count() @property def has_chunk_errors(self): """ Check if any of the created chunks have returned errors """ return self.chunks.filter( status=ExporterChunk.STATUS_CHOICES.error).exists() @property def is_pending(self): """ Check if it is pending """ return self.status == self.STATUS_CHOICES.processing @property def is_done(self): return self.status == self.STATUS_CHOICES.done
class Feedback(models.Model): user = models.ForeignKey(settings.AUTH_USER_MODEL, help_text=_("Author"), null=True) text = models.TextField(verbose_name=_("Comment"), help_text=_("Text reported by user")) status = models.BooleanField(default=False, verbose_name=_("Status"), help_text=_("Feedback has been served")) status_changed = MonitorField(monitor='status', verbose_name=_("Status change date")) created = models.DateTimeField(auto_now_add=True, verbose_name=_("Creation date")) def get_status_display(self): return _('open') if self.status else _('closed') def __unicode__(self): return str(self.created) def get_absolute_url(self): return reverse("tasty_feedback:details", kwargs={'pk': str(self.pk)}) def get_github_link(self): if hasattr(settings, 'FEEDBACK_GITHUB_REPO'): body = quote(githubify(self.text).encode('utf-8')) return "%s/issues/new?body=%s" % (settings.FEEDBACK_GITHUB_REPO, body) return class Meta: verbose_name = _("Feedback") verbose_name_plural = _("Feedbacks")
class StatusModel(models.Model): """ An abstract base class model with a ``status`` field that automatically uses a ``STATUS`` class attribute of choices, a ``status_changed`` date-time field that records when ``status`` was last modified, and an automatically-added manager for each status that returns objects with that status only. """ status = StatusField(_("status")) status_changed = MonitorField(_("status changed"), monitor="status") def save(self, *args, **kwargs): """ Overriding the save method in order to make sure that status_changed field is updated even if it is not given as a parameter to the update field argument. """ update_fields = kwargs.get("update_fields", None) if update_fields and "status" in update_fields: kwargs["update_fields"] = set(update_fields).union( {"status_changed"}) super().save(*args, **kwargs) class Meta: abstract = True
class Marca(models.Model): """ Es el marca comercial de un producto. Ejemplo: Rosamonte """ fabricante = models.ForeignKey('EmpresaFabricante', null=True, blank=True) nombre = models.CharField(max_length=100, unique=True, verbose_name=u"Nombre de la marca") logo = ImageCropField(null=True, blank=True, upload_to='marcas') # size is "width x height" logo_cropped = ImageRatioField('logo', '150x125', verbose_name=u'Recortar logo', free_crop=True) logo_changed = MonitorField(monitor='logo', editable=False) def __unicode__(self): return self.nombre class Meta: unique_together = (('nombre', 'fabricante')) verbose_name = u"marca" verbose_name_plural = u"marcas"
class Material(AbstractEntry): STATUS = Choices( (0, "writing", "writing"), (1, "draft", "draft"), (2, "published", "published"), (3, "hidden", "hidden"), ) status = models.IntegerField(_("status"), choices=STATUS, default=STATUS.draft) status_changed = MonitorField(_("status_changed"), monitor="status") cover = models.ImageField(_("cover"), upload_to="covers/materials/", blank=True) cover_thumbnail = ImageSpecField( source="cover", format="JPEG", processors=[ResizeToFill(60, 60)], options={"quality": 90}, ) cover_caption = models.CharField(_("cover_caption"), max_length=100, blank=True) rank = models.IntegerField(_("rank"), default=0) course = models.ForeignKey( Course, verbose_name=_("course"), on_delete=models.CASCADE ) objects = MaterialManager() index = IndexMaterialManager() class Meta: ordering = ["rank", "created"] verbose_name = _("material") verbose_name_plural = _("materials") def __str__(self): return self.title def get_absolute_url(self): return reverse( "courses:material_detail", kwargs={"pk": self.pk, "slug": self.course.slug} ) @property def type(self): return "m" @cached_property def prev(self): return self.get_next_or_previous( is_next=False, value_fields=["id", "title", "course__slug"], course_id=self.course_id, ) @cached_property def next(self): return self.get_next_or_previous( is_next=True, value_fields=["id", "title", "course__slug"], course_id=self.course_id, )
class BasicContentModel(TimeStampedModel): """ 内容基类,包含功能: created, modified status 默认:0 draft, 1 published is_removed: 软删除标记 Demo1: find list draft_books = Book.draft.all() published_books = Book.published.all() not_deleted_books = Book.objects.all() all_books = Book.all_objects.all() Demo2: status change book.status = Book.STATUS.draft book.status = Book.STATUS.published Demo3: status_display status_display = Article.STATUS[article.status] 注意: 1. 子类如果需要替换objects,自定义的Manager需要继承BasicContentManager 2. track=FieldTracker 不能在基类中定义,需要在子类中实现时定义: https://django-model-utils.readthedocs.io/en/latest/utilities.html#field-tracker """ STATUS = Choices((0, "draft", _("草稿")), (1, "published", _("已发布"))) status = models.IntegerField(choices=STATUS, default=STATUS.draft) status_changed = MonitorField(_("status changed"), monitor="status") is_removed = models.BooleanField(default=False) def delete(self, using=None, soft=True, *args, **kwargs): """ Soft delete object (set its ``is_removed`` field to True). Actually delete object if setting ``soft`` to False. """ if soft: self.is_removed = True self.save(using=using) else: return super().delete(using=using, *args, **kwargs) objects = BasicContentManager() all_objects = models.Manager() def save(self, *args, **kwargs): """ Overriding the save method in order to make sure that status_changed field is updated even if it is not given as a parameter to the update field argument. """ update_fields = kwargs.get("update_fields", None) if update_fields and "status" in update_fields: kwargs["update_fields"] = set(update_fields).union( {"status_changed"}) super().save(*args, **kwargs) class Meta: abstract = True
class Comment(models.Model): STATUS = Choices("name", "email", "address") name = models.CharField(max_length=100) email = models.EmailField(max_length=30) address = models.CharField(max_length=40) status = StatusField() published_at = MonitorField(monitor='status', when=['name', "email", "address"])
class Url(TimeStampedModel): ''' Url model shortcode -> str pk url -> str redirect_count -> int: amount of redirect calls last_redirect -> datetime: last redirect timestamp created -> datetime modified -> datetime ''' shortcode = models.CharField( _('shorcode'), primary_key=True, max_length=6, help_text=_('url shortname'), validators=[ RegexValidator( regex=r'^[a-z0-9_]{6}', message=_(REGEX_VALIDATOR_MSG), code='invalid shortcode', ), ], ) url = models.CharField(_('url'), max_length=256, validators=[URLValidator()]) _redirect_count = models.IntegerField( default=0, help_text=_('Number of times shortcode has been retreived')) last_redirect = MonitorField(monitor='redirect_count') objects = UrlManager() @property def redirect_count(self) -> int: return self._redirect_count def increment_redirect_count(self) -> None: """ increment redirect count by one. :return :type Url """ self._redirect_count += 1 self.save() class Meta: ordering: Tuple[str] = ('created', 'modified') def __str__(self) -> str: return self.url def __repr__(self) -> str: return f'<{self.__class__.__name__}({self.__str__()!r})>'
class ForumContributionModel(TimeStampedModel): courseevent = models.ForeignKey(CourseEvent) hidden = models.BooleanField(verbose_name=_('versteckt'), default=False) hidden_status_changed = MonitorField(monitor='hidden') text = models.TextField() class Meta: abstract = True
class JoinRequest(TimeStampedModel): class Status(models.TextChoices): PENDING = "pending", _("Pending") ACCEPTED = "accepted", _("Accepted") REJECTED = "rejected", _("Rejected") community = models.ForeignKey(Community, on_delete=models.CASCADE) sender = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) status = models.CharField(max_length=100, choices=Status.choices, default=Status.PENDING, db_index=True) status_changed = MonitorField(monitor="status") sent = models.DateTimeField(null=True, blank=True) intro = models.TextField( blank=True, verbose_name=_("Introduction"), help_text=_("Tell us a little bit about yourself and why you " "would like to join this community (Optional)."), ) objects = JoinRequestQuerySet.as_manager() class Meta: unique_together = ("community", "sender") indexes = [models.Index(fields=["status"])] def __str__(self): return str(self.sender) def get_absolute_url(self): return reverse("join_requests:detail", args=[self.id]) def is_pending(self): return self.status == self.Status.PENDING def is_accepted(self): return self.status == self.Status.ACCEPTED def is_rejected(self): return self.status == self.Status.REJECTED def accept(self): self.status = JoinRequest.Status.ACCEPTED self.save() def reject(self): self.status = JoinRequest.Status.REJECTED self.save()
class ConversionQueueItem(models.Model): """Represents an item in the conversion queue.""" url = models.ForeignKey( Version, null=False, verbose_name='URL', on_delete=models.CASCADE, ) file = models.CharField(max_length=4096, verbose_name='Fil') type = models.CharField(max_length=256, verbose_name='Type') page_no = models.IntegerField(null=True, verbose_name='Side') # Note that SUCCESS is indicated by just deleting the record NEW = "NEW" PROCESSING = "PROCESSING" FAILED = "FAILED" STATUS = ( (NEW, "Ny"), (PROCESSING, "I gang"), (FAILED, "Mislykket"), ) status = StatusField(max_length=10, default=NEW, verbose_name='Status') process_id = models.IntegerField(blank=True, null=True, verbose_name='Proces id') process_start_time = MonitorField(monitor='status', when=[PROCESSING], blank=True, null=True, verbose_name='Proces starttidspunkt') @property def file_path(self): """Return the full path to the conversion queue item's file.""" return self.file @property def tmp_dir(self): """The path to the temporary dir associated with this queue item.""" return os.path.join(self.url.scan.scan_dir, 'queue_item_%d' % (self.pk)) def delete_tmp_dir(self): """Delete the item's temp dir if it is writable.""" if os.access(self.tmp_dir, os.W_OK): shutil.rmtree(self.tmp_dir, True) class Meta: abstract = False
class Invite(TimeStampedModel): class Status(models.TextChoices): PENDING = "pending", _("Pending") ACCEPTED = "accepted", _("Accepted") REJECTED = "rejected", _("Rejected") id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) email = models.EmailField() community = models.ForeignKey(Community, on_delete=models.CASCADE) status = models.CharField(max_length=100, choices=Status.choices, default=Status.PENDING, db_index=True) status_changed = MonitorField(monitor="status") sent = models.DateTimeField(null=True, blank=True) sender = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) objects = InviteQuerySet.as_manager() class Meta: unique_together = ("email", "community") def __str__(self): return self.email def is_pending(self): return self.status == self.Status.PENDING def is_accepted(self): return self.status == self.Status.ACCEPTED def is_rejected(self): return self.status == self.Status.REJECTED def set_status(self, status): self.status = status self.save() @transaction.atomic def accept(self, user): self.set_status(self.Status.ACCEPTED) try: Membership.objects.create(member=user, community=self.community) except IntegrityError: pass def reject(self): self.set_status(self.Status.REJECTED)
class TelegramMessage(Base): STATUS = Choices(_('Created'), _('Scheduled'), _('Sent')) status = StatusField(verbose_name=_('Status')) widget = models.ForeignKey('widgets.Widget', null=True) leed = models.ForeignKey('widgets.Leed', null=True) message = models.CharField(max_length=500, null=True) status_changed = MonitorField(monitor='status') scheduled_at = MonitorField(monitor='status', when=['Scheduled'], verbose_name=_('SMS sheduled at')) sent_at = MonitorField(monitor='status', when=['Sent'], verbose_name=_('SMS sent at')) def get_absolute_url(self): return reverse('widgets:telegram_detail', kwargs={'pk': self.pk})