class Usuario(AbstractBaseUser, PermissionsMixin): username = models.CharField( verbose_name='Nombre de usuario', max_length=50, unique=True, db_index=True, validators=[ MinLengthValidator(2), MaxLengthValidator(50), ] ) email = models.EmailField( max_length=100, unique=True, db_index=True, validators=[ EmailValidator(), ] ) numero_tarjeta_magnetica = models.PositiveIntegerField(verbose_name='Número de tarjeta mágnetica', default=0) numero_acceso_biometrico = models.PositiveIntegerField(verbose_name='Número de acceso biométrico', default=0) slug = models.SlugField(editable=False, max_length=255 ,unique=True, db_index=True, ) fecha_registro = models.DateTimeField(auto_now_add=True, auto_now=False) usuario_creador = models.ForeignKey('self', null=True, default=None) nombre_host = models.CharField(max_length=255) direccion_ip = models.GenericIPAddressField(validators=[validate_ipv46_address]) fecha_ultima_actualizacion = models.DateTimeField(auto_now_add=False, auto_now=True) ultimo_usuario_editor = models.ForeignKey('self', null=True, default=None, related_name='ultimo_usuario_editor_usuarios_related') ultimo_nombre_host = models.CharField(max_length=255) ultimo_direccion_ip = models.GenericIPAddressField(validators=[validate_ipv46_address]) objects = UserManager() is_active = models.BooleanField(default=True) is_staff = models.BooleanField(default=True) USERNAME_FIELD = 'username' REQUIRED_FIELDS = ['email',] def save(self, *args, **kwargs): if not self.pk: self.slug = slugify(self.username) else: slug = slugify(self.username) if self.slug != slug: self.slug = slug super(Usuario, self).save(*args, **kwargs) def get_short_name(self): return self.username #Opciones class Meta: #Nombre para la tabla del gestor de base de datos db_table = 'Usuarios' #Ordenar los registros por un campo especifico ordering = ('username',) #Nombre para el Conjunto de Objetos en el Panel de Administración verbose_name = 'Usuario' #Nombre en Plural en la lista de módulos en el Panel de Administración verbose_name_plural = 'Usuarios'
class Node(models.Model): type = "node" remote_server_url = models.URLField(max_length=200, primary_key=True, unique=True) remote_server_username = models.CharField(max_length=200, default='', blank=True) remote_server_password = models.CharField(max_length=200, default='', blank=True, validators=[MinLengthValidator(8)]) adminApproval = models.BooleanField(default=False) konnection_username = models.CharField(max_length=200, default='', blank=True) konnection_password = models.CharField(max_length=200, default='', blank=True) # create author of type 'node' if node is admin approved and remote_server_* are provided def save(self, *args, **kwargs): # set username to hostname if blank if not self.remote_server_username: self.remote_server_username = self.hostname() self.remote_server_username = re.sub(r'\W+', '', self.remote_server_username) super(Node, self).save(*args, **kwargs) user_model = get_user_model() if self.adminApproval and self.remote_server_url and self.remote_server_username and self.remote_server_password: try: server_user = user_model.objects.get(username=self.remote_server_username) # update server_user server_user.username = self.remote_server_username server_user.password = self.remote_server_password server_user.url = self.remote_server_url server_user.adminApproval = self.adminApproval server_user.save() except user_model.DoesNotExist: # create server_user user_model.objects.create_author( self.remote_server_username, self.remote_server_password, url=self.remote_server_url, adminApproval=self.adminApproval, type=self.type ) else: # change adminApproval in server_user to False if it exists already try: server_user = user_model.objects.get(username=self.remote_server_username) if server_user: server_user.adminApproval = False server_user.save() except user_model.DoesNotExist: pass # delete corresponding author if exists def delete(self): try: server_user = get_user_model().objects.get(username=self.remote_server_username) if server_user: server_user.delete() except get_user_model().DoesNotExist: pass super(Node, self).delete() def hostname(self): parsed_url = urlparse(self.remote_server_url) return parsed_url.hostname
class User(AbstractBaseUser, PermissionsMixin): """Custom user model that support using phone number instead of username""" EDUCATION_CHOICES = [ ('High school', 'High school'), ('College', 'College'), ('University', 'University') ] EMPLOYMENT_CHOICES = [ ('Student', 'Student'), ('Full time', 'Full time'), ('Part time', 'Part time') ] phone_regex = RegexValidator( regex=r'^\+?1?\d{9,15}$', message="Phone number must be entered in the format: '+999999999'. \ Up to 15 digits allowed." ) # INFO phone_number = models.CharField(_('phone number'), max_length=17, unique=True) email = models.EmailField(_('email address'), blank=True, null=True) name = models.CharField(max_length=255) first_name = models.CharField(_('first name'), max_length=30, blank=True, null=True) last_name = models.CharField(_('last name'), max_length=30, blank=True, null=True) age = models.PositiveSmallIntegerField(_('age'), validators=[ MinValueValidator(18), MaxValueValidator(150) ], blank=True, null=True) zipcode = models.PositiveSmallIntegerField(_('zipcode'), validators=[ MinLengthValidator(5), MaxLengthValidator(5) ], blank=True, null=True) income = models.DecimalField(_('income'), max_digits=10, decimal_places=2, validators=[DecimalValidator], blank=True, null=True) education = models.CharField(_('education'), max_length=50, choices=EDUCATION_CHOICES, blank=True, null=True) employment = models.CharField(_('employment'), max_length=50, choices=EMPLOYMENT_CHOICES, blank=True, null=True) # SCORES scores_initial = models.ForeignKey('Score', on_delete=models.CASCADE, null=True, blank=True, related_name="score_initial_owner") scores_final = models.ForeignKey('Score', on_delete=models.CASCADE, null=True, blank=True, related_name="score_final_owner") date_joined = models.DateTimeField(_('registered'), auto_now_add=True, null=True) is_active = models.BooleanField(default=True) is_staff = models.BooleanField(default=False) objects = UserManager() USERNAME_FIELD = 'phone_number' def has_perm(self, perm, obj=None): "Does the user have a specific permission?" # Simplest possible answer: Yes, always return True def has_module_perms(self, app_label): "Does the user have permissions to view the app `app_label`?" # Simplest possible answer: Yes, always return True def get_full_name(self): """Returns the firstname plus the last_name, and a space in between.""" full_name = '%s %s' % (self.first_name, self.last_name) return full_name.strip() def get_short_name(self): """Returns the short name for the user.""" return self.first_name
class Empresas(models.Model): email = models.EmailField(unique=True) razao_social = models.CharField(max_length=255) endereco = models.CharField(max_length=255) ramo = models.CharField(max_length=255) numero = models.IntegerField() senha = models.TextField(validators=[MinLengthValidator(6)]) def login_empresa(self, request=None, email=None, senha=None): if not request.session.get('email_empresa', None): self.email = email self.senha = HashPassword(senha) try: self.empresa = Empresas.objects.get(email=self.email, senha=self.senha) if request.session.get('email', False): del request.session['email'] if request.session.get('id', False): del request.session['id'] if request.session.get('candidato'): del request.session['candidato'] request.session['email_empresa'] = self.empresa.email request.session['id_empresa'] = self.empresa.id request.session['empresa'] = True return self.empresa except Empresas.DoesNotExist: return False else: return False def empresa_update(self, id=None, email=None, razao_social=None, endereco=None, ramo=None, numero=None, senha=None): if id: self.empresa = self.get_empresa_by_id(id=id) if self.empresa: if senha: self.empresa.senha = HashPassword(senha) self.empresa.email = email self.empresa.razao_social = razao_social self.empresa.endereco = endereco self.empresa.ramo = ramo self.empresa.numero = numero self.empresa.save() return True else: return False def get_empresa_by_id(self, id=id): if id: self.id = id try: self.empresa = Empresas.objects.get(pk=self.id) return self.empresa except Empresas.DoesNotExist: return False else: return False
class Article(models.Model): """ A simple model. Use Article.get_articles(CATEGORY=None, TAG=None, NUM=100) to get available articles list. Use Article.get_recently_articles(RECENTLY_ARTICLES_NUM) to get recently(RECENTLY_ARTICLES_NUM) articles. Use Article.get_hots_articles(HOT_ARTICLES_NUM) to get hot(HOT_ARTICLES_NUM) articles. Use article_object.related_articles(REALITVE_ARTICLES_NUM) to get related_articles of an object. """ author = models.ForeignKey(User, verbose_name=_(u"Author")) category = models.ForeignKey(Category, verbose_name=_(u'Category')) title = models.CharField(max_length=100, verbose_name=_(u'Title')) tags = models.CharField(max_length=100, null=True, blank=True, verbose_name=_(u'Tags'), help_text=_(u"Use the comma(',') separated") ) summary = models.TextField( verbose_name=_(u'Summary'), validators=[MinLengthValidator(30)], error_messages={"min_length": _("At least %(limit_value)d word,please!(it has %(show_value)d).") } ) content = wmd_models.MarkDownField(verbose_name=_(u'Content')) title_image = ProcessedImageField(upload_to='thumbnail', processors=[ResizeToFill(70, 70)], format='JPEG', options={'quality': 60} ) status = models.IntegerField( default=0, choices=STATUS.items(), verbose_name=_(u'Status')) view_times = models.IntegerField(default=1) like_times = models.IntegerField(default=1) liked_ip = models.TextField(verbose_name=_(u'liked_ip')) disliked_ip = models.TextField(verbose_name=_(u'disliked_ip')) is_top = models.BooleanField(default=False, verbose_name=_(u'Top')) create_time = models.DateTimeField( _(u'Create Time'), auto_now_add=True, editable=True) update_time = models.DateTimeField(_(u'Update Time'), auto_now=True) def __unicode__(self): return self.title def tags_list(self): """ Use article_object.tags_list() to split and get article_object's tags. """ return [tag.strip() for tag in self.tags.split(',')] def related_articles(self, num): """ A simple method. Use article_object.related_articles(REALITVE_ARTICLES_NUM) to get related_articles of an object. """ related_articles = None try: related_articles = Article.objects.values('id', 'title', 'view_times', 'update_time', 'author').\ filter(tags__icontains=self.tags_list()[0]).\ exclude(id=self.id)[:num] except IndexError: pass if not related_articles: related_articles = Article.objects.values('id', 'title', 'view_times', 'update_time', 'author').\ filter(category=self.category).\ exclude(id=self.id)[:num] return related_articles @classmethod def get_articles(cls, CATEGORY=None, TAG=None, NUM=100): """ A simple classmethod. Use Article.get_articles(CATEGORY=None, TAG=None, NUM=100) to get articles list. """ if CATEGORY: article_list = cls.objects.filter( Q(status=0) & Q(category__name__icontains=CATEGORY))[:NUM] return article_list if TAG: article_list = cls.objects.filter( Q(status=0) & Q(tags__icontains=TAG))[:NUM] return article_list return cls.objects.filter(status=0)[:NUM] @classmethod def get_all_tags_list(cls): """ A simple classmethod. Use Article.get_all_tags_list() to get all articles' tags list. """ all_tags_list = [] # obj_list = cls.objects.filter(status=0).order_by('-update_time') obj_list = Article.objects.all() for obj in obj_list: all_tags_list = all_tags_list + obj.tags_list() # for tag in obj.tags.split(','): # all_tags_list.append(tag) return all_tags_list @classmethod def get_recently_articles(cls, num): """ A simple classmethod. Use Article.get_recently_articles(RECENTLY_ARTICLES_NUM) to get recently(RECENTLY_ARTICLES_NUM) articles. """ return cls.objects.values('title', 'view_times', 'update_time', 'author')\ .filter(status=0).order_by('-update_time')[:num] @classmethod def get_hots_articles(cls, num): """ A simple classmethod. Use Article.get_hots_articles(HOT_ARTICLES_NUM) to get hot(HOT_ARTICLES_NUM) articles. """ return cls.objects.values('id', 'title', 'view_times', 'update_time', 'author').\ filter(status=0).order_by('-view_times' )[:num] class Meta: ordering = ['-is_top', '-update_time', '-create_time'] verbose_name_plural = verbose_name = _(u"Article")
class Project(ProjectMixin, models.Model): """ """ objects = ProjectManager() __original_label_config = None title = models.CharField( _('title'), null=True, blank=True, default='', max_length=settings.PROJECT_TITLE_MAX_LEN, help_text= f'Project name. Must be between {settings.PROJECT_TITLE_MIN_LEN} and {settings.PROJECT_TITLE_MAX_LEN} characters long.', validators=[ MinLengthValidator(settings.PROJECT_TITLE_MIN_LEN), MaxLengthValidator(settings.PROJECT_TITLE_MAX_LEN) ]) description = models.TextField(_('description'), blank=True, null=True, default='', help_text='Project description') organization = models.ForeignKey('organizations.Organization', on_delete=models.CASCADE, related_name='projects', null=True) label_config = models.TextField( _('label config'), blank=True, null=True, default='<View></View>', help_text= 'Label config in XML format. See more about it in documentation') expert_instruction = models.TextField( _('expert instruction'), blank=True, null=True, default='', help_text='Labeling instructions in HTML format') show_instruction = models.BooleanField( _('show instruction'), default=False, help_text='Show instructions to the annotator before they start') show_skip_button = models.BooleanField( _('show skip button'), default=True, help_text= 'Show a skip button in interface and allow annotators to skip the task' ) enable_empty_annotation = models.BooleanField( _('enable empty annotation'), default=True, help_text='Allow annotators to submit empty annotations') show_annotation_history = models.BooleanField( _('show annotation history'), default=False, help_text='Show annotation history to annotator') show_collab_predictions = models.BooleanField( _('show predictions to annotator'), default=True, help_text='If set, the annotator can view model predictions') evaluate_predictions_automatically = models.BooleanField( _('evaluate predictions automatically'), default=False, help_text='Retrieve and display predictions when loading a task') token = models.CharField(_('token'), max_length=256, default=create_hash, null=True, blank=True) result_count = models.IntegerField( _('result count'), default=0, help_text='Total results inside of annotations counter') color = models.CharField(_('color'), max_length=16, default='#FFFFFF', null=True, blank=True) created_by = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='created_projects', on_delete=models.SET_NULL, null=True, verbose_name=_('created by')) maximum_annotations = models.IntegerField( _('maximum annotation number'), default=1, help_text='Maximum number of annotations for one task. ' 'If the number of annotations per task is equal or greater ' 'to this value, the task is completed (is_labeled=True)') min_annotations_to_start_training = models.IntegerField( _('min_annotations_to_start_training'), default=10, help_text= 'Minimum number of completed tasks after which model training is started' ) control_weights = JSONField(_('control weights'), null=True, default=dict, help_text='Weights for control tags') model_version = models.TextField( _('model version'), blank=True, null=True, default='', help_text='Machine learning model version') data_types = JSONField(_('data_types'), default=dict, null=True) is_draft = models.BooleanField( _('is draft'), default=False, help_text='Whether or not the project is in the middle of being created' ) is_published = models.BooleanField( _('published'), default=False, help_text='Whether or not the project is published to annotators') created_at = models.DateTimeField(_('created at'), auto_now_add=True) updated_at = models.DateTimeField(_('updated at'), auto_now=True) SEQUENCE = 'Sequential sampling' UNIFORM = 'Uniform sampling' UNCERTAINTY = 'Uncertainty sampling' SAMPLING_CHOICES = (( SEQUENCE, 'Tasks are ordered by Data manager ordering' ), (UNIFORM, 'Tasks are chosen randomly'), ( UNCERTAINTY, 'Tasks are chosen according to model uncertainty scores (active learning mode)' )) sampling = models.CharField(max_length=100, choices=SAMPLING_CHOICES, null=True, default=SEQUENCE) show_ground_truth_first = models.BooleanField(_('show ground truth first'), default=True) show_overlap_first = models.BooleanField(_('show overlap first'), default=True) overlap_cohort_percentage = models.IntegerField( _('overlap_cohort_percentage'), default=100) task_data_login = models.CharField( _('task_data_login'), max_length=256, blank=True, null=True, help_text='Task data credentials: login') task_data_password = models.CharField( _('task_data_password'), max_length=256, blank=True, null=True, help_text='Task data credentials: password') def __init__(self, *args, **kwargs): super(Project, self).__init__(*args, **kwargs) self.__original_label_config = self.label_config self.__maximum_annotations = self.maximum_annotations self.__overlap_cohort_percentage = self.overlap_cohort_percentage # TODO: once bugfix with incorrect data types in List # logging.warning('! Please, remove code below after patching of all projects (extract_data_types)') if self.label_config is not None: if self.data_types != extract_data_types(self.label_config): self.data_types = extract_data_types(self.label_config) @property def num_tasks(self): return self.tasks.count() def get_current_predictions(self): return Prediction.objects.filter( Q(task__project=self.id) & Q(model_version=self.model_version)) @property def num_predictions(self): return self.get_current_predictions().count() @property def num_annotations(self): return Annotation.objects.filter( Q(task__project=self) & Q_finished_annotations & Q(ground_truth=False)).count() @property def has_predictions(self): return self.get_current_predictions().exists() @property def has_any_predictions(self): return Prediction.objects.filter(Q(task__project=self.id)).exists() @property def business(self): return self.created_by.business @property def is_private(self): return None @property def has_storages(self): return hasattr( self, 'storages' ) and self.storages is not None and self.storages.count() > 0 @property def secure_mode(self): return False @property def one_object_in_label_config(self): return len(self.data_types) <= 1 @property def only_undefined_field(self): return self.one_object_in_label_config and self.summary.common_data_columns and self.summary.common_data_columns[ 0] == settings.DATA_UNDEFINED_NAME @property def get_labeled_count(self): return self.tasks.filter(is_labeled=True).count() @property def get_collected_count(self): return self.tasks.count() @property def get_total_possible_count(self): """ Tasks has overlap - how many tc should be accepted possible count = sum [ t.overlap for t in tasks] :return: N int total amount of Annotations that should be submitted """ if self.tasks.count() == 0: return 0 return self.tasks.aggregate(Sum('overlap'))['overlap__sum'] @property def get_available_for_labeling(self): return self.get_collected_count - self.get_labeled_count @property def need_annotators(self): return self.maximum_annotations - self.num_annotators @classmethod def find_by_invite_url(cls, url): token = url.strip('/').split('/')[-1] if len(token): return Project.objects.get(token=token) else: raise KeyError(f'Can\'t find Project by invite URL: {url}') def reset_token(self): self.token = create_hash() self.save() def add_collaborator(self, user): created = False with transaction.atomic(): try: ProjectMember.objects.get(user=user, project=self) except ProjectMember.DoesNotExist: ProjectMember.objects.create(user=user, project=self) created = True else: logger.debug( f'Project membership {self} for user {user} already exists' ) return created def has_collaborator(self, user): return ProjectMember.objects.filter(user=user, project=self).exists() def has_collaborator_enabled(self, user): membership = ProjectMember.objects.filter(user=user, project=self) return membership.exists() and membership.first().enabled def update_tasks_states(self, maximum_annotations_changed, overlap_cohort_percentage_changed, tasks_number_changed): # if only maximum annotations parameter is tweaked if maximum_annotations_changed and not overlap_cohort_percentage_changed: tasks_with_overlap = self.tasks.filter(overlap__gt=1) if tasks_with_overlap.exists(): # if there is a part with overlaped tasks, affect only them tasks_with_overlap.update(overlap=self.maximum_annotations) else: # otherwise affect all tasks self.tasks.update(overlap=self.maximum_annotations) # if cohort slider is tweaked elif overlap_cohort_percentage_changed and self.maximum_annotations > 1: self._rearrange_overlap_cohort() # if adding/deleting tasks and cohort settings are applied elif tasks_number_changed and self.overlap_cohort_percentage < 100 and self.maximum_annotations > 1: self._rearrange_overlap_cohort() if maximum_annotations_changed or overlap_cohort_percentage_changed: bulk_update_stats_project_tasks( self.tasks.filter( Q(annotations__isnull=False) & Q(annotations__ground_truth=False))) def _rearrange_overlap_cohort(self): tasks_with_overlap = self.tasks.filter(overlap__gt=1) tasks_with_overlap_count = tasks_with_overlap.count() total_tasks = self.tasks.count() new_tasks_with_overlap_count = int(self.overlap_cohort_percentage / 100 * total_tasks + 0.5) if tasks_with_overlap_count > new_tasks_with_overlap_count: # TODO: warn if we try to reduce current cohort that is already labeled with overlap reduce_by = tasks_with_overlap_count - new_tasks_with_overlap_count reduce_tasks = sample_query(tasks_with_overlap, reduce_by) reduce_tasks.update(overlap=1) reduced_tasks_ids = reduce_tasks.values_list('id', flat=True) tasks_with_overlap.exclude(id__in=reduced_tasks_ids).update( overlap=self.maximum_annotations) elif tasks_with_overlap_count < new_tasks_with_overlap_count: increase_by = new_tasks_with_overlap_count - tasks_with_overlap_count tasks_without_overlap = self.tasks.filter(overlap=1) increase_tasks = sample_query(tasks_without_overlap, increase_by) increase_tasks.update(overlap=self.maximum_annotations) tasks_with_overlap.update(overlap=self.maximum_annotations) def remove_tasks_by_file_uploads(self, file_upload_ids): self.tasks.filter(file_upload_id__in=file_upload_ids).delete() def advance_onboarding(self): """ Move project to next onboarding step """ po_qs = self.steps_left.order_by('step__order') count = po_qs.count() if count: po = po_qs.first() po.finished = True po.save() return count != 1 def created_at_prettify(self): return self.created_at.strftime("%d %b %Y %H:%M:%S") def onboarding_step_finished(self, step): """ Mark specific step as finished """ pos = ProjectOnboardingSteps.objects.get(code=step) po = ProjectOnboarding.objects.get(project=self, step=pos) po.finished = True po.save() return po def data_types_json(self): return json.dumps(self.data_types) def available_data_keys(self): return sorted(list(self.data_types.keys())) @classmethod def validate_label_config(cls, config_string): validate_label_config(config_string) def validate_config(self, config_string): self.validate_label_config(config_string) if not hasattr(self, 'summary'): return # validate data columns consistency fields_from_config = get_all_object_tag_names(config_string) if not fields_from_config: logger.debug(f'Data fields not found in labeling config') return fields_from_data = set(self.summary.common_data_columns) fields_from_data.discard(settings.DATA_UNDEFINED_NAME) if fields_from_data and not fields_from_config.issubset( fields_from_data): different_fields = list( fields_from_config.difference(fields_from_data)) raise ValidationError( f'These fields are not present in the data: {",".join(different_fields)}' ) # validate annotations consistency annotations_from_config = set( get_all_control_tag_tuples(config_string)) if not annotations_from_config: logger.debug(f'Annotation schema is not found in config') return annotations_from_data = set(self.summary.created_annotations) if annotations_from_data and not annotations_from_data.issubset( annotations_from_config): different_annotations = list( annotations_from_data.difference(annotations_from_config)) diff_str = [] for ann_tuple in different_annotations: from_name, to_name, t = ann_tuple.split('|') diff_str.append( f'{self.summary.created_annotations[ann_tuple]} ' f'with from_name={from_name}, to_name={to_name}, type={t}') diff_str = '\n'.join(diff_str) raise ValidationError( f'Created annotations are incompatible with provided labeling schema, ' f'we found:\n{diff_str}') # validate labels consistency labels_from_config = get_all_labels(config_string) created_labels = self.summary.created_labels for control_tag_from_data, labels_from_data in created_labels.items(): # Check if labels created in annotations, and their control tag has been removed if labels_from_data and control_tag_from_data not in labels_from_config: raise ValidationError( f'There are {sum(labels_from_data.values(), 0)} annotation(s) created with tag ' f'"{control_tag_from_data}", you can\'t remove it') labels_from_config_by_tag = set( labels_from_config[control_tag_from_data]) if not set(labels_from_data).issubset( set(labels_from_config_by_tag)): different_labels = list( set(labels_from_data).difference( labels_from_config_by_tag)) diff_str = '\n'.join(f'{l} ({labels_from_data[l]} annotations)' for l in different_labels) raise ValidationError( f'These labels still exist in annotations:\n{diff_str}') def _label_config_has_changed(self): return self.label_config != self.__original_label_config def delete_predictions(self): predictions = Prediction.objects.filter(task__project=self) count = predictions.count() predictions.delete() return {'deleted_predictions': count} def get_updated_weights(self): outputs = parse_config(self.label_config) control_weights = {} exclude_control_types = ('Filter', ) for control_name in outputs: control_type = outputs[control_name]['type'] if control_type in exclude_control_types: continue control_weights[control_name] = { 'overall': 1.0, 'type': control_type, 'labels': { label: 1.0 for label in outputs[control_name].get('labels', []) } } return control_weights def save(self, *args, recalc=True, **kwargs): exists = True if self.pk else False if self.label_config and (self._label_config_has_changed() or not exists or not self.control_weights): self.control_weights = self.get_updated_weights() super(Project, self).save(*args, **kwargs) project_with_config_just_created = not exists and self.pk and self.label_config if self._label_config_has_changed( ) or project_with_config_just_created: self.data_types = extract_data_types(self.label_config) if self._label_config_has_changed(): self.__original_label_config = self.label_config if not exists: steps = ProjectOnboardingSteps.objects.all() objs = [ ProjectOnboarding(project=self, step=step) for step in steps ] ProjectOnboarding.objects.bulk_create(objs) # argument for recalculate project task stats if recalc: self.update_tasks_states( maximum_annotations_changed=self.__maximum_annotations != self.maximum_annotations, overlap_cohort_percentage_changed=self. __overlap_cohort_percentage != self.overlap_cohort_percentage, tasks_number_changed=False) self.__maximum_annotations = self.maximum_annotations self.__overlap_cohort_percentage = self.overlap_cohort_percentage def get_member_ids(self): if hasattr(self, 'team_link'): # project has defined team scope # TODO: avoid checking team but rather add all project members when creating a project return self.team_link.team.members.values_list('user', flat=True) else: from users.models import User # TODO: may want to return all users from organization return User.objects.none() def has_team_user(self, user): return hasattr(self, 'team_link') and self.team_link.team.has_user(user) def annotators(self): """ Annotators connected to this project including team members """ from users.models import User member_ids = self.get_member_ids() team_members = User.objects.filter(id__in=member_ids).order_by('email') # add members from invited projects project_member_ids = self.members.values_list('user__id', flat=True) project_members = User.objects.filter(id__in=project_member_ids) annotators = team_members | project_members # set annotator.team_member=True if annotator is not an invited user annotators = annotators.annotate(team_member=Case( When(id__in=project_member_ids, then=Value(False)), default=Value(True), output_field=BooleanField(), )) return annotators def annotators_with_annotations(self, min_count=500): """ Annotators with annotation number > min_number :param min_count: minimal annotation number to leave an annotators :return: filtered annotators """ annotators = self.annotators() q = Q( annotations__task__project=self) & Q_task_finished_annotations & Q( annotations__ground_truth=False) annotators = annotators.annotate( annotation_count=Count('annotations', filter=q, distinct=True)) return annotators.filter(annotation_count__gte=min_count) def labeled_tasks(self): return self.tasks.filter(is_labeled=True) def has_annotations(self): from tasks.models import Annotation # prevent cycling imports return Annotation.objects.filter( Q(task__project=self) & Q(ground_truth=False)).count() > 0 # [TODO] this should be a template tag or something like this @property def label_config_line(self): c = self.label_config return config_line_stipped(c) def get_sample_task(self, label_config=None): config = label_config or self.label_config task, _, _ = get_sample_task(config) return task def eta(self): """ Show eta for project to be finished eta = avg task annotations finish time * remain annotations task has overlap = amount of task annotations to consider as finished (is_labeled) remain annotations = sum ( task annotations to be done to fulfill each unfinished task overlap) :return: time in seconds """ # finished tasks * overlap finished_tasks = Task.objects.filter(project=self.id, is_labeled=True) # one could make more than need to overlap min_n_finished_annotations = sum([ft.overlap for ft in finished_tasks]) annotations_unfinished_tasks = Annotation.objects.filter( task__project=self.id, task__is_labeled=False, ground_truth=False, result__isnull=False).count() # get minimum remain annotations total_annotations_needed = self.get_total_possible_count annotations_remain = total_annotations_needed - min_n_finished_annotations - annotations_unfinished_tasks # get average time of all finished TC finished_annotations = Annotation.objects.filter( Q(task__project=self.id) & Q(ground_truth=False), result__isnull=False).values('lead_time') avg_lead_time = finished_annotations.aggregate( avg_lead_time=Avg('lead_time'))['avg_lead_time'] if avg_lead_time is None: return None return avg_lead_time * annotations_remain def finished(self): return not self.tasks.filter(is_labeled=False).exists() def annotations_lead_time(self): annotations = Annotation.objects.filter( Q(task__project=self.id) & Q(ground_truth=False)) return annotations.aggregate( avg_lead_time=Avg('lead_time'))['avg_lead_time'] @staticmethod def django_settings(): return settings @staticmethod def max_tasks_file_size(): return settings.TASKS_MAX_FILE_SIZE def get_control_tags_from_config(self): return parse_config(self.label_config) def get_parsed_config(self): return parse_config(self.label_config) def __str__(self): return f'{self.title} (id={self.id})' or _( "Business number %d") % self.pk class Meta: db_table = 'project'
class UserForm(AbstractParticipantForm): """ Form for user profiles """ is_active = forms.BooleanField( label=_("Active"), required=False, help_text=_("Whether this user is active, disable to remove access.")) email = forms.CharField(max_length=256, label=_("Email"), help_text=_("Email address and login.")) password = forms.CharField( widget=forms.PasswordInput, validators=[MinLengthValidator(8)], label=_("Password"), help_text=_("Password used to log in (minimum of 8 characters).")) new_password = forms.CharField( widget=forms.PasswordInput, validators=[MinLengthValidator(8)], required=False, label=_("New password"), help_text=_( "Password used to login (minimum of 8 characters, optional).")) confirm_password = forms.CharField(widget=forms.PasswordInput, required=False, label=_("Confirm password")) change_password = forms.BooleanField( label=_("Require change"), required=False, help_text=_("Whether user must change password on next login.")) rooms = forms.ModelMultipleChoiceField( label=_("Rooms (chatting)"), queryset=Room.objects.all(), required=False, help_text=_("Chat rooms which this user can chat in.")) manage_rooms = forms.ModelMultipleChoiceField( label=_("Rooms (manage)"), queryset=Room.objects.all(), required=False, help_text=_("Chat rooms which this user can manage.")) def __init__(self, *args, **kwargs): super(UserForm, self).__init__(*args, **kwargs) if self.user.get_org(): org_rooms = Room.get_all(self.user.get_org()).order_by('name') self.fields['rooms'].queryset = org_rooms self.fields['manage_rooms'].queryset = org_rooms def clean(self): cleaned_data = super(UserForm, self).clean() password = cleaned_data.get('password', None) or cleaned_data.get( 'new_password', None) if password: confirm_password = cleaned_data.get('confirm_password', '') if password != confirm_password: self.add_error('confirm_password', _("Passwords don't match.")) class Meta: model = User exclude = ()
class AgencyProfile(TimeStampedModel): NUMBER_OF_SPECIALISTS = ((1, '<5'), (2, '5-10'), (3, '10-20'), (4, '>20')) user = models.OneToOneField(User, related_name='agency_profile', on_delete=models.CASCADE) company_logo = models.ImageField(_('Logo'), upload_to='company_logos', blank=True, null=True) company_name = models.CharField(_('Company name'), max_length=255, blank=False) number_of_specialists = models.IntegerField( _('Number of available specialists'), choices=NUMBER_OF_SPECIALISTS, null=True) communication_languages = MultiSelectField(_('Communication languages'), choices=LANGUAGES, blank=False) company_description = models.TextField( _('Description'), blank=True, validators=[ MinLengthValidator(100, message=_("Please enter minimum 100 symbols")), MaxLengthValidator(2000, message=_("Please enter maximun 2000 symbols")) ]) founded = models.DateField(_('Founded'), blank=False) company_type = models.CharField(_('Company type'), max_length=255, blank=False) average_hourly_rate = models.OneToOneField( 'AverageHourlyRate', related_name='average_hourly_rate', on_delete=models.CASCADE, blank=True, null=True) specialization = models.ManyToManyField( 'Specialization', related_name='agency_specilaizations', blank=False) technologies = models.ManyToManyField('Technology', related_name='agency_technologies', blank=False) company_adress = models.CharField(_('Adress'), max_length=255, blank=False) postal_code = models.CharField(_('Postal Code'), max_length=255, blank=False) city = models.CharField(_('City'), max_length=255, blank=False) country = models.CharField(_('Country'), choices=COUNTRY_CHOICES, max_length=255, blank=False, db_index=True) company_website = models.CharField(_('Website'), max_length=255) phone_number = models.CharField(_('Phone number'), max_length=16, blank=False) objects = AgencyManager() class Meta: verbose_name = 'agency profile' verbose_name_plural = 'agency profiles' def __str__(self): return self.company_name def get_contact_persons_email(self): contact_persons = self.contact_persons.all() return [cp.email for cp in contact_persons] def activate_membership(self): self.user.activate_membership()
class Ingredient(AbstractSubmissionModel, AbstractLicenseModel, models.Model): """ An ingredient, with some approximate nutrition values """ objects = SubmissionManager() """Custom manager""" ENERGY_APPROXIMATION = 15 """ How much the calculated energy from protein, etc. can deviate from the energy amount given (in percent). """ # Metaclass to set some other properties class Meta: ordering = [ "name", ] # Meta data language = models.ForeignKey(Language, verbose_name=_('Language'), editable=False, on_delete=models.CASCADE) creation_date = models.DateField(_('Date'), auto_now_add=True) update_date = models.DateField(_('Date'), auto_now=True, blank=True, editable=False) # Product infos name = models.CharField(max_length=200, verbose_name=_('Name'), validators=[MinLengthValidator(3)]) energy = models.IntegerField(verbose_name=_('Energy'), help_text=_('In kcal per 100g')) protein = models.DecimalField( decimal_places=3, max_digits=6, verbose_name=_('Protein'), help_text=_('In g per 100g of product'), validators=[MinValueValidator(0), MaxValueValidator(100)]) carbohydrates = models.DecimalField( decimal_places=3, max_digits=6, verbose_name=_('Carbohydrates'), help_text=_('In g per 100g of product'), validators=[MinValueValidator(0), MaxValueValidator(100)]) carbohydrates_sugar = models.DecimalField( decimal_places=3, max_digits=6, blank=True, null=True, verbose_name=_('Sugar content in carbohydrates'), help_text=_('In g per 100g of product'), validators=[MinValueValidator(0), MaxValueValidator(100)]) fat = models.DecimalField( decimal_places=3, max_digits=6, verbose_name=_('Fat'), help_text=_('In g per 100g of product'), validators=[MinValueValidator(0), MaxValueValidator(100)]) fat_saturated = models.DecimalField( decimal_places=3, max_digits=6, blank=True, null=True, verbose_name=_('Saturated fat content in fats'), help_text=_('In g per 100g of product'), validators=[MinValueValidator(0), MaxValueValidator(100)]) fibres = models.DecimalField( decimal_places=3, max_digits=6, blank=True, null=True, verbose_name=_('Fibres'), help_text=_('In g per 100g of product'), validators=[MinValueValidator(0), MaxValueValidator(100)]) sodium = models.DecimalField( decimal_places=3, max_digits=6, blank=True, null=True, verbose_name=_('Sodium'), help_text=_('In g per 100g of product'), validators=[MinValueValidator(0), MaxValueValidator(100)]) code = models.CharField(max_length=200, null=True, blank=True, db_index=True) """Internal ID of the source database, e.g. a barcode or similar""" source_name = models.CharField(max_length=200, null=True, blank=True) """Name of the source, such as Open Food Facts""" source_url = models.URLField(verbose_name=_('Link'), help_text=_('Link to product'), blank=True, null=True) """URL of the product at the source""" last_imported = models.DateTimeField(_('Date'), auto_now_add=True, null=True, blank=True) common_name = models.CharField(max_length=200, null=True, blank=True) category = models.ForeignKey(IngredientCategory, verbose_name=_('Category'), on_delete=models.CASCADE, null=True, blank=True) brand = models.CharField(max_length=200, verbose_name=_('Brand name of product'), null=True, blank=True) # # Django methods # def get_absolute_url(self): """ Returns the canonical URL to view this object. Since some names consist of only non-ascii characters (e.g. 감자깡), the resulting slug would be empty and no URL would match. In that case, use the regular URL with only the ID. """ slug = slugify(self.name) if not slug: return reverse('nutrition:ingredient:view', kwargs={'id': self.id}) else: return reverse('nutrition:ingredient:view', kwargs={ 'id': self.id, 'slug': slug }) def clean(self): """ Do a very broad sanity check on the nutritional values according to the following rules: - 1g of protein: 4kcal - 1g of carbohydrates: 4kcal - 1g of fat: 9kcal The sum is then compared to the given total energy, with ENERGY_APPROXIMATION percent tolerance. """ # Note: calculations in 100 grams, to save us the '/100' everywhere energy_protein = 0 if self.protein: energy_protein = self.protein * ENERGY_FACTOR['protein']['kg'] energy_carbohydrates = 0 if self.carbohydrates: energy_carbohydrates = self.carbohydrates * ENERGY_FACTOR[ 'carbohydrates']['kg'] energy_fat = 0 if self.fat: # TODO: for some reason, during the tests the fat value is not # converted to decimal (django 1.9) energy_fat = Decimal(self.fat * ENERGY_FACTOR['fat']['kg']) energy_calculated = energy_protein + energy_carbohydrates + energy_fat # Compare the values, but be generous if self.energy: energy_upper = self.energy * ( 1 + (self.ENERGY_APPROXIMATION / Decimal(100.0))) energy_lower = self.energy * ( 1 - (self.ENERGY_APPROXIMATION / Decimal(100.0))) if not ((energy_upper > energy_calculated) and (energy_calculated > energy_lower)): raise ValidationError( _('The total energy ({energy}kcal) is not the approximate sum of the ' 'energy provided by protein, carbohydrates and fat ({energy_calculated}kcal ' '+/-{energy_approx}%)'.format( energy=self.energy, energy_calculated=energy_calculated, energy_approx=self.ENERGY_APPROXIMATION))) def save(self, *args, **kwargs): """ Reset the cache """ super(Ingredient, self).save(*args, **kwargs) cache.delete(cache_mapper.get_ingredient_key(self.id)) def __str__(self): """ Return a more human-readable representation """ return self.name def __eq__(self, other): """ Compare ingredients based on their values, not like django on their PKs """ logger.debug( 'Overwritten behaviour: comparing ingredients on values, not PK.') equal = True if isinstance(other, self.__class__): for i in self._meta.fields: if (hasattr(self, i.name) and hasattr(other, i.name) and (getattr(self, i.name, None) != getattr( other, i.name, None))): equal = False else: equal = False return equal def __hash__(self): """ Define a hash function This is rather unnecessary, but it seems that newer versions of django have a problem when the __eq__ function is implemented, but not the __hash__ one. Returning hash(pk) is also django's default. :return: hash(pk) """ return hash(self.pk) # # Own methods # def compare_with_database(self): """ Compares the current ingredient with the version saved in the database. If the current object has no PK, returns false """ if not self.pk: return False ingredient = Ingredient.objects.get(pk=self.pk) if self != ingredient: return False else: return True def send_email(self, request): """ Sends an email after being successfully added to the database (for user submitted ingredients only) """ try: user = User.objects.get(username=self.license_author) except User.DoesNotExist: return if self.license_author and user.email: translation.activate( user.userprofile.notification_language.short_name) url = request.build_absolute_uri(self.get_absolute_url()) subject = _( 'Ingredient was successfully added to the general database') context = { 'ingredient': self.name, 'url': url, 'site': Site.objects.get_current().domain } message = render_to_string('ingredient/email_new.tpl', context) mail.send_mail(subject, message, settings.WGER_SETTINGS['EMAIL_FROM'], [user.email], fail_silently=True) def set_author(self, request): if request.user.has_perm('nutrition.add_ingredient'): self.status = Ingredient.STATUS_ACCEPTED if not self.license_author: self.license_author = request.get_host().split(':')[0] else: if not self.license_author: self.license_author = request.user.username # Send email to administrator subject = _('New user submitted ingredient') message = _( """The user {0} submitted a new ingredient "{1}".""".format( request.user.username, self.name)) mail.mail_admins(subject, message, fail_silently=True) def get_owner_object(self): """ Ingredient has no owner information """ return False @property def energy_kilojoule(self): """ returns kilojoules for current ingredient, 0 if energy is uninitialized """ if self.energy: return Decimal(self.energy * 4.184).quantize(TWOPLACES) else: return 0
class DomesticComplaint(models.Model): doc_id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, verbose_name='Complaint ID') #pk # own info of customer user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True) o_name = models.CharField( max_length=128, verbose_name='Complainant Name') #complainant name o_email = models.EmailField( max_length=64, verbose_name='Complainant Email') #complainant email o_no = PhoneNumberField(verbose_name='Complainant No') #complainant no o_state = models.CharField( max_length=32, verbose_name='Complainant Name') #complainant state o_city = models.CharField( max_length=32, verbose_name='Complainant City') #complainant city o_adds = models.TextField( max_length=256, verbose_name='Complainant Address') #complainant address gender = models.CharField(max_length=8, choices=GENDER_CHOICES, default='MALE', verbose_name='Gender') #complainant gender acc_name = models.CharField(max_length=128, verbose_name='Accused Name') #accused name acc_adds = models.TextField( max_length=256, blank=True, null=True, verbose_name='Accused address') #accused address acc_state = models.CharField(max_length=32, verbose_name='Accused state') #accused state acc_city = models.CharField(max_length=32, verbose_name='Accused city') #accused city acc_email = models.EmailField(blank=True, null=True, verbose_name='Accused Email') #accused email acc_no = PhoneNumberField(blank=True, null=True, verbose_name='Accused contact No') #accused no acc_gender = models.CharField( max_length=8, choices=GENDER_CHOICES, default='MALE', verbose_name='Accused gender') #accused gender case_pending_a = models.CharField( max_length=4, choices=ICC_CHOICES, default='YES', verbose_name='case pending at any other court' ) #case pending at any other court case_pending_w = models.CharField( max_length=4, choices=ICC_CHOICES, default='YES', verbose_name='case pending at any women association court' ) #case pending at any women association court c_description = models.TextField(max_length=4056, verbose_name='Complainant Description', validators=[MinLengthValidator(30) ]) #complaint discription c_document = models.FileField(upload_to='domestic/', null=True, blank=True, verbose_name='Complaint related documents') c_filed = models.DateField(auto_now_add=True, verbose_name='Complaint filed date') c_amt = models.DecimalField(decimal_places=2, max_digits=10, verbose_name='Complaint Amount', null=True, blank=True) p_date = models.DateTimeField(null=True, verbose_name='Payment Date', blank=True) p_status = models.BooleanField(verbose_name='Payment Status', default=0) new_cid = models.CharField(max_length=128, null=True, blank=True, verbose_name='Order ID') txn_id = models.CharField(max_length=128, null=True, blank=True, verbose_name='Transaction ID') update_flag = models.BooleanField(verbose_name='Information Updated', default=0) admin_reply = models.TextField(max_length=4056, verbose_name='Update Complaint Status', null=True, blank=True) admin_document = models.FileField(upload_to='admin/domestic/', null=True, blank=True, verbose_name='Attach documents') def __str__(self): return self.o_name
class CandidateProfile(TimeStampedModel): user = models.OneToOneField(User, related_name='candidate_profile', on_delete=models.CASCADE) first_name = models.CharField( _('First name'), max_length=255, blank=False, error_messages={"max_length": _("Please enter maximum 255 symbols")}) last_name = models.CharField( _('Last name'), max_length=255, blank=False, error_messages={"max_length": _("Please enter maximum 255 symbols")}) nationality = models.CharField(_('Nationality'), max_length=255, blank=False) image = models.ImageField(_('Profile image'), upload_to='candidate_images', blank=True, null=True) job_position = models.CharField(_('Job position'), max_length=255, blank=False) cover_letter = models.TextField( _('Cover letter'), validators=[ MinLengthValidator( 255, message=_("Please enter between 255 and 1000 symbols")), MaxLengthValidator( 1000, message=_("Please enter between 255 and 1000 symbols")), ], blank=True, null=True) hourly_rate = models.OneToOneField(HourlyRate, related_name='hourly_rate', on_delete=models.CASCADE, blank=True, null=True) monthly_rate = models.OneToOneField(MonthlyRate, related_name='monthly_rate', on_delete=models.CASCADE, blank=True, null=True) adress = models.CharField(_('Adress'), max_length=255, blank=False) postal_code = models.CharField(_('Postal Code'), max_length=255, blank=False) city = models.CharField(_('City'), max_length=255, blank=False) country = models.CharField(_('Country'), choices=COUNTRY_CHOICES, max_length=255, blank=False, db_index=True) date_of_birth = models.DateField(_('Date of birth'), blank=False) experience = models.IntegerField(_('Experience'), choices=EXPERIENCE, blank=False, db_index=True) experience_level = models.IntegerField( _('Experience level'), choices=EXPERIENCE_LVL, blank=False, db_index=True, ) job_type = MultiSelectField(_('Job type'), choices=JOB_TYPE, blank=False, db_index=True) specialization = models.ManyToManyField( 'Specialization', related_name='candidate_specilaizations', blank=False) technologies = models.ManyToManyField('Technology', related_name='technologies', blank=False, db_index=True) communication_languages = MultiSelectField(_('Communication Language'), choices=LANGUAGES, blank=False) phone_number = models.CharField(_('Phone number'), max_length=16, blank=False) email = models.EmailField(_('Email address'), blank=False) linkedin_url = models.URLField(_('LinkedIn Profile'), blank=True, null=True) is_identified = models.BooleanField(_('Is identified'), default=False) def __str__(self): return self.user.email @cached_property def full_name(self): return "{} {}".format(self.first_name, self.last_name)
class User(AbstractBaseUser, PermissionsMixin, TimeStampedModel): class Meta: verbose_name = _("User") verbose_name_plural = _("Users") email = models.EmailField(_('Email address'), default="", unique=True, blank=True) pin = models.PositiveIntegerField( _("PIN"), default=get_random_pin, validators=[MinLengthValidator(6)], ) first_name = models.CharField(_('First name'), max_length=30, default="", blank=True) last_name = models.CharField(_('Last name'), max_length=30, default="", blank=True) birthdate = models.DateField(verbose_name=_("Birth Date"), null=True) is_staff = models.BooleanField(_('Is Staff'), default=False) is_active = models.BooleanField(_('Is Active'), default=False) is_verified = models.BooleanField(_('Is Verified'), default=False) is_email = models.BooleanField( _('Is Email Verified'), default=False, help_text=_( "Email verification is important to keep email address verified")) img = models.ImageField(verbose_name=_("Avatar"), upload_to=settings.DEFAULT_USER_FOLDER, blank=True, default=settings.DEFAULT_USER_AVATAR) address = models.TextField( verbose_name=_("Address"), blank=True, ) mobile = models.CharField(verbose_name=_("Mobile"), max_length=15, blank=True, validators=[_PHONE_REGEX]) telephone = models.CharField(verbose_name=_("Telephone"), max_length=15, blank=True, validators=[_PHONE_REGEX]) fax = models.CharField(verbose_name=_("Fax"), max_length=15, blank=True, validators=[_PHONE_REGEX]) username_validator = ASCIIUsernameValidator() username = models.CharField( _('Username'), max_length=150, unique=True, help_text= _('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.' ), validators=[username_validator], error_messages={ 'unique': _("A user with that username already exists."), }, ) objects = UserManager() EMAIL_FIELD = 'email' USERNAME_FIELD = 'username' REQUIRED_FIELDS = ['email'] @property def date_joined(self): return self.created def get_full_name(self): """ Returns the first_name plus the last_name, with a space in between. """ full_name = f'{self.first_name} {self.last_name}' if self.first_name and self.last_name else self.username return full_name.strip() get_full_name.short_description = _("Full Name") def get_full_name_slug(self): return "{}-{}".format(self.get_full_name().replace(' ', '-'), self.pin) @property def full_name(self): return self.get_full_name() def get_short_name(self): """Returns the short name for the user.""" return f"{self.first_name} {self.last_name[:1]}" if self.first_name else self.username get_short_name.short_description = _("Short Name") def save(self, *args, **kwargs): super(User, self).save(*args, **kwargs) def __str__(self): return self.get_full_name() def get_dict(self): return { "img": self.img if self.img else settings.DEFAULT_USER_AVATAR, "username": self.username, "first_name": self.first_name, "last_name": self.last_name, "full_name": self.get_full_name(), "email": self.email, "created": self.created.isoformat() if self.created else None, }
class User(AbstractBaseUser, PermissionsMixin): """Custom user model that support using phone number instead of username""" EDUCATION_CHOICES = [ ("Associate degree", "Associate degree"), ("Bachelor's degree", "Bachelor's degree"), ("Master's degree", "Master's degree"), ("Doctoral degree", "Doctoral degree"), ] EMPLOYMENT_CHOICES = [ ("Employed", "Employed"), ("Unemployed", "Unemployed"), ("Contractor", "Contractor"), ("Student", "Student"), ] COVERAGE_CHOICES = [("Yes", "Yes"), ("No", "No"), ("Don't know", "Don't know")] phone_regex = RegexValidator( regex=r"^\+?1?\d{9,15}$", message="Phone number must be entered in the format: '+999999999'. \ Up to 15 digits allowed.", ) # PERSONAL INFO phone_number = models.CharField(_("phone number"), max_length=17, unique=True) email = models.EmailField(_("email address"), blank=True) name = models.CharField(max_length=255) first_name = models.CharField(_("first name"), max_length=30, blank=True) last_name = models.CharField(_("last name"), max_length=30, blank=True) age = models.PositiveSmallIntegerField( _("age"), validators=[MinValueValidator(18), MaxValueValidator(150)], blank=True, null=True, ) zipcode = models.CharField(_("zipcode"), max_length=5, validators=[MinLengthValidator(5)], blank=True) income = models.DecimalField(_("income"), max_digits=10, decimal_places=2, blank=True, null=True) savings = models.DecimalField(_("savings"), max_digits=10, decimal_places=2, blank=True, null=True) debt = models.DecimalField(_("debt"), max_digits=10, decimal_places=2, blank=True, null=True) education = models.CharField(_("education"), max_length=50, choices=EDUCATION_CHOICES, blank=True) employment = models.CharField(_("employment"), max_length=50, choices=EMPLOYMENT_CHOICES, blank=True) # SCORES score = models.ForeignKey("Score", on_delete=models.CASCADE, blank=True, null=True) # STUFF own_vehicle = models.BooleanField(default=False) own_pet = models.BooleanField(default=False) own_rent_house = models.BooleanField(default=False) # COVERAGES have_health_cover = models.CharField(_("health"), max_length=50, choices=COVERAGE_CHOICES, blank=True) have_vision_cover = models.CharField(_("vision"), max_length=50, choices=COVERAGE_CHOICES, blank=True) have_dental_cover = models.CharField(_("dental"), max_length=50, choices=COVERAGE_CHOICES, blank=True) have_life_cover = models.CharField(_("life"), max_length=50, choices=COVERAGE_CHOICES, blank=True) have_longtermdisability_cover = models.CharField(_("long term disability"), max_length=50, choices=COVERAGE_CHOICES, blank=True) have_shorttermdisability_cover = models.CharField( _("short term disability"), max_length=50, choices=COVERAGE_CHOICES, blank=True) have_accident_cover = models.CharField(_("accident"), max_length=50, choices=COVERAGE_CHOICES, blank=True) have_criticalillness_cover = models.CharField(_("critical illness"), max_length=50, choices=COVERAGE_CHOICES, blank=True) have_auto_cover = models.CharField(_("auto"), max_length=50, choices=COVERAGE_CHOICES, blank=True) have_homeowner_cover = models.CharField(_("homeowner"), max_length=50, choices=COVERAGE_CHOICES, blank=True) have_renters_cover = models.CharField(_("renters"), max_length=50, choices=COVERAGE_CHOICES, blank=True) have_pet_cover = models.CharField(_("pet"), max_length=50, choices=COVERAGE_CHOICES, blank=True) date_joined = models.DateTimeField(_("registered"), auto_now_add=True, null=True) is_active = models.BooleanField(default=True) is_staff = models.BooleanField(default=False) objects = UserManager() USERNAME_FIELD = "phone_number" def has_perm(self, perm, obj=None): "Does the user have a specific permission?" # Simplest possible answer: Yes, always return True def has_module_perms(self, app_label): "Does the user have permissions to view the app `app_label`?" # Simplest possible answer: Yes, always return True def get_full_name(self): """Returns the firstname plus the last_name, and a space in between.""" full_name = "%s %s" % (self.first_name, self.last_name) return full_name.strip() def get_short_name(self): """Returns the short name for the user.""" return self.first_name def calculate_score(self): """Initializes dummy score object for now.""" # TODO: Call make_user_score_metrics(user, products) to get score metrics overall_score = randint(0, 100) return Score( score_overall=overall_score, score_medical=randint(0, 100), score_income=randint(0, 100), score_stuff=randint(0, 100), score_liability=randint(0, 100), score_digital=randint(0, 100), content_overall="Your overall score of {} shows you're doing good." .format(overall_score), content_medical="You are underprotected in your medical category.", content_income= "We also think you're overprotected in your income category.", content_stuff="", content_liability="", content_digital="", )
class User(AbstractBaseUser, PermissionsMixin): """ User model. It inherits the basic structure of the Django user model. The username field is overwiritten with the email value. This model manage basic user iformation and legal items status. """ USERNAME_FIELD = 'email' avatar = models.ImageField( verbose_name=_('profile image'), max_length=255, blank=True, validators=[FileSizeValidator(4000)], ) first_name = models.CharField( verbose_name=_('name'), max_length=128, blank=False, validators=[ MinLengthValidator(3), ], error_messages={ 'min_length': 'El campo "Nombre" debe tener al menos %(limit_value)d ' 'caracteres (actualmente tiene %(show_value)d).' }) last_name = models.CharField( verbose_name=_('last name'), max_length=128, blank=False, validators=[ MinLengthValidator(3), ], error_messages={ 'min_length': 'El campo "Apellidos" debe tener al menos %(limit_value)d ' 'caracteres (actualmente tiene %(show_value)d).' }) email = models.EmailField( verbose_name=_('email'), unique=True, blank=False, ) is_staff = models.BooleanField( 'staff status', default=False, ) is_active = models.BooleanField( 'Activo', default=True, ) country = models.ForeignKey( 'place.Country', null=True, verbose_name=_('country'), ) state = models.ForeignKey( 'place.State', null=True, verbose_name=_('state'), ) city = models.ForeignKey( 'place.City', null=True, verbose_name=_('city'), ) address = models.CharField( verbose_name=_('address'), max_length=80, null=True, blank=True, ) date_joined = models.DateTimeField( verbose_name=_('created at'), default=timezone.now, ) accepted_terms = models.BooleanField( verbose_name=_('accepted user agreement'), default=True, ) accepted_terms_date = models.DateField( verbose_name=_('accepted user agreement date'), null=True, blank=True, ) accepted_privacy_policy = models.BooleanField( verbose_name=_('accepted privacy policy'), default=True, ) accepted_privacy_policy_date = models.DateField( verbose_name=_('accepted privacy policy date'), null=True, blank=True, ) objects = UserManager() def get_short_name(self): return self.first_name if self.first_name else self.email.split('@')[0] @property def get_avatar(self): avatar = '/static/img/profile_default_avatar.svg' if self.avatar: avatar = self.avatar.url return avatar @property def get_country(self): country = None if self.country: country = self.country.country return country @property def get_full_name(self): full_name = '{0} {1}'.format(self.first_name, self.last_name) return full_name.strip() def __str__(self): return self.get_full_name class Meta: verbose_name = _('user') verbose_name_plural = _('users') ordering = ('email', )
def __init__( self, name="", default=dict, required=False, prefix="", call_default=True, transform_default=False, validators=(), key_type=None, value_type=None, outer_delimiter=None, inner_delimiter="=", min_length=None, max_length=None, empty=None, ): """ Initialization method. Args: name (str): the name of the setting. default (dict): default value given to the setting. required (bool): whether the setting is required or not. prefix (str): the setting's prefix (overrides ``AppSettings.Meta`` prefix). call_default (bool): whether to call the default (if callable). transform_default (bool): whether to transform the default value. validators (list of callables): list of additional validators to use. key_type: the type of the dict keys. value_type (type): the type of dict values. outer_delimiter (str): value used to split environ string into separated parts inner_delimiter (str): value used to split environ string parts min_length (int): Noop. Deprecated. max_length (int): Noop. Deprecated. empty (bool): whether empty iterable is allowed. Deprecated in favor of MinLengthValidator. """ super().__init__( name=name, default=default, required=required, prefix=prefix, call_default=call_default, transform_default=transform_default, validators=validators, ) self.key_type = key_type self.value_type = value_type self.outer_delimiter = outer_delimiter self.inner_delimiter = inner_delimiter if key_type is not None: self.validators.append(DictKeysTypeValidator(key_type)) if value_type is not None: self.validators.append(DictValuesTypeValidator(value_type)) if empty is not None: warnings.warn( "Empty argument is deprecated, use MinLengthValidator instead.", DeprecationWarning) self.validators.append(MinLengthValidator(1)) if min_length is not None: warnings.warn( "Argument min_length does nothing and is deprecated.", DeprecationWarning) if max_length is not None: warnings.warn( "Argument max_length does nothing and is deprecated.", DeprecationWarning)
class Post(models.Model): STATUS = ((0, 'Draft'), (1, 'Publish')) title = models.CharField( max_length=60, validators=[MinLengthValidator(40)], help_text='The length of the post must be between 40 and 60 characters' ) slug = models.SlugField(max_length=60, unique=True) content = HTMLField() reference_url = models.URLField(blank=True) publish_date = models.DateTimeField(db_index=True, auto_now_add=True, editable=False) updated_date = models.DateTimeField(db_index=True, auto_now=True) image = models.ImageField( default='post_images/algorithm1.jpeg', upload_to='post_images', max_length=200, help_text= 'For bests results, use an image that is 1,200px wide x 600px high', ) status = models.IntegerField(db_index=True, choices=STATUS, default=0) author = models.ForeignKey(get_user_model(), related_name='author', on_delete=models.CASCADE) categories = models.ManyToManyField( Category, related_name='posts', help_text= 'Select more than one category by holding down Ctrl or Cmd key') # Model Managers objects = models.Manager() published = PublishedManager() class Meta: ordering = ['-updated_date', '-publish_date'] default_manager_name = 'objects' def __str__(self): return str(self.title) @property def word_count(self) -> int: return len(self.content.split()) @property def reading_time(self) -> int: return int(math.ceil(self.word_count / 75)) @property def publish_year(self) -> int: return self.publish_date.year @staticmethod def num_draft_posts() -> int: return Post.objects.filter(status=0).count() def save(self): if not self.slug.strip(): # pragma: no cover self.slug = slugify(self.title) _slug = self.slug _count = 1 while True: try: Post.objects.all().exclude(pk=self.pk).get(slug=_slug) except ObjectDoesNotExist: break _slug = f"{self.slug}{_count}" _count += 1 self.slug = _slug super(Post, self).save() def get_absolute_url(self): return reverse('blog:post_detail', kwargs={'slug': self.slug}) def get_excerpt(self, char): return self.content[:char]
(MaxValueValidator(10), 0, None), (MaxValueValidator(NOW), NOW, None), (MaxValueValidator(NOW), NOW - timedelta(days=1), None), (MaxValueValidator(0), 1, ValidationError), (MaxValueValidator(NOW), NOW + timedelta(days=1), ValidationError), (MinValueValidator(-10), -10, None), (MinValueValidator(-10), 10, None), (MinValueValidator(-10), 0, None), (MinValueValidator(NOW), NOW, None), (MinValueValidator(NOW), NOW + timedelta(days=1), None), (MinValueValidator(0), -1, ValidationError), (MinValueValidator(NOW), NOW - timedelta(days=1), ValidationError), (MaxLengthValidator(10), '', None), (MaxLengthValidator(10), 10 * 'x', None), (MaxLengthValidator(10), 15 * 'x', ValidationError), (MinLengthValidator(10), 15 * 'x', None), (MinLengthValidator(10), 10 * 'x', None), (MinLengthValidator(10), '', ValidationError), (URLValidator(EXTENDED_SCHEMES), 'file://localhost/path', None), (URLValidator(EXTENDED_SCHEMES), 'git://example.com/', None), (URLValidator(EXTENDED_SCHEMES), 'git://-invalid.com', ValidationError), (BaseValidator(True), True, None), (BaseValidator(True), False, ValidationError), (RegexValidator(), '', None), (RegexValidator(), 'x1x2', None), (RegexValidator('[0-9]+'), 'xxxxxx', ValidationError), (RegexValidator('[0-9]+'), '1234', None), (RegexValidator(re.compile('[0-9]+')), '1234', None), (RegexValidator('.*'), '', None), (RegexValidator(re.compile('.*')), '', None), (RegexValidator('.*'), 'xxxxx', None),
class Simple(models.Model): sentence_text = models.CharField(max_length=200, unique=True, null=False, validators=[MinLengthValidator(1)]) preprocess_sen = models.CharField(max_length=200, null=True) pos_tagging = models.CharField(max_length=200, null=True) lexical_tree = models.TextField('lexical tree', null=True) request_date = models.DateTimeField('date requested', default=timezone.now) request_count = models.PositiveIntegerField('count', default=0) pv_word = models.TextField("pv word", null=True) pv_modifier_word = models.TextField("pv modifier word", null=True) keywords = models.TextField("keywords", null=True) emotion = models.IntegerField('emotion', default=-1) def __str__(self): return self.sentence_text def __unicode__(self): return u'%s' % self.sentence_text def get_washed_text(self, refresh=False): """ 获取预处理后的数据 :param refresh: 如果refresh设置为True,则强制进行依次预处理,再返回结果 :return: 第一次调用会进行一次预处理,并把结果存入数据库,之后调用将直接从数据库读取结果 """ if self.preprocess_sen is None or refresh: self.preprocess_sen = wash_data(self.sentence_text) self.save() print "washed text :%s" % self.preprocess_sen return self.preprocess_sen def get_seg_json(self, refresh=False): """ 获取jieba分词结果的json格式 :param refresh: 是否强制重新分词,并刷新分词结果 :return: jieba分词 """ if self.pos_tagging is None or refresh: words = pseg.cut(self.get_washed_text()) self.pos_tagging = '' for word, flag in words: self.pos_tagging += (word + flag[0] + ',') self.pos_tagging = self.pos_tagging[:-1] self.save() return self.pos_tagging def get_lexical_tree(self, refresh=False): """ 获取词法分析树的数据(调用哈工大云的API) :param refresh: 是否强制刷新数据,是则重新调用哈工大云API :return: 词法分析树的json格式数据 """ if self.lexical_tree is None or len(self.lexical_tree) == 0 or refresh: text = self.get_washed_text() params = { 'api_key': 'N5G9s2d6TVoT7mptglCmWagXJqWWKAfBMBlDxJBR', 'text': text.encode('utf8'), 'format': 'json', 'pattern': 'all' } params = urlencode(params) url = "http://api.ltp-cloud.com/analysis/?" + params result = urllib2.urlopen(url) content = result.read().strip() content = re.sub('\n', ' ', content.decode('utf8')).encode('utf8') self.lexical_tree = content self.save() print self.lexical_tree return self.lexical_tree def get_lexical_tree_strip(self): content = self.get_lexical_tree() content = json.loads(content)[0][0] content = json.dumps(content) return content def syntactic(self): """ call API from algorithm to tell the syntactic of this sentence :return: Negative, Declarative or Question """ if self.emotion < 0: washed = self.get_washed_text() segs = self.get_seg_json() ltp = self.get_lexical_tree_strip() ltp_list = [] ltp_list.append(ltp.encode('utf8')) washed_list = [] washed_list.append(washed.encode('utf8')) segs_list = [] segs_list.append(segs.encode('utf8')) id_list = [] id_list.append(self.id) # hgd_file 是指经过哈工大预处理后的句子 # test_numark_file 是指没有处理过的句子 # test_file 是指分词后句子 result = judge.test(washed_list, segs_list, ltp_list, id_list) if result is None: self.emotion = -1 else: self.emotion = result self.save() if self.emotion == 0: return '疑问句' if self.emotion == 1: return '否定句' if self.emotion == 2: return '陈述句' return self.emotion
class PDAInstance(models.Model): # record contains teacher, school-year and summary pda_record = models.ForeignKey(PDARecord, on_delete=models.PROTECT, null=False, blank=False) pda_type = models.ForeignKey(PDAType, on_delete=models.PROTECT, null=False, blank=False) date_completed = models.DateField(null=False) description = models.CharField(validators=[MinLengthValidator(1)], max_length=3000, blank=False, null=False) # OR between those three ceu = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True) clock_hours = models.DecimalField(max_digits=3, decimal_places=1, null=True, blank=True) pages = models.DecimalField(max_digits=3, decimal_places=0, null=True, blank=True) file = models.FileField(upload_to='documents/Supporting_Files/', null=True, blank=True) date_submitted = models.DateField(null=True, blank=True) submitted = models.BooleanField(null=False, default=False, blank=True) principal_signed = models.BooleanField(null=False, default=False, blank=True) isei_reviewed = models.BooleanField(null=False, default=False, blank=True) approved = models.BooleanField(null=False, default=False, blank=True) approved_ceu = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True) approval_comment = models.CharField(max_length=300, null=True, blank=True) class Meta: ordering = ['pda_record'] @property def status(self): return int( self.submitted == True ) + int(self.principal_signed == True) * 2 + int( self.isei_reviewed == True) * 4 + int(self.approved == True) * 8 # 0 - New instance # 1 - Submitted instance # 2 - Denied by the principal (submitted=0, principal_signed = 1) # 3 - Signed by the principal # 4 - Summary denied, whole record returned (isei_reviewed = 1, submitted = 0, principal_signed = 0) # 5 - Resubmitted to principal (isei_reviewed = 1, submitted = 1, principal_signed = 0) # 6 - Record approved, individual instance denied ( isei_reviewed = 1, principal_signed = 1, submitted = 0) # 15 - Approved by ISEI def suggested_ceu(self): if self.approved: if self.ceu is not None: return self.ceu elif self.pages is not None: return round(self.pages / 100, 2) elif self.clock_hours is not None: return round(self.clock_hours / 10, 2) def __str__(self): return self.description
class Shop(models.Model): name = models.CharField(max_length=100, validators=[MinLengthValidator(5)]) desc = models.TextField(blank=True) address = models.CharField(max_length=100, blank=True)
class Candidatos(models.Model): email = models.EmailField(unique=True) escolaridade = models.IntegerField(choices=ESCOLARIDADE_CHOICES, blank=True, null=True) experiencia = models.IntegerField(blank=True, null=True) distancia = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True) faixa_salarial = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True) senha = models.TextField(validators=[MinLengthValidator(6)]) def login(self, request, email=None, senha=None): self.email = email self.senha = HashPassword(senha) if not request.session.get('email', False): try: self.candidato = Candidatos.objects.get(email=self.email, senha=self.senha) if request.session.get('email_empresa', False): del request.session['email_empresa'] if request.session.get('id_empresa', False): del request.session['id_empresa'] if request.session.get('empresa', False): del request.session['empresa'] request.session['email'] = self.candidato.email request.session['id'] = self.candidato.id request.session['candidato'] = True return self.candidato except Candidatos.DoesNotExist: return False else: return True def candidato_update(self, id=None, email=None, escolaridade=None, experiencia=None, distancia=None, faixa_salarial=None, senha=None): if id: self.id = id self.distancia = distancia self.faixa_salarial = faixa_salarial self.candidato = self.getcandidato_by_id(id=id) if self.candidato: if senha: self.candidato.senha = HashPassword(senha) if email: self.candidato.email = email self.candidato.escolaridade = escolaridade self.candidato.experiencia = experiencia self.candidato.faixa_salarial = faixa_salarial self.candidato.save() return True else: return False else: return False def getcandidato_by_id(self, id=None): if id: self.id = id try: self.candidato = Candidatos.objects.get(pk=id) return self.candidato except Candidatos.DoesNotExist: return False else: return False
class Headquarters(models.Model): ''' This Class: <Headquarters> contains the information of an headquarters. Esta Clase: <Sede> contiene la información de una sede. ''' entity = models.ForeignKey( Entity, db_index=True, on_delete=models.CASCADE, help_text='Entity | Entidad' ) name = models.CharField( max_length=100, unique=True, db_index=True, validators=[ MinLengthValidator(1), MaxLengthValidator(100), ], help_text= 'Name | Nombre' ) contact_information = models.ManyToManyField( ContactInformation, blank=True, help_text='Contact information | Informarción de contacto' ) extra_information = models.ManyToManyField( ExtraInformation, blank=True, help_text='Extra information | Informarción extra' ) active = models.BooleanField( default=True, help_text='Active | Activo' ) slug = models.SlugField( editable=False, max_length=255, unique=True, db_index=True ) def __str__(self): return self.get_name() def save(self, *args, **kwargs): if not self.pk: self.slug = slugify(self.get_name()) else: slug = slugify(self.get_name()) if self.slug != slug: self.slug = slug super(Headquarters, self).save(*args, **kwargs) #Setter def set_entity(self, entity): self.entity = entity def set_name(self, name): self.name = name def set_contact_information(self, contact_information): self.contact_information = contact_information def set_extra_information(self, extra_information): self.extra_information = extra_information def set_active(self, active): self.active = active #Getter def get_entity(self): return self.entity def get_name(self): return self.name def get_contact_information(self): return self.contact_information def get_extra_information(self): return self.extra_information def is_active(self): return self.active def get_full_name(self): return '%s - %s'%(self.get_entity(), self.get_name()) class Meta: db_table = 'headquarters' ordering = ['entity', 'name'] verbose_name = 'Entity' verbose_name_plural = 'Headquarters'
def validate_tag_embed(embed: Any) -> None: """ Validate a JSON document containing an embed as possible to send on Discord. This attempts to rebuild the validation used by Discord as well as possible by checking for various embed limits so we can ensure that any embed we store here will also be accepted as a valid embed by the Discord API. Using this directly is possible, although not intended - you usually stick this onto the `validators` keyword argument of model fields. Example: >>> from django.contrib.postgres import fields as pgfields >>> from django.db import models >>> from pydis_site.apps.api.models.bot.tag import validate_tag_embed >>> class MyMessage(models.Model): ... embed = pgfields.JSONField( ... validators=( ... validate_tag_embed, ... ) ... ) ... # ... ... Args: embed (Any): A dictionary describing the contents of this embed. See the official documentation for a full reference of accepted keys by this dictionary: https://discordapp.com/developers/docs/resources/channel#embed-object Raises: ValidationError: In case the given embed is deemed invalid, a `ValidationError` is raised which in turn will allow Django to display errors as appropriate. """ all_keys = { 'title', 'type', 'description', 'url', 'timestamp', 'color', 'footer', 'image', 'thumbnail', 'video', 'provider', 'author', 'fields' } one_required_of = {'description', 'fields', 'image', 'title', 'video'} field_validators = { 'title': (MinLengthValidator(limit_value=1, message="Embed title must not be empty."), MaxLengthValidator(limit_value=256)), 'description': (MaxLengthValidator(limit_value=2048), ), 'fields': (MaxLengthValidator(limit_value=25), validate_tag_embed_fields), 'footer': (validate_tag_embed_footer, ), 'author': (validate_tag_embed_author, ) } if not embed: raise ValidationError("Tag embed must not be empty.") elif not isinstance(embed, Mapping): raise ValidationError("Tag embed must be a mapping.") elif not any(field in embed for field in one_required_of): raise ValidationError( f"Tag embed must contain one of the fields {one_required_of}.") for required_key in one_required_of: if required_key in embed and not embed[required_key]: raise ValidationError(f"Key {required_key!r} must not be empty.") for field_name, value in embed.items(): if field_name not in all_keys: raise ValidationError(f"Unknown field name: {field_name!r}") if field_name in field_validators: for validator in field_validators[field_name]: validator(value)
class Analysis(models.Model): name = models.CharField(max_length=30, unique=True, validators=[MinLengthValidator(3)]) date_create = models.DateField(auto_now_add=True) date_modification = models.DateField(auto_now=True) data_set = models.FileField(upload_to="data_sets/") signal_speed = models.IntegerField(validators=[MaxValueValidator(4), MinValueValidator(1)]) signal_direction = models.IntegerField(validators=[MaxValueValidator(4), MinValueValidator(1)]) step_group = models.IntegerField(validators=[greater_zero]) start_sector_direction = models.IntegerField( validators=[MaxValueValidator(360), MinValueValidator(0)] ) end_sector_direction = models.IntegerField( validators=[MaxValueValidator(360), MinValueValidator(0)] ) start_sector_speed = models.IntegerField(validators=[MinValueValidator(0)]) end_sector_speed = models.IntegerField(validators=[MinValueValidator(0)]) result_analysis = models.FilePathField(blank=True) user = models.ForeignKey(User, on_delete=models.CASCADE) def __str__(self): return self.name class Meta: ordering = ["date_modification"] def delete(self, using=None, keep_parents=False): shutil.rmtree(self.result_analysis) self.data_set.delete(save=False) super(Analysis, self).delete(using, keep_parents) def delete_results_analysis(self): if os.path.exists(self.result_analysis): for analysis_file in os.listdir(self.result_analysis): os.remove(os.path.join(self.result_analysis, analysis_file)) logging.warning(f"Path does not exists {self.result_analysis}") def save(self, force_insert=False, force_update=False, using=None, update_fields=None): is_new = self.pk is None self.calculate_analysis() if is_new: self.result_analysis = os.path.join(settings.MEDIA_ROOT, self.name) super().save(force_insert, force_update, using, update_fields) def calculate_analysis(self): try: ApplicationManager().go( self, settings.MEDIA_ROOT, ) except Exception as e: try: Analysis.objects.get(name=self.name) except ObjectDoesNotExist: shutil.rmtree(os.path.join(settings.MEDIA_ROOT, self.name)) raise ValidationError(e) def create_archive(self): file_name = "{}_{}.zip".format(self.name, self.date_modification) base_name_dir = "zip_files" abs_path_dir = os.path.join(settings.MEDIA_ROOT, base_name_dir) if not os.path.exists(abs_path_dir): os.mkdir(abs_path_dir) compress_zip(os.path.join(abs_path_dir, file_name), get_all_abs_paths(self.result_analysis)) archive = ZipArchive() archive.name = self.name archive.zip_file = os.path.join(base_name_dir, file_name) archive.analysis = self archive.save() return archive def delete_archive(self): try: ZipArchive.objects.get(name=self.name).delete() except Exception: pass
class Project(SearchableMixin, CustomModel): name = models.CharField( _("Name"), max_length=30, validators=[ MinLengthValidator( 4, _("A Projectname should be at least 4 chars long")) ], ) activity = models.TextField(default="[]") name_short = models.CharField( _("Short Name"), max_length=4, unique=True, validators=[ RegexValidator(r'^[0-9a-zA-Z]*$', _("Only alphanumeric characters are valid")) ], ) description = models.TextField(_("Description"), blank=True) creator = models.ForeignKey( AUTH_USER_MODEL, # TODO BUG the project should not be deleted when the creator is deleted on_delete=models.CASCADE, verbose_name=_("creator"), related_name="creator") created_at = models.DateTimeField(_("Creation Date"), auto_now_add=True) updated_at = models.DateTimeField(_("Last updated:"), auto_now=True) manager = models.ManyToManyField(AUTH_USER_MODEL, verbose_name=_("project manager"), related_name="manager") developer = models.ManyToManyField(AUTH_USER_MODEL, verbose_name=_("developer"), related_name="dev_projects", blank=True) # TODO BUG projectWhereWctive? is that a typo what is meant with Wctive? (=active?) currentsprint = models.ForeignKey('sprint.Sprint', models.CASCADE, verbose_name=_("sprint"), related_name="projectWhereWctive", default=None, blank=True, null=True) nextTicketId = models.IntegerField(_("Next ticket ID"), editable=False, default=1) nextSprintId = models.IntegerField(_("Next sprint ID"), editable=False, default=1) activity_only_for_managers = models.BooleanField( _("Only managers can see timelog statistics for all developers"), default=True) objects = ProjectManager() class Meta: ordering = ['name'] verbose_name = _("project") verbose_name_plural = _("projects") def get_absolute_url(self): return reverse('project:detail', kwargs={'project': self.name_short}) def has_active_sprint(self): if (self.currentsprint is not None): return (self.currentsprint.is_active()) else: return False def developer_allowed(self, user): if (len(self.manager.filter(pk=user.pk)) == 1 or len(self.developer.filter(pk=user.pk)) == 1): return 1 return 0 def is_manager(self, user): if len(self.manager.filter(pk=user.pk)) == 1: return 1 return 0 def get_members(self): return (self.developer.all() | self.manager.all()).distinct() def __str__(self): return self.name # SearchableMixin functions def search_allowed_for_user(self, user): return self.developer_allowed(user) def get_relative_project(self): return self.name # permission functions def user_has_write_permissions(self, user): return self.is_manager(user) def user_has_read_permissions(self, user): return self.developer_allowed(user) # activity function def activity_stream_long_name(self): return self.description def increase_activity(self, date, issue=None, decrease=False): actor = CuserMiddleware.get_user() # handle user activity, if there is a current user if actor and not isinstance(actor, AnonymousUser): user_activity = json.loads(actor.activity) iss = 'None' if issue: iss = issue.get_ticket_identifier() if decrease: if self.name_short in user_activity: user_activity[self.name_short].pop() else: if self.name_short in user_activity: user_activity[self.name_short].append( (date.isoformat(), iss)) else: user_activity[self.name_short] = [] user_activity[self.name_short].append( (date.isoformat(), iss)) actor.activity = json.dumps(user_activity) actor.save() # delete cache cache.delete('action_data_' + actor.username) cache.delete('action_data_' + actor.username + '_' + self.name_short) # handle project activity activity_dict = json.loads(self.activity) if isinstance(activity_dict, dict): activity_dict = [] if decrease: activity_dict.pop() else: activity_dict.append(date.isoformat()) self.activity = json.dumps(activity_dict) self.save() return searchable_fields = [ 'creator', 'created_at', 'description', 'name', 'name_short', 'updated_at', 'issue' ]
class Exercise(AbstractSubmissionModel, AbstractLicenseModel, models.Model): """ Model for an exercise """ objects = SubmissionManager() """Custom manager""" description = models.TextField(max_length=2000, verbose_name=_('Description'), validators=[MinLengthValidator(40)]) """Description on how to perform the exercise""" name = models.CharField(max_length=200, verbose_name=_('Name')) """The exercise's name, with correct uppercase""" name_original = models.CharField(max_length=200, verbose_name=_('Name'), default='') """The exercise's name, as entered by the user""" creation_date = models.DateField(_('Date'), auto_now_add=True, null=True, blank=True) """The submission date""" language = models.ForeignKey(Language, verbose_name=_('Language'), on_delete=models.CASCADE) """The exercise's language""" uuid = models.UUIDField(default=uuid.uuid4, editable=False, verbose_name='UUID') """Globally unique ID, to identify the exercise across installations""" exercise_base = models.ForeignKey(ExerciseBase, verbose_name='ExerciseBase', on_delete=models.CASCADE, default=None, null=True, related_name='exercises') """ Refers to the base exercise with non translated information """ # # Django methods # class Meta: base_manager_name = 'objects' ordering = [ "name", ] def get_absolute_url(self): """ Returns the canonical URL to view an exercise """ return reverse('exercise:exercise:view', kwargs={ 'id': self.id, 'slug': slugify(self.name) }) def save(self, *args, **kwargs): """ Reset all cached infos """ self.name = smart_capitalize(self.name_original) super(Exercise, self).save(*args, **kwargs) # Cached template fragments for language in Language.objects.all(): delete_template_fragment_cache('muscle-overview', language.id) delete_template_fragment_cache('exercise-overview', language.id) delete_template_fragment_cache('equipment-overview', language.id) # Cached workouts for setting in self.setting_set.all(): reset_workout_canonical_form(setting.set.exerciseday.training_id) def delete(self, *args, **kwargs): """ Reset all cached infos """ # Cached template fragments for language in Language.objects.all(): delete_template_fragment_cache('muscle-overview', language.id) delete_template_fragment_cache('exercise-overview', language.id) delete_template_fragment_cache('equipment-overview', language.id) # Cached workouts for setting in self.setting_set.all(): reset_workout_canonical_form(setting.set.exerciseday.training.pk) super(Exercise, self).delete(*args, **kwargs) def __str__(self): """ Return a more human-readable representation """ return self.name # # Properties to expose the info from the exercise base # @property def category(self): return self.exercise_base.category @property def muscles(self): return self.exercise_base.muscles @property def muscles_secondary(self): return self.exercise_base.muscles_secondary @property def equipment(self): return self.exercise_base.equipment @property def images(self): return self.exercise_base.exerciseimage_set @property def variations(self): """ Returns the variations for this exercise in the same language """ out = [] if self.exercise_base.variations: for variation in self.exercise_base.variations.exercisebase_set.all( ): for exercise in variation.exercises.filter( language=self.language).accepted(): out.append(exercise) return out # # Own methods # @property def main_image(self): """ Return the main image for the exercise or None if nothing is found """ return self.images.accepted().filter(is_main=True).first() @property def description_clean(self): """ Return the exercise description with all markup removed """ return bleach.clean(self.description, strip=True) def get_owner_object(self): """ Exercise has no owner information """ return False def send_email(self, request): """ Sends an email after being successfully added to the database (for user submitted exercises only) """ try: user = User.objects.get(username=self.license_author) except User.DoesNotExist: return if self.license_author and user.email: translation.activate( user.userprofile.notification_language.short_name) url = request.build_absolute_uri(self.get_absolute_url()) subject = _( 'Exercise was successfully added to the general database') context = { 'exercise': self.name, 'url': url, 'site': Site.objects.get_current().domain } message = render_to_string('exercise/email_new.tpl', context) mail.send_mail(subject, message, settings.WGER_SETTINGS['EMAIL_FROM'], [user.email], fail_silently=True) def set_author(self, request): """ Set author and status This is only used when creating exercises (via web or API) """ if request.user.has_perm('exercises.add_exercise'): self.status = self.STATUS_ACCEPTED if not self.license_author: self.license_author = request.get_host().split(':')[0] else: if not self.license_author: self.license_author = request.user.username subject = _('New user submitted exercise') message = _('The user {0} submitted a new exercise "{1}".').format( request.user.username, self.name) mail.mail_admins(str(subject), str(message), fail_silently=True)
class Person(models.Model): ''' This Class:<Person> is abstract and contains basic personal information. Esta Clase:<Persona> es abstracto y contiene la información personal básica. ''' GENDER_CHOICES = [(gender.value, gender.value) for gender in Gender] MARITAL_STATUS_CHOICES = [(marital_status.value, marital_status.value) for marital_status in MaritalStatus] GROUP_CHOICES_BLOOD = [(blood_group.value, blood_group.value) for blood_group in BloodGroup] name = models.CharField( max_length=100, unique=True, db_index=True, validators=[ MinLengthValidator(1), MaxLengthValidator(100), ], help_text='Name | Nombre' ) last_name = models.CharField( max_length=100, unique=True, db_index=True, validators=[ MinLengthValidator(1), MaxLengthValidator(100), ], help_text='Last name | Apellido paterno' ) mother_last_name = models.CharField( max_length=100, unique=True, db_index=True, validators=[ MinLengthValidator(1), MaxLengthValidator(100), ], help_text='Mother last name | Apellido materno' ) birthday = models.DateField( help_text='birthday | Fecha nacimiento' ) gender = models.CharField( choices = GENDER_CHOICES, max_length=9, help_text='Gender | Género' ) marital_status = models.CharField( choices = MARITAL_STATUS_CHOICES, max_length=9, help_text='Marital status | Estado marital o civil' ) blood_group = models.CharField( choices = GROUP_CHOICES_BLOOD, max_length=9, null=True, blank=True, help_text='Blood group | Grupo sanguíneo' ) photography = models.ImageField( upload_to='image/persons/', null=True, blank=True, default=None, help_text='Photography | Fotografía' ) slug = models.SlugField( editable=False, max_length=255, unique=True, db_index=True ) def __str__(self): return self.get_full_name() def save(self, *args, **kwargs): if not self.pk: self.slug = slugify(self.get_full_name()) else: slug = slugify(self.get_full_name()) if self.slug != slug: self.slug = slug super(Person, self).save(*args, **kwargs) def get_full_name(self): return '%s %s, %s' % (self.get_last_name(), self.get_mother_last_name(), self.get_name()) #Setter def set_name(self, name): self.name = name def set_last_name(self, last_name): self.last_name = last_name def set_mother_last_name(self, mother_last_name): self.mother_last_name = mother_last_name def set_birthday(self, birthday): self.birthday = birthday def set_gender(self, gender): self.gender = gender def set_marital_status(self, marital_status): self.marital_status = marital_status def set_blood_group(self, blood_group): self.blood_group = blood_group #Getter def get_name(self): return self.name def get_last_name(self): return self.last_name def get_mother_last_name(self): return self.mother_last_name def get_birthday(self): return self.birthday def get_gender(self): return self.gender def get_marital_status(self): return self.marital_status def get_blood_group(self): return self.blood_group class Meta: abstract = True
class Terceirizada(ExportModelOperationsMixin('terceirizada'), TemChaveExterna, Ativavel, TemIdentificadorExternoAmigavel, TemVinculos): nome_fantasia = models.CharField('Nome fantasia', max_length=160, blank=True) razao_social = models.CharField('Razao social', max_length=160, blank=True) cnpj = models.CharField('CNPJ', validators=[MinLengthValidator(14)], max_length=14) representante_legal = models.CharField('Representante legal', max_length=160, blank=True) representante_telefone = models.CharField( 'Representante contato (telefone)', max_length=160, blank=True) representante_email = models.CharField('Representante contato (email)', max_length=160, blank=True) endereco = models.CharField('Endereco', max_length=160, blank=True) cep = models.CharField('CEP', max_length=8, blank=True) bairro = models.CharField('Bairro', max_length=150, blank=True) cidade = models.CharField('Cidade', max_length=150, blank=True) estado = models.CharField('Estado', max_length=150, blank=True) numero = models.CharField('Número', max_length=10, blank=True) complemento = models.CharField('Complemento', max_length=50, blank=True) eh_distribuidor = models.BooleanField('É distribuidor?', default=False) responsavel_nome = models.CharField('Responsável', max_length=160, blank=True) responsavel_email = models.CharField('Responsável contato (email)', max_length=160, blank=True) responsavel_cpf = models.CharField( max_length=11, blank=True, null=True, unique=True, # noqa DJ01 validators=[MinLengthValidator(11)]) responsavel_telefone = models.CharField('Responsável contato (telefone)', max_length=160, blank=True) responsavel_cargo = models.CharField('Responsável cargo', max_length=50, blank=True) # TODO: criar uma tabela central (Instituição) para agregar Escola, DRE, Terc e CODAE??? # e a partir dai a instituição que tem contatos e endereço? # o mesmo para pessoa fisica talvez? contatos = models.ManyToManyField('dados_comuns.Contato', blank=True) @property def vinculos_que_podem_ser_finalizados(self): return self.vinculos.filter( Q(data_inicial=None, data_final=None, ativo=False) | # noqa W504 esperando ativacao Q(data_inicial__isnull=False, data_final=None, ativo=True) # noqa W504 ativo ).exclude(perfil__nome=NUTRI_ADMIN_RESPONSAVEL) def desvincular_lotes(self): for lote in self.lotes.all(): self.lotes.remove(lote) self.save() @property def quantidade_alunos(self): quantidade_total = 0 for lote in self.lotes.all(): quantidade_total += lote.quantidade_alunos return quantidade_total @property def nome(self): return self.nome_fantasia @property def nutricionistas(self): return self.nutricionistas @property def super_admin(self): vinculo = self.vinculos.filter( usuario__super_admin_terceirizadas=True).last() if vinculo: return vinculo.usuario return None @property def inclusoes_continuas_autorizadas(self): return InclusaoAlimentacaoContinua.objects.filter( escola__lote__in=self.lotes.all(), status__in=[ InclusaoAlimentacaoContinua.workflow_class.CODAE_AUTORIZADO, InclusaoAlimentacaoContinua.workflow_class. TERCEIRIZADA_TOMOU_CIENCIA ]) @property def inclusoes_normais_autorizadas(self): return GrupoInclusaoAlimentacaoNormal.objects.filter( escola__lote__in=self.lotes.all(), status__in=[ GrupoInclusaoAlimentacaoNormal.workflow_class.CODAE_AUTORIZADO, GrupoInclusaoAlimentacaoNormal.workflow_class. TERCEIRIZADA_TOMOU_CIENCIA ]) @property def inclusoes_continuas_reprovadas(self): return InclusaoAlimentacaoContinua.objects.filter( escola__lote__in=self.lotes.all(), status=InclusaoAlimentacaoContinua.workflow_class. CODAE_NEGOU_PEDIDO) @property def solicitacao_kit_lanche_avulsa_autorizadas(self): return SolicitacaoKitLancheAvulsa.objects.filter( escola__lote__in=self.lotes.all(), status__in=[ SolicitacaoKitLancheAvulsa.workflow_class.CODAE_AUTORIZADO, SolicitacaoKitLancheAvulsa.workflow_class. TERCEIRIZADA_TOMOU_CIENCIA ]) @property def inclusoes_normais_reprovadas(self): return GrupoInclusaoAlimentacaoNormal.objects.filter( escola__lote__in=self.lotes.all(), status=GrupoInclusaoAlimentacaoNormal.workflow_class. CODAE_NEGOU_PEDIDO) # TODO: talvez fazer um manager genérico pra fazer esse filtro def inclusoes_continuas_das_minhas_escolas_no_prazo_vencendo( self, filtro_aplicado): if filtro_aplicado == 'hoje': # TODO: rever filtro hoje que nao é mais usado inclusoes_continuas = InclusaoAlimentacaoContinua.objects else: # se o filtro nao for hoje, filtra o padrao inclusoes_continuas = InclusaoAlimentacaoContinua.vencidos return inclusoes_continuas.filter( status=InclusaoAlimentacaoContinua.workflow_class.CODAE_AUTORIZADO, escola__lote__in=self.lotes.all()) def inclusoes_continuas_das_minhas_escolas_no_prazo_limite( self, filtro_aplicado): if filtro_aplicado == 'daqui_a_7_dias': inclusoes_continuas = InclusaoAlimentacaoContinua.desta_semana else: inclusoes_continuas = InclusaoAlimentacaoContinua.objects # type: ignore return inclusoes_continuas.filter( status=InclusaoAlimentacaoContinua.workflow_class.CODAE_AUTORIZADO, escola__lote__in=self.lotes.all()) def inclusoes_continuas_das_minhas_escolas_no_prazo_regular( self, filtro_aplicado): if filtro_aplicado == 'daqui_a_30_dias': inclusoes_continuas = InclusaoAlimentacaoContinua.deste_mes elif filtro_aplicado == 'daqui_a_7_dias': inclusoes_continuas = InclusaoAlimentacaoContinua.desta_semana # type: ignore else: inclusoes_continuas = InclusaoAlimentacaoContinua.objects # type: ignore return inclusoes_continuas.filter( status=InclusaoAlimentacaoContinua.workflow_class.CODAE_AUTORIZADO, escola__lote__in=self.lotes.all()) def inclusoes_normais_das_minhas_escolas_no_prazo_vencendo( self, filtro_aplicado): if filtro_aplicado == 'hoje': # TODO: rever filtro hoje que nao é mais usado inclusoes_normais = GrupoInclusaoAlimentacaoNormal.objects else: inclusoes_normais = GrupoInclusaoAlimentacaoNormal.vencidos return inclusoes_normais.filter( status=InclusaoAlimentacaoContinua.workflow_class.CODAE_AUTORIZADO, escola__lote__in=self.lotes.all()) def inclusoes_normais_das_minhas_escolas_no_prazo_limite( self, filtro_aplicado): if filtro_aplicado == 'daqui_a_7_dias': inclusoes_normais = GrupoInclusaoAlimentacaoNormal.desta_semana else: inclusoes_normais = GrupoInclusaoAlimentacaoNormal.objects # type: ignore return inclusoes_normais.filter( status=InclusaoAlimentacaoContinua.workflow_class.CODAE_AUTORIZADO, escola__lote__in=self.lotes.all()) def inclusoes_normais_das_minhas_escolas_no_prazo_regular( self, filtro_aplicado): if filtro_aplicado == 'daqui_a_30_dias': inclusoes_normais = GrupoInclusaoAlimentacaoNormal.deste_mes elif filtro_aplicado == 'daqui_a_7_dias': inclusoes_normais = GrupoInclusaoAlimentacaoNormal.desta_semana # type: ignore else: inclusoes_normais = GrupoInclusaoAlimentacaoNormal.objects # type: ignore return inclusoes_normais.filter( status=InclusaoAlimentacaoContinua.workflow_class.CODAE_AUTORIZADO, escola__lote__in=self.lotes.all()) def alteracoes_cardapio_das_minhas_escolas_no_prazo_vencendo( self, filtro_aplicado): if filtro_aplicado == 'hoje': # TODO: rever filtro hoje que nao é mais usado alteracoes_cardapio = AlteracaoCardapio.objects else: alteracoes_cardapio = AlteracaoCardapio.vencidos return alteracoes_cardapio.filter( status=AlteracaoCardapio.workflow_class.CODAE_AUTORIZADO, escola__lote__in=self.lotes.all()) def alteracoes_cardapio_das_minhas_escolas_no_prazo_limite( self, filtro_aplicado): if filtro_aplicado == 'daqui_a_7_dias': alteracoes_cardapio = AlteracaoCardapio.desta_semana else: alteracoes_cardapio = AlteracaoCardapio.objects # type: ignore return alteracoes_cardapio.filter( status=AlteracaoCardapio.workflow_class.CODAE_AUTORIZADO, escola__lote__in=self.lotes.all()) def alteracoes_cardapio_das_minhas_escolas_no_prazo_regular( self, filtro_aplicado): if filtro_aplicado == 'daqui_a_30_dias': alteracoes_cardapio = AlteracaoCardapio.deste_mes elif filtro_aplicado == 'daqui_a_7_dias': alteracoes_cardapio = AlteracaoCardapio.desta_semana # type: ignore else: alteracoes_cardapio = AlteracaoCardapio.objects # type: ignore return alteracoes_cardapio.filter( status=AlteracaoCardapio.workflow_class.CODAE_AUTORIZADO, escola__lote__in=self.lotes.all()) def alteracoes_cardapio_das_minhas(self, filtro_aplicado): queryset = queryset_por_data(filtro_aplicado, AlteracaoCardapio) return queryset.filter(status__in=[ AlteracaoCardapio.workflow_class.CODAE_AUTORIZADO, AlteracaoCardapio.workflow_class.CODAE_QUESTIONADO ], escola__lote__in=self.lotes.all()) def alteracoes_cardapio_cei_das_minhas(self, filtro_aplicado): queryset = queryset_por_data(filtro_aplicado, AlteracaoCardapioCEI) return queryset.filter(status__in=[ AlteracaoCardapioCEI.workflow_class.CODAE_AUTORIZADO, AlteracaoCardapioCEI.workflow_class.CODAE_QUESTIONADO ], escola__lote__in=self.lotes.all()) def grupos_inclusoes_alimentacao_normal_das_minhas_escolas( self, filtro_aplicado): queryset = queryset_por_data(filtro_aplicado, GrupoInclusaoAlimentacaoNormal) return queryset.filter( status=AlteracaoCardapio.workflow_class.CODAE_AUTORIZADO, escola__lote__in=self.lotes.all()) def inclusoes_alimentacao_de_cei_das_minhas_escolas(self, filtro_aplicado): return self.filtra_solicitacoes_minhas_escolas_a_validar_por_data( filtro_aplicado, InclusaoAlimentacaoDaCEI) def inclusoes_alimentacao_continua_das_minhas_escolas( self, filtro_aplicado): queryset = queryset_por_data(filtro_aplicado, InclusaoAlimentacaoContinua) return queryset.filter( status=AlteracaoCardapio.workflow_class.CODAE_AUTORIZADO, escola__lote__in=self.lotes.all()) def suspensoes_alimentacao_das_minhas_escolas(self, filtro_aplicado): queryset = queryset_por_data(filtro_aplicado, GrupoSuspensaoAlimentacao) return queryset.filter( status=GrupoSuspensaoAlimentacao.workflow_class.INFORMADO, escola__lote__in=self.lotes.all()) @property def alteracoes_cardapio_autorizadas(self): return AlteracaoCardapio.objects.filter( escola__lote__in=self.lotes.all(), status__in=[ AlteracaoCardapio.workflow_class.CODAE_AUTORIZADO, AlteracaoCardapio.workflow_class.TERCEIRIZADA_TOMOU_CIENCIA ]) @property def alteracoes_cardapio_reprovadas(self): return AlteracaoCardapio.objects.filter( escola__lote__in=self.lotes.all(), status=AlteracaoCardapio.workflow_class.CODAE_NEGOU_PEDIDO) # # Inversão de dia de cardápio # def inversoes_cardapio_das_minhas_escolas(self, filtro_aplicado): if filtro_aplicado == 'daqui_a_7_dias': inversoes_cardapio = InversaoCardapio.desta_semana elif filtro_aplicado == 'daqui_a_30_dias': inversoes_cardapio = InversaoCardapio.deste_mes # type: ignore else: inversoes_cardapio = InversaoCardapio.objects # type: ignore return inversoes_cardapio.filter( escola__lote__in=self.lotes.all(), status=InversaoCardapio.workflow_class.CODAE_AUTORIZADO) @property def inversoes_cardapio_autorizadas(self): return InversaoCardapio.objects.filter( escola__lote__in=self.lotes.all(), status__in=[ InversaoCardapio.workflow_class.CODAE_AUTORIZADO, InversaoCardapio.workflow_class.TERCEIRIZADA_TOMOU_CIENCIA ]) # # Solicitação Unificada # def solicitacoes_unificadas_das_minhas_escolas(self, filtro_aplicado): if filtro_aplicado == 'daqui_a_7_dias': solicitacoes_unificadas = SolicitacaoKitLancheUnificada.desta_semana elif filtro_aplicado == 'daqui_a_30_dias': solicitacoes_unificadas = SolicitacaoKitLancheUnificada.deste_mes # type: ignore else: solicitacoes_unificadas = SolicitacaoKitLancheUnificada.objects # type: ignore return solicitacoes_unificadas.filter( escolas_quantidades__escola__lote__in=self.lotes.all(), status=SolicitacaoKitLancheUnificada.workflow_class. CODAE_AUTORIZADO).distinct() @property def solicitacoes_unificadas_autorizadas(self): return SolicitacaoKitLancheUnificada.objects.filter( escolas_quantidades__escola__lote__in=self.lotes.all(), status__in=[ SolicitacaoKitLancheUnificada.workflow_class.CODAE_AUTORIZADO, SolicitacaoKitLancheUnificada.workflow_class. TERCEIRIZADA_TOMOU_CIENCIA ]).distinct() def solicitacoes_kit_lanche_das_minhas_escolas_a_validar( self, filtro_aplicado): if filtro_aplicado == 'daqui_a_7_dias': solicitacoes_kit_lanche = SolicitacaoKitLancheAvulsa.desta_semana elif filtro_aplicado == 'daqui_a_30_dias': solicitacoes_kit_lanche = SolicitacaoKitLancheAvulsa.deste_mes # type: ignore else: solicitacoes_kit_lanche = SolicitacaoKitLancheAvulsa.objects # type: ignore return solicitacoes_kit_lanche.filter( escola__lote__in=self.lotes.all(), status__in=[ SolicitacaoKitLancheAvulsa.workflow_class.CODAE_AUTORIZADO, SolicitacaoKitLancheAvulsa.workflow_class.CODAE_QUESTIONADO ]) def solicitacoes_kit_lanche_cei_das_minhas_escolas_a_validar( self, filtro_aplicado): if filtro_aplicado == 'daqui_a_7_dias': solicitacoes_kit_lanche = SolicitacaoKitLancheCEIAvulsa.desta_semana elif filtro_aplicado == 'daqui_a_30_dias': solicitacoes_kit_lanche = SolicitacaoKitLancheCEIAvulsa.deste_mes # type: ignore else: solicitacoes_kit_lanche = SolicitacaoKitLancheCEIAvulsa.objects # type: ignore return solicitacoes_kit_lanche.filter( escola__lote__in=self.lotes.all(), status__in=[ SolicitacaoKitLancheCEIAvulsa.workflow_class.CODAE_AUTORIZADO, SolicitacaoKitLancheCEIAvulsa.workflow_class.CODAE_QUESTIONADO ]) def __str__(self): return f'{self.nome_fantasia}' class Meta: verbose_name = 'Terceirizada' verbose_name_plural = 'Terceirizadas'
class Contest(models.Model): title = models.CharField(max_length=200) author = models.ForeignKey(to=User, on_delete=models.PROTECT) short_description = models.TextField( verbose_name="Short Description", max_length=250, help_text="A short description whch describes your contest.", null=True, ) description = RichTextUploadingField( help_text="Give a brief or detailed description for your contest") eligibility = models.TextField( null=True, help_text="What is the eligibility criteria for participants?", ) rules = models.TextField( null=True, help_text="What are the rules that all participants must follow?", ) prizes = models.TextField( null=True, help_text="Mention prizes for diff positions/winners (If any)", max_length=200) contacts = models.TextField( null=True, help_text= "Give your email, phone etc. so that people can contact you if they need to" ) start_date = models.DateField(verbose_name="Start Date") start_time = models.TimeField(verbose_name="Start Time", null=True) end_date = models.DateField(verbose_name="End Date") end_time = models.TimeField(verbose_name="End Time", null=True) unique_code = models.CharField( verbose_name="Unique Code", max_length=15, validators=[MinLengthValidator(3), unique_code_validator], unique=True, db_index=True, help_text= "A unique code for your contest. between 3-15 characters. May contain only \ lowercase characters and numbers. For example if the question name is 'Sorting Array', \ you may name the code SORTARR") is_public = models.BooleanField( verbose_name="Is this Public?", default=True, help_text= "If you choose to make this non public, please enter a link below that participants will\ click to register for the contest. It can lead to a form or a website etc. After they complete \ registration, it is your responsibility to add them in the participants list via\ the REST API call.") status = models.IntegerField( default=0, help_text="0-Yet to start, 1- live, 2- ended", validators=[MinValueValidator(0), MaxValueValidator(2)]) registration_link = models.URLField(verbose_name="Registration Link", blank=True) participants = models.ManyToManyField( to=User, related_name="participating_contests") def __str__(self): return self.unique_code
class Team(UUIDClassicModel): organization: models.ForeignKey = models.ForeignKey( "posthog.Organization", on_delete=models.CASCADE, related_name="teams", related_query_name="team") api_token: models.CharField = models.CharField( max_length=200, unique=True, default=generate_random_token, validators=[ MinLengthValidator( 10, "Project's API token must be at least 10 characters long!") ], ) app_urls: ArrayField = ArrayField(models.CharField(max_length=200, null=True), default=list, blank=True) name: models.CharField = models.CharField( max_length=200, default="Default Project", validators=[MinLengthValidator(1, "Project must have a name!")], ) slack_incoming_webhook: models.CharField = models.CharField(max_length=500, null=True, blank=True) created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True) updated_at: models.DateTimeField = models.DateTimeField(auto_now=True) anonymize_ips: models.BooleanField = models.BooleanField(default=False) completed_snippet_onboarding: models.BooleanField = models.BooleanField( default=False) ingested_event: models.BooleanField = models.BooleanField(default=False) session_recording_opt_in: models.BooleanField = models.BooleanField( default=False) session_recording_retention_period_days: models.IntegerField = models.IntegerField( null=True, default=None, blank=True) signup_token: models.CharField = models.CharField(max_length=200, null=True, blank=True) is_demo: models.BooleanField = models.BooleanField(default=False) test_account_filters: models.JSONField = models.JSONField(default=list) timezone: models.CharField = models.CharField(max_length=240, choices=TIMEZONES, default="UTC") data_attributes: models.JSONField = models.JSONField( default=get_default_data_attributes) # DEPRECATED, DISUSED: plugins are enabled for everyone now plugins_opt_in: models.BooleanField = models.BooleanField(default=False) # DEPRECATED, DISUSED: replaced with env variable OPT_OUT_CAPTURE and User.anonymized_data opt_out_capture: models.BooleanField = models.BooleanField(default=False) # DEPRECATED, DISUSED: now managing access in an Organization-centric way users: models.ManyToManyField = models.ManyToManyField( "User", blank=True, related_name="teams_deprecated_relationship") # DEPRECATED: in favor of `EventDefinition` model event_names: models.JSONField = models.JSONField(default=list) event_names_with_usage: models.JSONField = models.JSONField(default=list) # DEPRECATED: in favor of `PropertyDefinition` model event_properties: models.JSONField = models.JSONField(default=list) event_properties_with_usage: models.JSONField = models.JSONField( default=list) event_properties_numerical: models.JSONField = models.JSONField( default=list) objects: TeamManager = TeamManager() def __str__(self): if self.name: return self.name if self.app_urls and self.app_urls[0]: return ", ".join(self.app_urls) return str(self.pk) __repr__ = sane_repr("uuid", "name", "api_token") def get_latest_event_names_with_usage(self): """ TODO: #4070 This has been deprecated in favor of `EventDefinition` and should be removed upon final migration. Fetches `event_names_with_usage` but adding any events that may have come in since the property was last computed. Ensures all events are included. """ def get_key(event: str, type: str): return next((item.get(type) for item in self.event_names_with_usage if item["event"] == event), None) return [{ "event": event, "volume": get_key(event, "volume"), "usage_count": get_key(event, "usage_count") } for event in self.event_names] def get_latest_event_properties_with_usage(self): """ TODO: #4070 This has been deprecated in favor of `EventDefinition` and should be removed upon final migration. Fetches `event_properties_with_usage` but adding any properties that may have appeared since the property was last computed. Ensures all properties are included. """ def get_key(key: str, type: str): return next((item.get(type) for item in self.event_properties_with_usage if item["key"] == key), None) return [{ "key": key, "volume": get_key(key, "volume"), "usage_count": get_key(key, "usage_count") } for key in self.event_properties]