class Migration(migrations.Migration): initial = True dependencies = [ ('thesis', '0011_auto_20200429_2213'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ migrations.CreateModel( name='Review', fields=[ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('created', django_extensions.db.fields.CreationDateTimeField( auto_now_add=True, verbose_name='created')), ('modified', django_extensions.db.fields.ModificationDateTimeField( auto_now=True, verbose_name='modified')), ('comment', models.TextField(verbose_name='Review comment')), ('questions', models.TextField(verbose_name='Review questions')), ('difficulty', models.PositiveSmallIntegerField( help_text= 'As value between 1 and 3 inclusive, higher is harder.', validators=[ django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(3) ], verbose_name='Difficulty')), ('grades', django.contrib.postgres.fields. ArrayField(base_field=models.PositiveSmallIntegerField( help_text= 'As value between 1 and 4 inclusive, higher is better.', validators=[ django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4) ]), size=None, validators=[ django.contrib.postgres.validators. ArrayMinLengthValidator(5), django.contrib.postgres.validators. ArrayMaxLengthValidator(6) ], verbose_name='Grades')), ('thesis', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='review_thesis', to='thesis.ThesisAuthor')), ('user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='review_user', to=settings.AUTH_USER_MODEL)), ], options={ 'verbose_name': 'Review', 'verbose_name_plural': 'Reviews', }, ), ]
class Migration(migrations.Migration): initial = True dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ migrations.CreateModel( name='Correspondence', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=254)), ('email', models.EmailField(max_length=254)), ('subject', models.CharField(max_length=254)), ('content', models.TextField()), ('created_on', models.DateTimeField(auto_now_add=True)), ], ), migrations.CreateModel( name='University', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=254)), ('description', models.CharField(blank=True, max_length=254)), ], options={ 'verbose_name_plural': 'universities', }, ), migrations.CreateModel( name='Program', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=254)), ('description', models.CharField(blank=True, max_length=254)), ('members', models.ManyToManyField(blank=True, related_name='programs', to=settings.AUTH_USER_MODEL)), ('university', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='programs', to='community.university')), ], ), migrations.CreateModel( name='Profile', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('description', models.CharField(blank=True, max_length=254)), ('year', models.PositiveSmallIntegerField(blank=True, choices=[(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)], null=True)), ('phone_number', phonenumber_field.modelfields.PhoneNumberField(blank=True, max_length=128, null=True, region=None)), ('discord_username', models.CharField(blank=True, max_length=254, null=True)), ('facebook_link', models.CharField(blank=True, max_length=254, null=True)), ('skype_link', models.CharField(blank=True, max_length=254, null=True)), ('user', annoying.fields.AutoOneToOneField( on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ], ), ]
class PositiveSmallIntegerData(models.Model): data = models.PositiveSmallIntegerField(null=True)
class EDID(models.Model): objects = EDIDPublicManager() all_objects = models.Manager() manufacturer = models.ForeignKey(Manufacturer) # Initialized and basic data auto-added STATUS_INITIALIZED = 0 # Standard and detailed timings auto-added STATUS_TIMINGS_ADDED = 1 # Manually edited by users STATUS_EDITED = 2 # Private, hidden from public STATUS_PRIVATE = 3 STATUS_CHOICES = ((STATUS_INITIALIZED, 'Initialized'), (STATUS_TIMINGS_ADDED, 'Timings Added'), (STATUS_EDITED, 'Edited'), (STATUS_PRIVATE, 'Private')) status = models.PositiveSmallIntegerField(choices=STATUS_CHOICES, default=STATUS_INITIALIZED) created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True) # Binary file encoded in base64 file_base64 = models.TextField(editable=False) ### Header # ID Product Code manufacturer_product_code = models.CharField(max_length=4, blank=True) # ID Serial Number, 32-bit manufacturer_serial_number = models.PositiveIntegerField(blank=True, null=True) # Week of manufacture, 1-54, 0==Unknown, 255==the year model week_of_manufacture = models.PositiveSmallIntegerField() # Year of manufacture, 1990-2245 year_of_manufacture = models.PositiveSmallIntegerField() # EDID version and revision VERSION_1_0 = 0 VERSION_1_1 = 1 VERSION_1_2 = 2 VERSION_1_3 = 3 VERSION_1_4 = 4 VERSION_2_0 = 5 VERSION_CHOICES = ( (VERSION_1_0, '1.0'), (VERSION_1_1, '1.1'), (VERSION_1_2, '1.2'), (VERSION_1_3, '1.3'), (VERSION_1_4, '1.4'), (VERSION_2_0, '2.0'), ) version = models.PositiveSmallIntegerField(choices=VERSION_CHOICES) ### ASCII Text Descriptors # Monitor Name, from Monitor Descriptor Description (type 0xFC) monitor_name = models.CharField(max_length=13, blank=True) # Monitor Serial Number, from Monitor Descriptor Description (type 0xFF) monitor_serial_number = models.CharField(max_length=13, blank=True) # Monitor Data String, from Monitor Descriptor Description (type 0xFE) monitor_data_string = models.CharField(max_length=13, blank=True) ### bdp=Basic display parameters bdp_video_input_analog = 0 bdp_video_input_digital = 1 BDP_VIDEO_INPUT_CHOICES = ((bdp_video_input_analog, 'Analog'), (bdp_video_input_digital, 'Digital')) bdp_video_input = models.PositiveSmallIntegerField( 'video input', choices=BDP_VIDEO_INPUT_CHOICES, default=bdp_video_input_analog ) # Analog Input bdp_signal_level_std_0700_0300 = 0 bdp_signal_level_std_0714_0286 = 1 bdp_signal_level_std_1000_0400 = 2 bdp_signal_level_std_0700_0000 = 3 BDP_SIGNAL_LVL_STD_CHOICE = ( (bdp_signal_level_std_0700_0300, '(0.700, 0.300)'), (bdp_signal_level_std_0714_0286, '(0.714, 0.286)'), (bdp_signal_level_std_1000_0400, '(1.000, 0.400)'), (bdp_signal_level_std_0700_0000, '(0.700, 0.000)'), ) bdp_signal_level_standard = models.PositiveSmallIntegerField( 'signal level standard', choices=BDP_SIGNAL_LVL_STD_CHOICE, blank=True, null=True) bdp_blank_to_black_setup = models.NullBooleanField( 'blank-to-black setup level') bdp_separate_syncs = models.NullBooleanField('separate sync') bdp_composite_sync = models.NullBooleanField( 'composite sync signal on horizontal') bdp_sync_on_green_video = models.NullBooleanField( 'composite sync signal on green video') bdp_vsync_serration = models.NullBooleanField( 'serration on the vertical sync') # Digital Input bdp_video_input_dfp_1 = models.NullBooleanField('digital flat panel 1.x') bdp_max_horizontal_image_size = models.PositiveSmallIntegerField( 'maximum horizontal image size') bdp_max_vertical_image_size = models.PositiveSmallIntegerField( 'maximum vertical image size') bdp_display_gamma = models.DecimalField('display gamma', max_digits=3, decimal_places=2, blank=True, null=True) BDP_FEATURE_DISPLY_CHOICE = ( (DisplayType.Monochrome, 'Monochrome or grayscale display'), (DisplayType.RGB, 'RGB color display'), (DisplayType.Non_RGB, 'Non-RGB multicolor display'), (DisplayType.Undefined, 'Undefined'), ) bdp_feature_standby = models.BooleanField('standby mode') bdp_feature_suspend = models.BooleanField('suspend mode') bdp_feature_active_off = models.BooleanField( 'active off/very low power mode') bdp_feature_display_type = models.PositiveSmallIntegerField( 'display color type', choices=BDP_FEATURE_DISPLY_CHOICE) bdp_feature_standard_srgb = models.BooleanField('standard sRGB') bdp_feature_pref_timing_mode = models.BooleanField( 'preferred timing mode') bdp_feature_default_gtf = models.BooleanField('default GTF') ### chr=Chromaticity chr_red_x = models.DecimalField( 'red x', max_digits=4, decimal_places=3) chr_red_y = models.DecimalField( 'red y', max_digits=4, decimal_places=3) chr_green_x = models.DecimalField( 'green x', max_digits=4, decimal_places=3) chr_green_y = models.DecimalField( 'green y', max_digits=4, decimal_places=3) chr_blue_x = models.DecimalField( 'blue x', max_digits=4, decimal_places=3) chr_blue_y = models.DecimalField( 'blue y', max_digits=4, decimal_places=3) chr_white_x = models.DecimalField( 'white x', max_digits=4, decimal_places=3) chr_white_y = models.DecimalField( 'white y', max_digits=4, decimal_places=3) ### est_timings=Established Timings est_timings_720_400_70 = models.BooleanField('720x400@70Hz') est_timings_720_400_88 = models.BooleanField('720x400@88Hz') est_timings_640_480_60 = models.BooleanField('640x480@60Hz') est_timings_640_480_67 = models.BooleanField('640x480@67Hz') est_timings_640_480_72 = models.BooleanField('640x480@72Hz') est_timings_640_480_75 = models.BooleanField('640x480@75Hz') est_timings_800_600_56 = models.BooleanField('800x600@56Hz') est_timings_800_600_60 = models.BooleanField('800x600@60Hz') est_timings_800_600_72 = models.BooleanField('800x600@72Hz') est_timings_800_600_75 = models.BooleanField('800x600@75Hz') est_timings_832_624_75 = models.BooleanField('832x624@75Hz') est_timings_1024_768_87 = models.BooleanField('1024x768@87Hz') est_timings_1024_768_60 = models.BooleanField('1024x768@60Hz') est_timings_1024_768_70 = models.BooleanField('1024x768@70Hz') est_timings_1024_768_75 = models.BooleanField('1024x768@75Hz') est_timings_1280_1024_75 = models.BooleanField('1280x1024@75Hz') ### mrl=Monitor range limits, optional starting from v1.1 monitor_range_limits = models.BooleanField('monitor range limits') # in kHz mrl_min_horizontal_rate = models.PositiveSmallIntegerField( 'minimum horizontal rate', blank=True, null=True) mrl_max_horizontal_rate = models.PositiveSmallIntegerField( 'maximum horizontal rate', blank=True, null=True) # in Hz mrl_min_vertical_rate = models.PositiveSmallIntegerField( 'minimum vertical rate', blank=True, null=True) mrl_max_vertical_rate = models.PositiveSmallIntegerField( 'maximum vertical rate', blank=True, null=True) # in MHz mrl_max_pixel_clock = models.PositiveSmallIntegerField( 'maximum supported pixel clock', blank=True, null=True) mrl_secondary_gtf_curve_support = models.NullBooleanField( 'secondary GTF curve') # in kHz mrl_secondary_gtf_start_freq = models.PositiveSmallIntegerField( 'start frequency', blank=True, null=True) mrl_secondary_gtf_c = models.PositiveSmallIntegerField( 'C', blank=True, null=True) mrl_secondary_gtf_m = models.PositiveSmallIntegerField( 'M', blank=True, null=True) mrl_secondary_gtf_k = models.PositiveSmallIntegerField( 'K', blank=True, null=True) mrl_secondary_gtf_j = models.PositiveSmallIntegerField( 'J', blank=True, null=True) @classmethod def create(cls, file_base64, edid_data): edid = cls(file_base64=file_base64) # Add basic data edid._populate_from_edid_parser(edid_data) return edid def _populate_from_edid_parser(self, edid): ### Header try: self.manufacturer = Manufacturer.objects.get( name_id=edid['ID_Manufacturer_Name']) except ObjectDoesNotExist: # UNK is reserved for unknown manufacturer self.manufacturer = Manufacturer.objects.get(name_id='UNK') self.manufacturer_product_code = edid['ID_Product_Code'] self.manufacturer_serial_number = edid['ID_Serial_Number'] self.week_of_manufacture = edid['Week_of_manufacture'] self.year_of_manufacture = edid['Year_of_manufacture'] if edid['EDID_version'] == 1: if edid['EDID_revision'] == 0: self.version = self.VERSION_1_0 elif edid['EDID_revision'] == 1: self.version = self.VERSION_1_1 elif edid['EDID_revision'] == 2: self.version = self.VERSION_1_2 elif edid['EDID_revision'] == 3: self.version = self.VERSION_1_3 elif edid['EDID_revision'] == 4: self.version = self.VERSION_1_4 elif edid['EDID_version'] == 2: if edid['EDID_revision'] == 0: self.version = self.VERSION_2_0 if self.version is None: raise ValidationError('Invalid EDID version and revision.') ### ASCII Text Descriptors if 'Monitor_Name' in edid: self.monitor_name = edid['Monitor_Name'] if 'Monitor_Serial_Number' in edid: self.monitor_serial_number = edid['Monitor_Serial_Number'] if 'Monitor_Data_String' in edid: self.monitor_data_string = edid['Monitor_Data_String'] ### Basic display parameters bdp = edid['Basic_display_parameters'] self.bdp_video_input = bdp['Video_Input'] if not self.bdp_video_input: # Analog Input if bdp['Signal_Level_Standard'] == (0.700, 0.300): self.bdp_signal_level_standard = \ self.bdp_signal_level_std_0700_0300 elif bdp['Signal_Level_Standard'] == (0.714, 0.286): self.bdp_signal_level_standard = \ self.bdp_signal_level_std_0714_0286 elif bdp['Signal_Level_Standard'] == (1.000, 0.400): self.bdp_signal_level_standard = \ self.bdp_signal_level_std_1000_0400 elif bdp['Signal_Level_Standard'] == (0.700, 0.000): self.bdp_signal_level_standard = \ self.bdp_signal_level_std_0700_0000 else: raise ValidationError( 'Invalid signal level standard can not be parsed.' ) self.bdp_blank_to_black_setup = bdp['Blank-to-black_setup'] self.bdp_separate_syncs = bdp['Separate_syncs'] self.bdp_composite_sync = bdp['Composite_sync'] self.bdp_sync_on_green_video = bdp['Sync_on_green_video'] self.bdp_vsync_serration = bdp['Vsync_serration'] else: # Digital Input self.bdp_video_input_dfp_1 = bdp['Video_Input_DFP_1'] self.bdp_max_horizontal_image_size = bdp['Max_Horizontal_Image_Size'] self.bdp_max_vertical_image_size = bdp['Max_Vertical_Image_Size'] self.bdp_display_gamma = bdp['Display_Gamma'] self.bdp_feature_standby = bdp['Feature_Support']['Standby'] self.bdp_feature_suspend = bdp['Feature_Support']['Suspend'] self.bdp_feature_active_off = bdp['Feature_Support']['Active-off'] self.bdp_feature_display_type = bdp['Feature_Support']['Display_Type'] self.bdp_feature_standard_srgb = \ bdp['Feature_Support']['Standard-sRGB'] self.bdp_feature_pref_timing_mode = \ bdp['Feature_Support']['Preferred_Timing_Mode'] self.bdp_feature_default_gtf = bdp['Feature_Support']['Default_GTF'] ### Chromaticity self.chr_red_x = edid['Chromaticity']['Red_x'] self.chr_red_y = edid['Chromaticity']['Red_y'] self.chr_green_x = edid['Chromaticity']['Green_x'] self.chr_green_y = edid['Chromaticity']['Green_y'] self.chr_blue_x = edid['Chromaticity']['Blue_x'] self.chr_blue_y = edid['Chromaticity']['Blue_y'] self.chr_white_x = edid['Chromaticity']['White_x'] self.chr_white_y = edid['Chromaticity']['White_y'] ### Established Timings self.est_timings_720_400_70 = \ edid['Established_Timings']['720x400@70Hz'] self.est_timings_720_400_88 = \ edid['Established_Timings']['720x400@88Hz'] self.est_timings_640_480_60 = \ edid['Established_Timings']['640x480@60Hz'] self.est_timings_640_480_67 = \ edid['Established_Timings']['640x480@67Hz'] self.est_timings_640_480_72 = \ edid['Established_Timings']['640x480@72Hz'] self.est_timings_640_480_75 = \ edid['Established_Timings']['640x480@75Hz'] self.est_timings_800_600_56 = \ edid['Established_Timings']['800x600@56Hz'] self.est_timings_800_600_60 = \ edid['Established_Timings']['800x600@60Hz'] self.est_timings_800_600_72 = \ edid['Established_Timings']['800x600@72Hz'] self.est_timings_800_600_75 = \ edid['Established_Timings']['800x600@75Hz'] self.est_timings_832_624_75 = \ edid['Established_Timings']['832x624@75Hz'] self.est_timings_1024_768_87 = \ edid['Established_Timings']['1024x768@87Hz'] self.est_timings_1024_768_60 = \ edid['Established_Timings']['1024x768@60Hz'] self.est_timings_1024_768_70 = \ edid['Established_Timings']['1024x768@70Hz'] self.est_timings_1024_768_75 = \ edid['Established_Timings']['1024x768@75Hz'] self.est_timings_1280_1024_75 = \ edid['Established_Timings']['1280x1024@75Hz'] def populate_timings_from_parser(self, edid): for item in edid['Standard_Timings']: data = edid['Standard_Timings'][item] identification = re.search(r"^Identification_(\d+)$", item, re.IGNORECASE) if data['Image_aspect_ratio'] == (1, 1): aspect_ratio = StandardTiming.ASPECT_RATIO_1_1 elif data['Image_aspect_ratio'] == (16, 10): aspect_ratio = StandardTiming.ASPECT_RATIO_16_10 elif data['Image_aspect_ratio'] == (4, 3): aspect_ratio = StandardTiming.ASPECT_RATIO_4_3 elif data['Image_aspect_ratio'] == (5, 4): aspect_ratio = StandardTiming.ASPECT_RATIO_5_4 elif data['Image_aspect_ratio'] == (16, 9): aspect_ratio = StandardTiming.ASPECT_RATIO_16_9 else: raise ValidationError( 'Invalid aspect ratio can not be parsed.' ) timing = StandardTiming( identification=identification.group(1), user=self.user, horizontal_active=data['Horizontal_active'], vertical_active=data['Vertical_active'], refresh_rate=data['Refresh_Rate'], aspect_ratio=aspect_ratio ) self.standardtiming_set.add(timing) for item in edid['Descriptors']: data = edid['Descriptors'][item] identification = re.search(r"^Timing_Descriptor_(\d+)$", item, re.IGNORECASE) if not identification: # Not timing descriptor break timing = DetailedTiming( identification=identification.group(1), user=self.user, pixel_clock=data['Pixel_clock'], horizontal_active=data['Horizontal_Active'], horizontal_blanking=data['Horizontal_Blanking'], horizontal_sync_offset=data['Horizontal_Sync_Offset'], horizontal_sync_pulse_width=data[ 'Horizontal_Sync_Pulse_Width' ], horizontal_image_size=data['Horizontal_Image_Size'], horizontal_border=data['Horizontal_Border'], vertical_active=data['Vertical_Active'], vertical_blanking=data['Vertical_Blanking'], vertical_sync_offset=data['Vertical_Sync_Offset'], vertical_sync_pulse_width=data['Vertical_Sync_Pulse_Width'], vertical_image_size=data['Vertical_Image_Size'], vertical_border=data['Vertical_Border'], flags_interlaced=data['Flags']['Interlaced'], flags_stereo_mode=data['Flags']['Stereo_Mode'], flags_sync_scheme=data['Flags']['Sync_Scheme'] ) if (timing.flags_sync_scheme == DetailedTiming.Sync_Scheme.Digital_Separate): timing.flags_horizontal_polarity = \ data['Flags']['Horizontal_Polarity'] timing.flags_vertical_polarity = \ data['Flags']['Vertical_Polarity'] else: timing.flags_serrate = data['Flags']['Serrate'] if (timing.flags_sync_scheme == DetailedTiming.Sync_Scheme.Digital_Composite): timing.flags_composite_polarity = \ data['Flags']['Composite_Polarity'] else: timing.flags_sync_on_rgb = data['Flags']['Sync_On_RGB'] self.detailedtiming_set.add(timing) if 'Monitor_Range_Limits_Descriptor' in edid['Descriptors']: self.monitor_range_limits = True data = edid['Descriptors']['Monitor_Range_Limits_Descriptor'] self.mrl_min_horizontal_rate = data['Min_Horizontal_rate'] self.mrl_max_horizontal_rate = data['Max_Horizontal_rate'] self.mrl_min_vertical_rate = data['Min_Vertical_rate'] self.mrl_max_vertical_rate = data['Max_Vertical_rate'] self.mrl_max_pixel_clock = data['Max_Supported_Pixel_Clock'] self.mrl_secondary_gtf_curve_support = \ data['Secondary_GTF_curve_supported'] if self.mrl_secondary_gtf_curve_support: self.mrl_secondary_gtf_start_freq = \ data['Secondary_GTF']['start_frequency'] self.mrl_secondary_gtf_c = data['Secondary_GTF']['C'] self.mrl_secondary_gtf_m = data['Secondary_GTF']['M'] self.mrl_secondary_gtf_k = data['Secondary_GTF']['K'] self.mrl_secondary_gtf_j = data['Secondary_GTF']['J'] else: self.monitor_range_limits = False self.status = self.STATUS_TIMINGS_ADDED def get_absolute_url(self): return reverse('edid-detail', kwargs={'pk': self.pk}) def get_comments(self): comments = list(Comment.objects.filter(EDID=self) .select_related('user').all()) ordered_comments = self._get_nested_comments(comments, 0) return ordered_comments def _get_nested_comments(self, comments, level, parent=None): nested_comments = [] for comment in comments: if comment.level == level and comment.parent == parent: deep_nested_comments = {'comment': comment} deeper_nested_comments = self._get_nested_comments( comments, comment.level + 1, comment ) if deeper_nested_comments: deep_nested_comments['subcomments'] = \ deeper_nested_comments nested_comments.append(deep_nested_comments) if not nested_comments: return None return nested_comments def get_est_timings(self): """ Returns established timings in a dictionary. """ return [ {'horizontal_active': 720, 'vertical_active': 400, 'refresh_rate': 70, 'supported': self.est_timings_720_400_70}, {'horizontal_active': 720, 'vertical_active': 400, 'refresh_rate': 88, 'supported': self.est_timings_720_400_88}, {'horizontal_active': 640, 'vertical_active': 480, 'refresh_rate': 60, 'supported': self.est_timings_640_480_60}, {'horizontal_active': 640, 'vertical_active': 480, 'refresh_rate': 67, 'supported': self.est_timings_640_480_67}, {'horizontal_active': 640, 'vertical_active': 480, 'refresh_rate': 72, 'supported': self.est_timings_640_480_72}, {'horizontal_active': 640, 'vertical_active': 480, 'refresh_rate': 75, 'supported': self.est_timings_640_480_75}, {'horizontal_active': 800, 'vertical_active': 600, 'refresh_rate': 56, 'supported': self.est_timings_800_600_56}, {'horizontal_active': 800, 'vertical_active': 600, 'refresh_rate': 60, 'supported': self.est_timings_800_600_60}, {'horizontal_active': 800, 'vertical_active': 600, 'refresh_rate': 72, 'supported': self.est_timings_800_600_72}, {'horizontal_active': 800, 'vertical_active': 600, 'refresh_rate': 75, 'supported': self.est_timings_800_600_75}, {'horizontal_active': 832, 'vertical_active': 624, 'refresh_rate': 75, 'supported': self.est_timings_832_624_75}, {'horizontal_active': 1024, 'vertical_active': 768, 'refresh_rate': 87, 'supported': self.est_timings_1024_768_87}, {'horizontal_active': 1024, 'vertical_active': 768, 'refresh_rate': 60, 'supported': self.est_timings_1024_768_60}, {'horizontal_active': 1024, 'vertical_active': 768, 'refresh_rate': 70, 'supported': self.est_timings_1024_768_70}, {'horizontal_active': 1024, 'vertical_active': 768, 'refresh_rate': 75, 'supported': self.est_timings_1024_768_75}, {'horizontal_active': 1280, 'vertical_active': 1024, 'refresh_rate': 75, 'supported': self.est_timings_1280_1024_75}, ] def get_maximum_resolution(self): """ Returns parameters of the maximum resolution supported by timings. """ maximum_resolution = { 'horizontal_active': 0, 'vertical_active': 0, 'refresh_rate': 0 } for timing in self.get_est_timings(): if timing['supported']: maximum_resolution = self._update_maximum_resolution( maximum_resolution, timing['horizontal_active'], timing['vertical_active'], timing['refresh_rate'] ) for timing in self.standardtiming_set.all(): maximum_resolution = self._update_maximum_resolution( maximum_resolution, timing.horizontal_active, timing.vertical_active, timing.refresh_rate ) for timing in self.detailedtiming_set.all(): maximum_resolution = self._update_maximum_resolution( maximum_resolution, timing.horizontal_active, timing.vertical_active, timing.pixel_clock / 1000 ) return maximum_resolution def _update_maximum_resolution(self, maximum_resolution, horizontal_active, vertical_active, refresh_rate): """ Updates maximum_resolution if the new timing have higher resolution. Higher resolution is determined by the total number of pixels. """ maximum_resolution_pixels = maximum_resolution['horizontal_active'] \ * maximum_resolution['vertical_active'] if (horizontal_active * vertical_active) > maximum_resolution_pixels: maximum_resolution = { 'horizontal_active': horizontal_active, 'vertical_active': vertical_active, 'refresh_rate': refresh_rate } return maximum_resolution def __unicode__(self): return "%s %s" % (self.manufacturer.name, self.monitor_name)
class CredentialApplication(models.Model): """ An application to become PhysioNet credentialed """ RESEARCHER_CATEGORIES = ( (0, 'Student'), (7, 'Graduate Student'), (1, 'Postdoc'), (2, 'Academic Researcher'), (3, 'Hospital Researcher'), (4, 'Industry Researcher'), (5, 'Government Researcher'), (6, 'Independent Researcher'), ) REFERENCE_CATEGORIES = ( (0, 'Supervisor (required for students and Postdocs)'), (1, 'Colleague'), (2, 'Coauthor'), (3, 'Other'), ) COURSE_CATEGORIES = ( (0, 'Not for a course'), (1, 'I am taking a course using the data'), ) REFERENCE_RESPONSES = ( ('', '-----------'), (1, 'No'), (2, 'Yes') ) REJECT_ACCEPT_WITHDRAW = ( ('', '-----------'), (1, 'Reject'), (2, 'Accept'), (3, 'Withdrawn'), (4, 'Revoked') ) SUBMISSION_STATUS_LABELS = { 0: 'Not submitted.', 10: 'Initial review.', 20: 'Training check.', 30: 'Personal ID check.', 40: 'Reference check.', 50: 'Awaiting reference response.', 60: 'Final review.', 70: 'Rejected.', 80: 'Accepted.' } # Maximum size for training_completion_report MAX_REPORT_SIZE = 2 * 1024 * 1024 # Location for storing files associated with the application FILE_ROOT = os.path.join(settings.MEDIA_ROOT, 'credential-applications') slug = models.SlugField(max_length=20, unique=True, db_index=True) application_datetime = models.DateTimeField(auto_now_add=True) user = models.ForeignKey('user.User', related_name='credential_applications', on_delete=models.CASCADE) # Personal fields first_names = models.CharField(max_length=100, validators=[validators.validate_name]) last_name = models.CharField(max_length=50, validators=[validators.validate_name]) researcher_category = models.PositiveSmallIntegerField(choices=RESEARCHER_CATEGORIES) # Organization fields organization_name = models.CharField(max_length=200, validators=[validators.validate_organization]) job_title = models.CharField(max_length=60, validators=[validators.validate_job_title]) city = models.CharField(max_length=100, validators=[validators.validate_city]) state_province = models.CharField(max_length=100, validators=[validators.validate_state], default='', blank=True) country = models.CharField(max_length=2, choices=COUNTRIES) webpage = models.URLField(default='', blank=True) zip_code = models.CharField(max_length=60, validators=[validators.validate_zipcode]) suffix = models.CharField(max_length=60, validators=[validators.validate_suffix], default='', blank=True) # Human resources training training_course_name = models.CharField(max_length=100, default='', blank=True, validators=[validators.validate_training_course]) training_completion_date = models.DateField(null=True, blank=True) training_completion_report = models.FileField( upload_to=training_report_path, validators=[FileExtensionValidator( ['pdf'], 'File must be a pdf.')]) training_completion_report_url = models.URLField(blank=True, null=True) # Course info course_category = models.PositiveSmallIntegerField(choices=COURSE_CATEGORIES, null=True, blank=True) course_info = models.CharField(max_length=100, default='', blank=True, validators=[validators.validate_course]) # Reference reference_category = models.PositiveSmallIntegerField(null=True, blank=True, choices=REFERENCE_CATEGORIES) reference_name = models.CharField(max_length=202, default='', blank=True, validators=[validators.validate_reference_name]) reference_email = models.EmailField(default='', blank=True) reference_title = models.CharField(max_length=60, default='', blank=True, validators=[validators.validate_reference_title]) # 0 1 2 3 = pending, rejected, accepted, withdrawn status = models.PositiveSmallIntegerField(default=0, choices=REJECT_ACCEPT_WITHDRAW) # 0 10 20 30 40 50 60 70 80 = not submitted, initial, training, # personal ID, reference, reference response, final, rejected, accepted submission_status = models.PositiveSmallIntegerField(default=10) reference_contact_datetime = models.DateTimeField(null=True) reference_response_datetime = models.DateTimeField(null=True) # Whether reference verifies the applicant. 0 1 2 = null, no, yes reference_response = models.PositiveSmallIntegerField(default=0, choices=REFERENCE_RESPONSES) reference_response_text = models.CharField(max_length=2000, validators=[validators.validate_reference_response]) research_summary = models.CharField(max_length=1000, validators=[validators.validate_research_summary]) project_of_interest = models.ForeignKey('project.PublishedProject', null=True, on_delete=models.SET_NULL, limit_choices_to={'access_policy': 2},) decision_datetime = models.DateTimeField(null=True) responder = models.ForeignKey('user.User', null=True, related_name='responded_applications', on_delete=models.SET_NULL) responder_comments = models.CharField(max_length=500, default='', blank=True) revoked_datetime = models.DateTimeField(null=True) def file_root(self): """Location for storing files associated with the application""" return os.path.join(CredentialApplication.FILE_ROOT, self.slug) def get_full_name(self): return ' '.join([self.first_names, self.last_name]) def get_latest_by_user(self): return CredentialApplication.objects.filter(user=self.user).last() def is_latest_by_user(self): if self == CredentialApplication.objects.filter(user=self.user).last(): return True else: return False def is_legacy(self): return False def submission_status_label(self): return ActiveProject.SUBMISSION_STATUS_LABELS[self.submission_status] def time_elapsed(self): return (timezone.now() - self.first_date).days def _apply_decision(self, decision, responder): """ Reject, accept, or withdraw a credentialing application. Args: decision (int): 1 = reject, 2 = accept, 3 = withdraw. responder (str): User object """ self.responder = responder self.status = decision self.decision_datetime = timezone.now() self.save() def reject(self, responder): """ Reject a credentialing application. """ self._apply_decision(1, responder) def accept(self, responder): """ Reject a credentialing application. """ try: with transaction.atomic(): self._apply_decision(2, responder) # update the user credentials user = self.user user.is_credentialed = True user.credential_datetime = timezone.now() user.save() except DatabaseError: messages.error(request, 'Database error. Please try again.') def withdraw(self, responder): """ Reject a credentialing application. """ self._apply_decision(3, responder) def ref_known_flag(self): """ Returns True if the reference is known, else False. By "Known" we mean that the reference has been previously contacted. """ if CredentialApplication.objects.filter( reference_email__iexact=self.reference_email, reference_contact_datetime__isnull=False).exclude( reference_email=''): return True elif LegacyCredential.objects.filter( reference_email__iexact=self.reference_email).exclude( reference_email=''): return True else: return False def revoke(self): """ Revokes an approved application. """ # Set the application as unsucessful with the current datetime self.status = 4 self.revoked_datetime = timezone.now() # Removes credentialing from the user self.user.is_credentialed = False self.user.credential_datetime = None with transaction.atomic(): self.user.save() self.save() logger.info('Credentialing for user {0} has been removed.'.format( self.user.email)) def remove_contact_reference(self): """ Remove the date that indicates when the reference was contacted. Note that this may also affect the "known" status of the reference. """ self.reference_contact_datetime = None self.save()
class Migration(migrations.Migration): dependencies = [ ('cases', '0029_auto_20200710_2011'), ] operations = [ migrations.AddField( model_name='case', name='woonevaluatie_gepersonaliseerd_doel_1', field=models.CharField(blank=True, max_length=100, null=True, verbose_name='Woonevaluatie gepersonaliseerd doel 1'), ), migrations.AddField( model_name='case', name='woonevaluatie_gepersonaliseerd_doel_1_behaald', field=models.PositiveSmallIntegerField(blank=True, choices=[(1, 'Ja'), (2, 'Nee')], null=True, verbose_name='Woonevaluatie gepersonaliseerd doel 1 behaald'), ), migrations.AddField( model_name='case', name='woonevaluatie_gepersonaliseerd_doel_1_stand_van_zaken', field=models.TextField(blank=True, null=True, verbose_name='Woonevaluatie gepersonaliseerd doel 1, stand van zaken'), ), migrations.AddField( model_name='case', name='woonevaluatie_gepersonaliseerd_doel_2', field=models.CharField(blank=True, max_length=100, null=True, verbose_name='Woonevaluatie gepersonaliseerd doel 2'), ), migrations.AddField( model_name='case', name='woonevaluatie_gepersonaliseerd_doel_2_behaald', field=models.PositiveSmallIntegerField(blank=True, choices=[(1, 'Ja'), (2, 'Nee')], null=True, verbose_name='Woonevaluatie gepersonaliseerd doel 2 behaald'), ), migrations.AddField( model_name='case', name='woonevaluatie_gepersonaliseerd_doel_2_stand_van_zaken', field=models.TextField(blank=True, null=True, verbose_name='Woonevaluatie gepersonaliseerd doel 2, stand van zaken'), ), migrations.AddField( model_name='case', name='woonevaluatie_gepersonaliseerd_doel_3', field=models.CharField(blank=True, max_length=100, null=True, verbose_name='Woonevaluatie gepersonaliseerd doel 3'), ), migrations.AddField( model_name='case', name='woonevaluatie_gepersonaliseerd_doel_3_behaald', field=models.PositiveSmallIntegerField(blank=True, choices=[(1, 'Ja'), (2, 'Nee')], null=True, verbose_name='Woonevaluatie gepersonaliseerd doel 3 behaald'), ), migrations.AddField( model_name='case', name='woonevaluatie_gepersonaliseerd_doel_3_stand_van_zaken', field=models.TextField(blank=True, null=True, verbose_name='Woonevaluatie gepersonaliseerd doel 3, stand van zaken'), ), migrations.AddField( model_name='caseversion', name='woonevaluatie_gepersonaliseerd_doel_1', field=models.CharField(blank=True, max_length=100, null=True, verbose_name='Woonevaluatie gepersonaliseerd doel 1'), ), migrations.AddField( model_name='caseversion', name='woonevaluatie_gepersonaliseerd_doel_1_behaald', field=models.PositiveSmallIntegerField(blank=True, choices=[(1, 'Ja'), (2, 'Nee')], null=True, verbose_name='Woonevaluatie gepersonaliseerd doel 1 behaald'), ), migrations.AddField( model_name='caseversion', name='woonevaluatie_gepersonaliseerd_doel_1_stand_van_zaken', field=models.TextField(blank=True, null=True, verbose_name='Woonevaluatie gepersonaliseerd doel 1, stand van zaken'), ), migrations.AddField( model_name='caseversion', name='woonevaluatie_gepersonaliseerd_doel_2', field=models.CharField(blank=True, max_length=100, null=True, verbose_name='Woonevaluatie gepersonaliseerd doel 2'), ), migrations.AddField( model_name='caseversion', name='woonevaluatie_gepersonaliseerd_doel_2_behaald', field=models.PositiveSmallIntegerField(blank=True, choices=[(1, 'Ja'), (2, 'Nee')], null=True, verbose_name='Woonevaluatie gepersonaliseerd doel 2 behaald'), ), migrations.AddField( model_name='caseversion', name='woonevaluatie_gepersonaliseerd_doel_2_stand_van_zaken', field=models.TextField(blank=True, null=True, verbose_name='Woonevaluatie gepersonaliseerd doel 2, stand van zaken'), ), migrations.AddField( model_name='caseversion', name='woonevaluatie_gepersonaliseerd_doel_3', field=models.CharField(blank=True, max_length=100, null=True, verbose_name='Woonevaluatie gepersonaliseerd doel 3'), ), migrations.AddField( model_name='caseversion', name='woonevaluatie_gepersonaliseerd_doel_3_behaald', field=models.PositiveSmallIntegerField(blank=True, choices=[(1, 'Ja'), (2, 'Nee')], null=True, verbose_name='Woonevaluatie gepersonaliseerd doel 3 behaald'), ), migrations.AddField( model_name='caseversion', name='woonevaluatie_gepersonaliseerd_doel_3_stand_van_zaken', field=models.TextField(blank=True, null=True, verbose_name='Woonevaluatie gepersonaliseerd doel 3, stand van zaken'), ), migrations.AlterField( model_name='case', name='woonevaluatie_akkoord_zorgaanbieder_naam', field=models.CharField(blank=True, max_length=100, null=True, verbose_name='Woonevaluatie akkoord zorgaanbieder naam en functie'), ), migrations.AlterField( model_name='caseversion', name='woonevaluatie_akkoord_zorgaanbieder_naam', field=models.CharField(blank=True, max_length=100, null=True, verbose_name='Woonevaluatie akkoord zorgaanbieder naam en functie'), ), ]
class Migration(migrations.Migration): initial = True dependencies = [] operations = [ migrations.CreateModel( name='AuthGroup', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=150, unique=True)), ], options={ 'db_table': 'auth_group', 'managed': False, }, ), migrations.CreateModel( name='AuthGroupPermissions', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ], options={ 'db_table': 'auth_group_permissions', 'managed': False, }, ), migrations.CreateModel( name='AuthPermission', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=255)), ('codename', models.CharField(max_length=100)), ], options={ 'db_table': 'auth_permission', 'managed': False, }, ), migrations.CreateModel( name='AuthUser', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('password', models.CharField(max_length=128)), ('last_login', models.DateTimeField(blank=True, null=True)), ('is_superuser', models.IntegerField()), ('username', models.CharField(max_length=150, unique=True)), ('first_name', models.CharField(max_length=150)), ('last_name', models.CharField(max_length=150)), ('email', models.CharField(max_length=254)), ('is_staff', models.IntegerField()), ('is_active', models.IntegerField()), ('date_joined', models.DateTimeField()), ], options={ 'db_table': 'auth_user', 'managed': False, }, ), migrations.CreateModel( name='AuthUserGroups', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ], options={ 'db_table': 'auth_user_groups', 'managed': False, }, ), migrations.CreateModel( name='AuthUserUserPermissions', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ], options={ 'db_table': 'auth_user_user_permissions', 'managed': False, }, ), migrations.CreateModel( name='DjangoAdminLog', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('action_time', models.DateTimeField()), ('object_id', models.TextField(blank=True, null=True)), ('object_repr', models.CharField(max_length=200)), ('action_flag', models.PositiveSmallIntegerField()), ('change_message', models.TextField()), ], options={ 'db_table': 'django_admin_log', 'managed': False, }, ), migrations.CreateModel( name='DjangoContentType', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('app_label', models.CharField(max_length=100)), ('model', models.CharField(max_length=100)), ], options={ 'db_table': 'django_content_type', 'managed': False, }, ), migrations.CreateModel( name='DjangoMigrations', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('app', models.CharField(max_length=255)), ('name', models.CharField(max_length=255)), ('applied', models.DateTimeField()), ], options={ 'db_table': 'django_migrations', 'managed': False, }, ), migrations.CreateModel( name='DjangoSession', fields=[ ('session_key', models.CharField(max_length=40, primary_key=True, serialize=False)), ('session_data', models.TextField()), ('expire_date', models.DateTimeField()), ], options={ 'db_table': 'django_session', 'managed': False, }, ), migrations.CreateModel( name='Issue', fields=[ ('id', models.AutoField(db_column='Id', primary_key=True, serialize=False)), ('title', models.TextField(blank=True, null=True)), ('link', models.CharField(blank=True, max_length=160, null=True)), ('type', models.CharField(blank=True, max_length=7, null=True)), ('dep_id', models.IntegerField(blank=True, null=True)), ('people_id', models.CharField(blank=True, max_length=20, null=True)), ('year', models.IntegerField(blank=True, null=True)), ], options={ 'db_table': 'issue', 'managed': False, }, ), migrations.CreateModel( name='NewsEvents', fields=[ ('id', models.AutoField(db_column='Id', primary_key=True, serialize=False)), ('date', models.DateField(blank=True, null=True)), ('title', models.TextField(blank=True, null=True)), ('shorttext', models.TextField(blank=True, null=True)), ('text', models.TextField(blank=True, null=True)), ('type', models.CharField(blank=True, max_length=1, null=True)), ], options={ 'db_table': 'news_events', 'managed': False, }, ), migrations.CreateModel( name='People', fields=[ ('id', models.AutoField(db_column='Id', primary_key=True, serialize=False)), ('name', models.CharField(blank=True, max_length=80, null=True)), ('phone', models.CharField(blank=True, max_length=60, null=True)), ('email', models.CharField(blank=True, max_length=50, null=True)), ('post', models.TextField(blank=True, null=True)), ('name_link', models.TextField(blank=True, null=True)), ('type', models.CharField(blank=True, max_length=3, null=True)), ('info', models.TextField(blank=True, null=True)), ('hist', models.IntegerField(blank=True, null=True)), ('iss', models.CharField(blank=True, max_length=60, null=True)), ], options={ 'db_table': 'people', 'managed': False, }, ), migrations.CreateModel( name='Plav', fields=[ ('id', models.AutoField(db_column='Id', primary_key=True, serialize=False)), ('time_create', models.IntegerField(blank=True, null=True)), ('time_progn', models.IntegerField(blank=True, null=True)), ('vlazh', models.TextField(blank=True, null=True)), ('osadki', models.TextField(blank=True, null=True)), ('veter', models.TextField(blank=True, null=True)), ('temp', models.TextField(blank=True, null=True)), ('temp_priz', models.TextField(blank=True, null=True)), ('type', models.CharField(blank=True, max_length=12, null=True)), ('link', models.TextField(blank=True, null=True)), ('text', models.TextField(blank=True, null=True)), ], options={ 'db_table': 'PLAV', 'managed': False, }, ), migrations.CreateModel( name='Requests', fields=[ ('id', models.SmallAutoField(primary_key=True, serialize=False)), ('dept', models.TextField(blank=True, null=True)), ('chamber', models.SmallIntegerField(blank=True, null=True)), ('name', models.TextField(blank=True, null=True)), ('date', models.DateField()), ('text', models.TextField()), ('label', models.IntegerField(blank=True, null=True)), ('phone', models.BigIntegerField(blank=True, null=True)), ('comment', models.TextField(blank=True, null=True)), ('idrand', models.IntegerField()), ('dateok', models.DateField(blank=True, null=True)), ], options={ 'db_table': 'requests', 'managed': False, }, ), migrations.CreateModel( name='SiteFace', fields=[ ('id', models.AutoField(db_column='Id', primary_key=True, serialize=False)), ('paramname', models.TextField(blank=True, null=True)), ('paramvalue', models.TextField(blank=True, null=True)), ], options={ 'db_table': 'site_face', 'managed': False, }, ), migrations.CreateModel( name='SiteFaceEn', fields=[ ('id', models.AutoField(db_column='Id', primary_key=True, serialize=False)), ('paramname', models.TextField(blank=True, null=True)), ('paramvalue', models.TextField(blank=True, null=True)), ], options={ 'db_table': 'site_face_en', 'managed': False, }, ), migrations.CreateModel( name='Structure', fields=[ ('id', models.AutoField(db_column='Id', primary_key=True, serialize=False)), ('title', models.CharField(blank=True, max_length=80, null=True)), ('name_id', models.IntegerField(blank=True, null=True)), ('type', models.CharField(blank=True, max_length=5, null=True)), ('dep_id', models.IntegerField(blank=True, null=True)), ('info', models.TextField(blank=True, null=True)), ], options={ 'db_table': 'structure', 'managed': False, }, ), migrations.CreateModel( name='Towns', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('lat', models.FloatField(blank=True, null=True)), ('lon', models.FloatField(blank=True, null=True)), ('name', models.CharField(blank=True, db_column='Name', max_length=1, null=True)), ('regname', models.CharField(blank=True, db_column='RegName', max_length=1, null=True)), ('size', models.PositiveIntegerField(blank=True, null=True)), ('regnum', models.IntegerField()), ], options={ 'db_table': 'towns', 'managed': False, }, ), migrations.CreateModel( name='Vacanc', fields=[ ('id', models.AutoField(db_column='Id', primary_key=True, serialize=False)), ('vacancy', models.TextField(blank=True, null=True)), ('speciality', models.TextField(blank=True, null=True)), ('pay', models.CharField(blank=True, max_length=25, null=True)), ], options={ 'db_table': 'vacanc', 'managed': False, }, ), migrations.CreateModel( name='Wrf', fields=[ ('id', models.AutoField(db_column='Id', primary_key=True, serialize=False)), ('time_create', models.IntegerField(blank=True, null=True)), ('time_progn', models.IntegerField(blank=True, null=True)), ('vlazh', models.TextField(blank=True, null=True)), ('osadki', models.TextField(blank=True, null=True)), ('veter', models.TextField(blank=True, null=True)), ('temp', models.TextField(blank=True, null=True)), ('temp_priz', models.TextField(blank=True, null=True)), ('type', models.CharField(blank=True, max_length=12, null=True)), ('link', models.TextField(blank=True, null=True)), ('text', models.TextField(blank=True, null=True)), ], options={ 'db_table': 'WRF', 'managed': False, }, ), ]
class Migration(migrations.Migration): initial = True dependencies = [ ('taggit', '0002_auto_20150616_2121'), ('structure', '0001_squashed_0054'), ] operations = [ migrations.CreateModel( name='AzureService', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('uuid', waldur_core.core.fields.UUIDField()), ('available_for_all', models.BooleanField( default=False, help_text= 'Service will be automatically added to all customers projects if it is available for all' )), ('customer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='structure.Customer', verbose_name='organization')), ], options={ 'abstract': False, }, bases=(waldur_core.core.models.DescendantMixin, waldur_core.logging.loggers.LoggableMixin, models.Model), ), migrations.CreateModel( name='AzureServiceProjectLink', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('cloud_service_name', models.CharField(blank=True, max_length=255)), ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='structure.Project')), ('service', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='waldur_azure.AzureService')), ], options={ 'abstract': False, }, bases=(waldur_core.core.models.DescendantMixin, waldur_core.logging.loggers.LoggableMixin, models.Model), ), migrations.CreateModel( name='Image', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField( max_length=150, validators=[waldur_core.core.validators.validate_name], verbose_name='name')), ('uuid', waldur_core.core.fields.UUIDField()), ('backend_id', models.CharField(max_length=255, unique=True)), ], options={ 'abstract': False, }, bases=(waldur_core.core.models.BackendModelMixin, models.Model), ), migrations.CreateModel( name='InstanceEndpoint', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('local_port', models.IntegerField(validators=[ django.core.validators.MaxValueValidator(65535) ])), ('public_port', models.IntegerField(validators=[ django.core.validators.MaxValueValidator(65535) ])), ('protocol', models.CharField(blank=True, choices=[('tcp', 'tcp'), ('udp', 'udp')], max_length=3)), ('name', models.CharField(blank=True, choices=[('SSH', 'SSH'), ('Remote Desktop', 'Remote Desktop') ], max_length=255)), ], bases=(waldur_core.core.models.BackendModelMixin, models.Model), ), migrations.CreateModel( name='VirtualMachine', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('created', model_utils.fields.AutoCreatedField( default=django.utils.timezone.now, editable=False, verbose_name='created')), ('modified', model_utils.fields.AutoLastModifiedField( default=django.utils.timezone.now, editable=False, verbose_name='modified')), ('description', models.CharField(blank=True, max_length=500, verbose_name='description')), ('name', models.CharField( max_length=150, validators=[waldur_core.core.validators.validate_name], verbose_name='name')), ('uuid', waldur_core.core.fields.UUIDField()), ('error_message', models.TextField(blank=True)), ('latitude', models.FloatField(blank=True, null=True)), ('longitude', models.FloatField(blank=True, null=True)), ('runtime_state', models.CharField(blank=True, max_length=150, verbose_name='runtime state')), ('state', django_fsm.FSMIntegerField(choices=[(5, 'Creation Scheduled'), (6, 'Creating'), (1, 'Update Scheduled'), (2, 'Updating'), (7, 'Deletion Scheduled'), (8, 'Deleting'), (3, 'OK'), (4, 'Erred')], default=5)), ('backend_id', models.CharField(blank=True, max_length=255)), ('cores', models.PositiveSmallIntegerField( default=0, help_text='Number of cores in a VM')), ('ram', models.PositiveIntegerField(default=0, help_text='Memory size in MiB')), ('disk', models.PositiveIntegerField(default=0, help_text='Disk size in MiB')), ('min_ram', models.PositiveIntegerField( default=0, help_text='Minimum memory size in MiB')), ('min_disk', models.PositiveIntegerField( default=0, help_text='Minimum disk size in MiB')), ('image_name', models.CharField(blank=True, max_length=150)), ('key_name', models.CharField(blank=True, max_length=50)), ('key_fingerprint', models.CharField(blank=True, max_length=47)), ('user_data', models.TextField( blank=True, help_text= 'Additional data that will be added to instance on provisioning' )), ('start_time', models.DateTimeField(blank=True, null=True)), ('public_ips', waldur_core.core.fields.JSONField( blank=True, default=[], help_text='List of public IP addresses')), ('private_ips', waldur_core.core.fields.JSONField( blank=True, default=[], help_text='List of private IP addresses')), ('user_username', models.CharField(max_length=50)), ('user_password', models.CharField(max_length=50)), ('service_project_link', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='virtualmachines', to='waldur_azure.AzureServiceProjectLink')), ('tags', waldur_core.core.shims.TaggableManager( related_name='+', blank=True, help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags')), ], options={ 'abstract': False, }, bases=(waldur_core.core.models.DescendantMixin, waldur_core.core.models.BackendModelMixin, waldur_core.logging.loggers.LoggableMixin, models.Model), ), migrations.AddField( model_name='instanceendpoint', name='instance', field=models.ForeignKey( on_delete=django.db.models.deletion.PROTECT, related_name='endpoints', to='waldur_azure.VirtualMachine'), ), migrations.AddField( model_name='azureservice', name='projects', field=models.ManyToManyField( related_name='azure_services', through='waldur_azure.AzureServiceProjectLink', to='structure.Project'), ), migrations.AddField( model_name='azureservice', name='settings', field=models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, to='structure.ServiceSettings'), ), migrations.AlterUniqueTogether( name='azureserviceprojectlink', unique_together=set([('service', 'project')]), ), migrations.AlterUniqueTogether( name='azureservice', unique_together=set([('customer', 'settings')]), ), ]
class Migration(migrations.Migration): initial = True dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), ('products', '0001_initial'), ] operations = [ migrations.CreateModel( name='Collecting', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), ], ), migrations.CreateModel( name='Share', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('image', models.ImageField(upload_to='s_images/', verbose_name='이미지')), ('content', models.TextField(verbose_name='내용')), ('collection_name', models.CharField(max_length=100, verbose_name='컬렉션명')), ('collection_products', models.TextField(verbose_name='컬렉션 상품')), ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), ('user', models.ForeignKey( null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='작성자')), ], options={ 'verbose_name': '공유', 'verbose_name_plural': '공유', }, ), migrations.CreateModel( name='CollectionProduct', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('qunatity', models.PositiveSmallIntegerField(verbose_name='수량')), ('sub_total', models.PositiveIntegerField(verbose_name='가격')), ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), ('product', models.OneToOneField( on_delete=django.db.models.deletion.CASCADE, to='products.Product', verbose_name='상품')), ], options={ 'verbose_name': '컬렉션상품', 'verbose_name_plural': '컬렉션상품', }, ), migrations.CreateModel( name='Collection', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('collection_total', models.PositiveIntegerField(default=0, verbose_name='가격')), ('period', models.CharField(blank=True, choices=[('1W', '1주'), ('2W', '2주'), ('3W', '3주'), ('1M', '1달'), ('2M', '2달'), ('3M', '3달')], max_length=2, verbose_name='배송주기')), ('name', models.CharField(max_length=100, verbose_name='컬렉션명')), ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), ('collection_products', models.ManyToManyField(blank=True, related_name='collection_products', through='picks.Collecting', to='picks.CollectionProduct', verbose_name='컬렉션 상품')), ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='사용자')), ], options={ 'verbose_name': '컬렉션', 'verbose_name_plural': '컬렉션', }, ), migrations.AddField( model_name='collecting', name='collection', field=models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, to='picks.Collection', verbose_name='컬렉션'), ), migrations.AddField( model_name='collecting', name='collection_product', field=models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, to='picks.CollectionProduct', verbose_name='컬렉션 상품'), ), migrations.AlterUniqueTogether( name='collecting', unique_together={('collection', 'collection_product')}, ), ]
class Migration(migrations.Migration): initial = True dependencies = [] operations = [ migrations.CreateModel( name='Archdiocese', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=200)), ('city', models.CharField(max_length=200)), ('state', models.CharField(max_length=200)), ('mother_church_name', models.CharField(max_length=200)), ('mother_church_address', models.CharField(max_length=200)), ('mother_church_zipcode', models.CharField(max_length=200)), ('establish_date', models.DateTimeField(verbose_name='date established')), ('change_date', models.DateTimeField(verbose_name='date established')), ('end_date', models.DateTimeField(verbose_name='date established')), ], ), migrations.CreateModel( name='Diocese', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=200)), ('city', models.CharField(max_length=200)), ('state', models.CharField(max_length=200)), ('establish_date', models.DateTimeField(verbose_name='date established')), ('change_date', models.DateTimeField(verbose_name='date established')), ('end_date', models.DateTimeField(verbose_name='date established')), ('archdiocese', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='diocese.Archdiocese')), ], ), migrations.CreateModel( name='Statistics', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('year', models.PositiveSmallIntegerField()), ('total_priests', models.PositiveSmallIntegerField()), ('num_parishes', models.PositiveSmallIntegerField()), ('diocese', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='diocese.Diocese')), ], ), ]
class Migration(migrations.Migration): initial = True dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), ("artist", "0001_initial"), ] operations = [ migrations.CreateModel( name="Campaign", fields=[ ( "id", models.AutoField( auto_created=True, primary_key=True, serialize=False, verbose_name="ID", ), ), ( "amount", models.PositiveIntegerField( help_text= "The amount of money the artist wishes to raise"), ), ( "reason", models.CharField( help_text= "The reason why the artist is raising money, in a few words", max_length=40, ), ), ( "value_per_share", models.PositiveIntegerField( default=1, help_text= "The value (in dollars) per share the artist wishes to sell", ), ), ( "start_datetime", models.DateTimeField( db_index=True, default=django.utils.timezone.now, help_text= "When the campaign will start accepting investors", ), ), ( "end_datetime", models.DateTimeField( blank=True, db_index=True, help_text= "When the campaign ends and will no longer accept investors (no end date if blank)", null=True, ), ), ( "use_of_funds", models.TextField( blank=True, help_text="A description of how the funds will be used", null=True, ), ), ( "fans_percentage", models.PositiveSmallIntegerField( help_text= "The percentage of revenue that goes back to the fans (a value from 0-100)" ), ), ( "artist", models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, to="artist.Artist"), ), ], ), migrations.CreateModel( name="Expense", fields=[ ( "id", models.AutoField( auto_created=True, primary_key=True, serialize=False, verbose_name="ID", ), ), ( "expense", models.CharField( help_text= "A description of one of the expenses for the artist (eg. Studio cost)", max_length=30, ), ), ( "campaign", models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, to="campaign.Campaign", ), ), ], ), migrations.CreateModel( name="Investment", fields=[ ( "id", models.AutoField( auto_created=True, primary_key=True, serialize=False, verbose_name="ID", ), ), ( "transaction_datetime", models.DateTimeField(auto_now_add=True, db_index=True), ), ( "num_shares", models.PositiveSmallIntegerField( default=1, help_text= "The number of shares a user made in a transaction", ), ), ( "campaign", models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, to="campaign.Campaign", ), ), ( "user", models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, ), ), ], ), migrations.CreateModel( name="RevenueReport", fields=[ ( "id", models.AutoField( auto_created=True, primary_key=True, serialize=False, verbose_name="ID", ), ), ( "amount", models.PositiveIntegerField( help_text= "The amount of revenue generated (in dollars) being reported (since last report)" ), ), ("reported_datetime", models.DateTimeField(auto_now_add=True)), ( "campaign", models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, to="campaign.Campaign", ), ), ], ), migrations.AlterUniqueTogether(name="expense", unique_together={("campaign", "expense") }), ]
class Migration(migrations.Migration): initial = True dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), ('common', '0001_initial'), ] operations = [ migrations.CreateModel( name='Activity', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('title', models.CharField(max_length=120, verbose_name='标题')), ('cover', models.ImageField(max_length=200, upload_to='', verbose_name='封面图')), ('activity_type', models.PositiveSmallIntegerField(choices=[(0, '线上'), (1, '线下')], default=0, verbose_name='活动类型')), ('start_at', models.DateTimeField(blank=True, null=True, verbose_name='开始时间')), ('end_at', models.DateTimeField(blank=True, null=True, verbose_name='结束时间')), ('ticket_price', models.FloatField(default=0, verbose_name='费用(元)')), ('address', models.CharField(max_length=120, verbose_name='具体位置信息')), ('live_plateform', models.CharField(blank=True, max_length=120, verbose_name='直播平台')), ('live_address', models.CharField(blank=True, max_length=20, verbose_name='直播地址|微信群名')), ('total_user', models.PositiveIntegerField(default=0, verbose_name='活动人数')), ('contact_name', models.CharField(max_length=100, verbose_name='联系人')), ('contact_info', models.CharField(max_length=100, verbose_name='联系人电话|微信')), ('total_view', models.PositiveIntegerField(default=0, verbose_name='查看人数')), ('total_registration', models.PositiveIntegerField(default=0, verbose_name='报名个数')), ('create_at', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')), ('area', models.ForeignKey( on_delete=django.db.models.deletion.DO_NOTHING, to='common.Area', verbose_name='区域')), ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='发起人')), ], options={ 'db_table': 'activity', 'ordering': ['-id'], }, ), migrations.CreateModel( name='Registration', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('status', models.PositiveSmallIntegerField(choices=[(0, '成功')], default=0)), ('create_at', models.DateTimeField(auto_now_add=True, verbose_name='申请时间')), ('activity', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='activity.Activity', verbose_name='活动')), ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='申请人')), ], options={ 'db_table': 'registration', 'unique_together': {('user', 'activity')}, 'index_together': {('user', 'activity')}, }, ), ]
class Podcast(UUIDModel, TitleModel, DescriptionModel, LinkModel, LanguageModel, LastUpdateModel, UpdateInfoModel, LicenseModel, FlattrModel, ContentTypesModel, MergedIdsModel, OutdatedModel, AuthorModel, UrlsMixin, SlugsMixin, TagsMixin, MergedUUIDsMixin, TwitterModel, ): """ A Podcast """ logo_url = models.URLField(null=True, max_length=1000) group = models.ForeignKey(PodcastGroup, null=True, on_delete=models.PROTECT) group_member_name = models.CharField(max_length=30, null=True, blank=False) # if p1 is related to p2, p2 is also related to p1 related_podcasts = models.ManyToManyField('self', symmetrical=True) subscribers = models.PositiveIntegerField(default=0) restrictions = models.CharField(max_length=20, null=False, blank=True, default='') common_episode_title = models.CharField(max_length=100, null=False, blank=True) new_location = models.URLField(max_length=1000, null=True, blank=False) latest_episode_timestamp = models.DateTimeField(null=True) episode_count = models.PositiveIntegerField(default=0) hub = models.URLField(null=True) # Interval between episodes, within a specified range update_interval = models.PositiveSmallIntegerField(null=False, default=DEFAULT_UPDATE_INTERVAL) # factor to increase update_interval if an update does not find any # new episodes update_interval_factor = models.FloatField(default=1) # "order" value of the most recent episode (will be the highest of all) max_episode_order = models.PositiveIntegerField(null=True, default=None) # indicates whether the search index is up-to-date (or needs updating) search_index_uptodate = models.BooleanField(default=False, db_index=True) # search vector for full-text search search_vector = SearchVectorField(null=True) objects = PodcastManager() class Meta: index_together = [ ('last_update',), ] def subscriber_count(self): # TODO: implement return self.subscribers def group_with(self, other, grouptitle, myname, othername): """ Group the podcast with another one """ # TODO: move to PodcastGroup? if bool(self.group) and (self.group == other.group): # they are already grouped return group1 = self.group group2 = other.group if group1 and group2: raise ValueError('both podcasts already are in different groups') elif not (group1 or group2): # Form a new group import uuid group = PodcastGroup.objects.create(id=uuid.uuid1(), title=grouptitle) self.group_member_name = myname self.group = group self.save() other.group_member_name = othername other.group = group other.save() return group elif group1: # add other to self's group other.group_member_name = othername other.group = group1 other.save() return group1 else: # add self to other's group self.group_member_name = myname self.group = group2 self.save() return group2 def get_common_episode_title(self, num_episodes=100): if self.common_episode_title: return self.common_episode_title episodes = self.episode_set.all()[:num_episodes] # We take all non-empty titles titles = [_f for _f in (e.title for e in episodes) if _f] # there can not be a "common" title of a single title if len(titles) < 2: return None # get the longest common substring common_title = utils.longest_substr(titles) # but consider only the part up to the first number. Otherwise we risk # removing part of the number (eg if a feed contains episodes 100-199) common_title = re.search(r'^\D*', common_title).group(0) if len(common_title.strip()) < 2: return None return common_title def get_episode_before(self, episode): if not episode.released: return None return self.episode_set.filter(released__lt=episode.released).latest() def get_episode_after(self, episode): if not episode.released: return None return self.episode_set.filter(released__gt=episode.released).first() @property def scope(self): """ A podcast is always in the global scope """ return '' @property def as_scope(self): """ If models use this object as scope, they'll use this value """ return self.id.hex @property def display_title(self): """ a title for display purposes """ if self.title: return self.title if not self.url: logger.warn('Podcast with ID {podcast_id} does not have a URL' .format(podcast_id=self.id)) return _('Unknown Podcast') return _('Unknown Podcast from {domain}'.format( domain=utils.get_domain(self.url))) @property def next_update(self): interval = (timedelta(hours=self.update_interval) * self.update_interval_factor) return self.last_update + interval
class Migration(migrations.Migration): dependencies = [ migrations.swappable_dependency(settings.FILER_IMAGE_MODEL), ('cms', '0016_auto_20160608_1535'), ('simple_plugins', '0001_initial'), ] operations = [ migrations.CreateModel( name='SimplePageTeaserPluginModel', fields=[ ('cmsplugin_ptr', models.OneToOneField( auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='simple_plugins_simplepageteaserpluginmodel', serialize=False, to='cms.CMSPlugin')), ('flavor', models.PositiveSmallIntegerField( choices=[(1, 'Bold headings and action button' ), (2, 'Photo and read-more button'), ( 3, 'Simple'), (4, 'More stories link')])), ('override_title', models.CharField(blank=True, max_length=80)), ('subtitle', models.CharField(blank=True, max_length=80)), ('content', djangocms_text_ckeditor.fields.HTMLField(blank=True)), ('image', filer.fields.image.FilerImageField( blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.FILER_IMAGE_MODEL)), ('page', models.ForeignKey( null=True, on_delete=django.db.models.deletion.SET_NULL, to='cms.Page')), ], options={ 'abstract': False, }, bases=('cms.cmsplugin', ), ), migrations.AlterField( model_name='simpletextpluginmodel', name='flavor', field=models.PositiveSmallIntegerField( choices=[(1, 'Not yet implemented')]), ), migrations.AlterField( model_name='textandimagepluginmodel', name='flavor', field=models.PositiveSmallIntegerField( choices=[(1, 'Not yet implemented')]), ), ]
class Migration(migrations.Migration): initial = True dependencies = [ ('dashboard', '0008_auto_20200429_2301'), ] operations = [ migrations.CreateModel( name='ArtEvents', fields=[ ('eid', models.CharField(db_column='Eid', max_length=60, primary_key=True, serialize=False)), ('title', models.CharField(blank=True, max_length=60, null=True)), ('e_image', models.CharField(blank=True, max_length=200, null=True)), ('seatmap', models.CharField(blank=True, max_length=200, null=True)), ], options={ 'db_table': 'Art_Events', 'managed': False, }, ), migrations.CreateModel( name='Artist', fields=[ ('aid', models.CharField(db_column='Aid', max_length=20, primary_key=True, serialize=False)), ('artist_name', models.CharField(blank=True, max_length=40, null=True)), ('info', models.CharField(blank=True, max_length=255, null=True)), ], options={ 'db_table': 'Artist', 'managed': False, }, ), migrations.CreateModel( name='AuthGroup', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=150, unique=True)), ], options={ 'db_table': 'auth_group', 'managed': False, }, ), migrations.CreateModel( name='AuthGroupPermissions', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ], options={ 'db_table': 'auth_group_permissions', 'managed': False, }, ), migrations.CreateModel( name='AuthPermission', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=255)), ('codename', models.CharField(max_length=100)), ], options={ 'db_table': 'auth_permission', 'managed': False, }, ), migrations.CreateModel( name='AuthUser', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('password', models.CharField(max_length=128)), ('last_login', models.DateTimeField(blank=True, null=True)), ('is_superuser', models.IntegerField()), ('username', models.CharField(max_length=150, unique=True)), ('first_name', models.CharField(max_length=30)), ('last_name', models.CharField(max_length=150)), ('email', models.CharField(max_length=254)), ('is_staff', models.IntegerField()), ('is_active', models.IntegerField()), ('date_joined', models.DateTimeField()), ], options={ 'db_table': 'auth_user', 'managed': False, }, ), migrations.CreateModel( name='AuthUserGroups', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ], options={ 'db_table': 'auth_user_groups', 'managed': False, }, ), migrations.CreateModel( name='AuthUserUserPermissions', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ], options={ 'db_table': 'auth_user_user_permissions', 'managed': False, }, ), migrations.CreateModel( name='DashboardArtist', fields=[ ('aid', models.CharField(db_column='Aid', max_length=20, primary_key=True, serialize=False)), ('artist_name', models.CharField(max_length=20)), ('info', models.CharField(max_length=50)), ], options={ 'db_table': 'dashboard_artist', 'managed': False, }, ), migrations.CreateModel( name='DashboardExhibition', fields=[ ('eid', models.CharField(db_column='Eid', max_length=20, primary_key=True, serialize=False)), ('background', models.CharField(max_length=20)), ], options={ 'db_table': 'dashboard_exhibition', 'managed': False, }, ), migrations.CreateModel( name='DashboardHeld', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('eid', models.CharField(db_column='Eid', max_length=20)), ('lid', models.CharField(db_column='Lid', max_length=20)), ], options={ 'db_table': 'dashboard_held', 'managed': False, }, ), migrations.CreateModel( name='DashboardLocation', fields=[ ('lid', models.CharField(db_column='Lid', max_length=20, primary_key=True, serialize=False)), ('longitude', models.CharField(max_length=20)), ('latitude', models.CharField(max_length=20)), ('address', models.CharField(max_length=20)), ('zipcode', models.CharField(max_length=20)), ], options={ 'db_table': 'dashboard_location', 'managed': False, }, ), migrations.CreateModel( name='DashboardPerform', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('eid', models.CharField(db_column='Eid', max_length=20)), ('aid', models.CharField(db_column='Aid', max_length=20)), ], options={ 'db_table': 'dashboard_perform', 'managed': False, }, ), migrations.CreateModel( name='DashboardTheater', fields=[ ('eid', models.CharField(db_column='Eid', max_length=20, primary_key=True, serialize=False)), ('genre', models.CharField(max_length=20)), ], options={ 'db_table': 'dashboard_theater', 'managed': False, }, ), migrations.CreateModel( name='DashboardTime', fields=[ ('time_serial', models.CharField(max_length=20, primary_key=True, serialize=False)), ('date', models.CharField(max_length=20)), ], options={ 'db_table': 'dashboard_time', 'managed': False, }, ), migrations.CreateModel( name='DjangoAdminLog', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('action_time', models.DateTimeField()), ('object_id', models.TextField(blank=True, null=True)), ('object_repr', models.CharField(max_length=200)), ('action_flag', models.PositiveSmallIntegerField()), ('change_message', models.TextField()), ], options={ 'db_table': 'django_admin_log', 'managed': False, }, ), migrations.CreateModel( name='DjangoContentType', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('app_label', models.CharField(max_length=100)), ('model', models.CharField(max_length=100)), ], options={ 'db_table': 'django_content_type', 'managed': False, }, ), migrations.CreateModel( name='DjangoMigrations', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('app', models.CharField(max_length=255)), ('name', models.CharField(max_length=255)), ('applied', models.DateTimeField()), ], options={ 'db_table': 'django_migrations', 'managed': False, }, ), migrations.CreateModel( name='DjangoSession', fields=[ ('session_key', models.CharField(max_length=40, primary_key=True, serialize=False)), ('session_data', models.TextField()), ('expire_date', models.DateTimeField()), ], options={ 'db_table': 'django_session', 'managed': False, }, ), migrations.CreateModel( name='Location', fields=[ ('lid', models.CharField(db_column='Lid', max_length=20, primary_key=True, serialize=False)), ('longitude', models.CharField(blank=True, max_length=30, null=True)), ('latitude', models.CharField(blank=True, max_length=30, null=True)), ('address', models.CharField(blank=True, max_length=80, null=True)), ('zipcode', models.CharField(blank=True, max_length=20, null=True)), ], options={ 'db_table': 'Location', 'managed': False, }, ), migrations.CreateModel( name='Payment', fields=[ ('pid', models.CharField(db_column='Pid', max_length=20, primary_key=True, serialize=False)), ('address', models.CharField(blank=True, max_length=200, null=True)), ('fname', models.CharField(blank=True, max_length=50, null=True)), ('lname', models.CharField(blank=True, max_length=50, null=True)), ('ticket_num', models.CharField(blank=True, max_length=20, null=True)), ('total_price', models.CharField(blank=True, max_length=20, null=True)), ], options={ 'db_table': 'Payment', 'managed': False, }, ), migrations.CreateModel( name='Subscription', fields=[ ('sid', models.CharField(db_column='Sid', max_length=100, primary_key=True, serialize=False)), ('email', models.CharField(blank=True, max_length=100, null=True)), ('s_name', models.CharField(blank=True, max_length=100, null=True)), ], options={ 'db_table': 'Subscription', 'managed': False, }, ), migrations.CreateModel( name='TicketHas', fields=[ ('tid', models.CharField(db_column='Tid', max_length=20, primary_key=True, serialize=False)), ('price', models.IntegerField(blank=True, null=True)), ('amount', models.IntegerField(blank=True, null=True)), ('refund_policy', models.CharField(blank=True, max_length=20, null=True)), ], options={ 'db_table': 'Ticket_has', 'managed': False, }, ), migrations.CreateModel( name='Time', fields=[ ('time_serial', models.CharField(max_length=20, primary_key=True, serialize=False)), ('date_ymd', models.CharField(blank=True, db_column='date_YMD', max_length=20, null=True)), ], options={ 'db_table': 'Time', 'managed': False, }, ), migrations.CreateModel( name='Buy', fields=[ ('pid', models.OneToOneField(db_column='Pid', on_delete=django.db.models.deletion.DO_NOTHING, primary_key=True, serialize=False, to='dashboard.Payment')), ], options={ 'db_table': 'buy', 'managed': False, }, ), migrations.CreateModel( name='Concert', fields=[ ('eid', models.OneToOneField(db_column='Eid', on_delete=django.db.models.deletion.DO_NOTHING, primary_key=True, serialize=False, to='dashboard.ArtEvents')), ('concert_type', models.CharField(blank=True, max_length=20, null=True)), ], options={ 'db_table': 'Concert', 'managed': False, }, ), migrations.CreateModel( name='Exhibition', fields=[ ('eid', models.OneToOneField(db_column='Eid', on_delete=django.db.models.deletion.DO_NOTHING, primary_key=True, serialize=False, to='dashboard.ArtEvents')), ('background', models.CharField(blank=True, max_length=20, null=True)), ], options={ 'db_table': 'Exhibition', 'managed': False, }, ), migrations.CreateModel( name='Held', fields=[ ('eid', models.OneToOneField(db_column='Eid', on_delete=django.db.models.deletion.DO_NOTHING, primary_key=True, serialize=False, to='dashboard.ArtEvents')), ], options={ 'db_table': 'held', 'managed': False, }, ), migrations.CreateModel( name='Perform', fields=[ ('eid', models.OneToOneField(db_column='Eid', on_delete=django.db.models.deletion.DO_NOTHING, primary_key=True, serialize=False, to='dashboard.ArtEvents')), ], options={ 'db_table': 'Perform', 'managed': False, }, ), migrations.CreateModel( name='Theater', fields=[ ('eid', models.OneToOneField(db_column='Eid', on_delete=django.db.models.deletion.DO_NOTHING, primary_key=True, serialize=False, to='dashboard.ArtEvents')), ('genre', models.CharField(blank=True, max_length=20, null=True)), ], options={ 'db_table': 'Theater', 'managed': False, }, ), migrations.CreateModel( name='TOn', fields=[ ('eid', models.OneToOneField(db_column='Eid', on_delete=django.db.models.deletion.DO_NOTHING, primary_key=True, serialize=False, to='dashboard.ArtEvents')), ], options={ 'db_table': 'T_on', 'managed': False, }, ), ]
class Process(models.Model): '''A process is an running instance of a Workflow. A workflow can be executed multiple times (and by different people), we call each run of this workflow, a process. Attributes: :id (int): Private sequential identificator :workflow (Workflow): :class:`workflow.models.Workflow` instance this process is based on :executioner (User): :class:`django.contrib.auth.models.User` this process is executed by :hash (str): Public hash that identifies the process instance publicly :start_date (datetime): Creation date :end_date (datetime): End date :status (smallint): Indicator of the status of execution of the process :removed (boolean): Logical indicator of removal status of this workflow ''' # Status literals, representing the translation to the statuses the process can be in RUNNING = 1 FINISHED = 2 CANCELED = 3 OVERDUE = 4 WAITING = 5 STATUS = ((RUNNING, 'Process is running'), (FINISHED, 'Process has ended successfully'), (CANCELED, 'Process was canceled'), (OVERDUE, 'Process has gone over end_date'), (WAITING, 'Process is waiting for users availability')) workflow = models.ForeignKey(Workflow) title = models.CharField(max_length=200, null=True) description = models.CharField(max_length=2000, null=True, default="") executioner = models.ForeignKey(User) hash = models.CharField(max_length=50, unique=True) start_date = models.DateTimeField(auto_now_add=True) end_date = models.DateTimeField(null=True) status = models.PositiveSmallIntegerField(choices=STATUS, default=RUNNING) removed = models.BooleanField(default=False) days_after_delay = models.IntegerField(default=0) send_notification_until = models.DateTimeField(null=True) days_before_delay = models.IntegerField(default=0) @staticmethod def statusCode(interpret_code): for code, translation in Process.STATUS: if code == interpret_code: return translation return "Unknown" def __unicode__(self): #return u'%s (started %s)' % (self.title or self.workflow, self.start_date.strftime("%Y-%m-%d %H:%M")) return u'%s' % (self.title or self.workflow) def tasks(self): return ProcessTask.all(process=self) def getAllUsersEnvolved(self, notification=True): tmp = [] tasks = self.tasks() for task in tasks: tmp += task.getAllUsersEnvolved(notification) # Remove duplicates seq = set(tmp) return list(seq) @transaction.atomic def cancel(self): ''' Cancels a process, also canceling all pending tasks in it and requests related with it too ''' ptasks = self.tasks() for ptask in ptasks: if ptask.status == ProcessTask.WAITING_AVAILABILITY or\ ptask.status == ProcessTask.REJECTED or\ ptask.status == ProcessTask.WAITING or\ ptask.status == ProcessTask.RUNNING: ptask.status = ProcessTask.CANCELED ptask.save() requests = Request.all(process=self.hash) for request in requests: request.remove() self.status = Process.CANCELED self.save() @transaction.atomic def move(self): ''' Reaccess tasks status (so we can move the state machine forward) ''' ptasks = self.tasks() if self.status == Process.WAITING: watasks = ProcessTask.all(process=self).filter( status=ProcessTask.WAITING_AVAILABILITY).count() if watasks == 0: self.status = Process.RUNNING self.save() History.new(event=History.RUN, actor=self.executioner, object=self) self.move() else: wlist = ptasks.filter(status=ProcessTask.WAITING) for ptask in wlist: move = True deps = ptask.task.dependencies() for dep in deps: pdep = ptasks.get(task=dep.dependency) if not (pdep.status == ProcessTask.FINISHED or pdep.status == ProcessTask.CANCELED): move = False if ptask.allow_sbe: ptus = ProcessTaskUser.all(processtask=pdep) for ptu in ptus: if ptu.status == ProcessTaskUser.FINISHED or ptu.status == ProcessTaskUser.CANCELED or ptu.finished: ptask.status = ProcessTask.RUNNING ptus2 = ProcessTaskUser.all(processtask=ptask) for ptu2 in ptus2: if (ptu.user == ptu2.user): ptu2.status = ProcessTaskUser.RUNNING ptu2.save() History.new(event=History.RUN, actor=ptu.user, object=ptu, authorized=[ptu.user], related=[ptask.process]) ptask.save() if move: ptask.status = ProcessTask.RUNNING ptus = ProcessTaskUser.all(processtask=ptask) for ptu in ptus: if ptu.status == ProcessTaskUser.ACCEPTED or ptu.status == ProcessTaskUser.WAITING: ptu.status = ProcessTaskUser.RUNNING ptu.save() ptask.save() pusers = ptask.users() for puser in pusers: History.new(event=History.RUN, actor=puser.user, object=puser, authorized=[puser.user], related=[ptask.process]) if ptasks.filter( Q(status=ProcessTask.WAITING) | Q(status=ProcessTask.RUNNING) | Q(status=ProcessTask.IMPROVING)).count( ) == 0: # and self.status != Process.FINISHED: self.status = Process.FINISHED self.end_date = timezone.now() History.new(event=History.DONE, actor=self.executioner, object=self) self.save() def progress(self): all = ProcessTask.all(process=self).count() done = ProcessTask.all(process=self).filter( Q(status=ProcessTask.FINISHED) | Q(status=ProcessTask.CANCELED)).count() try: return done * 100 / all except ZeroDivisionError: return 0 def changeReminders(self, reminders): self.days_after_delay = reminders.get('after') self.send_notification_until = reminders.get('repeatUpTo') self.days_before_delay = reminders.get('before') self.save() def start(self): ptasks = self.tasks() for ptask in ptasks: if ptask.status == ProcessTask.WAITING_AVAILABILITY: # or ptask.status == ProcessTask.REJECTED: ptask.status = ProcessTask.WAITING ptask.save() ptu = ProcessTaskUser.all(processtask=ptask) for ptuser in ptu: if ptuser.status == ProcessTaskUser.ACCEPTED: ptuser.status = ProcessTaskUser.WAITING ptuser.save() self.status = Process.RUNNING self.save() self.move() def validateAcceptions(self): ptasks = self.tasks() for ptask in ptasks: for ptasksUser in ProcessTaskUser.all(processtask=ptask): if(ptasksUser.status == ProcessTaskUser.WAITING or \ ptasksUser.status == ProcessTaskUser.REJECTED ): return False return True def resignRejectedUser(self, oldUser, newUser): #Resign all tasks that the old user belongs ptasks = self.tasks() for ptask in ptasks: ptask.resignRejectedUser(oldUser, newUser) self.save() class Meta: ordering = ["-id"] verbose_name_plural = "Processes" @staticmethod def allWithDelay(): tmp = Process.objects.filter(Q(removed=False) & Q(Q(status=Process.RUNNING) | Q(status=Process.WAITING)))\ .exclude(days_after_delay = 0)\ .filter(send_notification_until__gte=timezone.now()) return tmp @staticmethod def allWithNotificationBeforeDelay(): tmp = Process.objects.filter(Q(removed=False) & Q(Q(status=Process.RUNNING) | Q(status=Process.WAITING))) \ .exclude(days_before_delay=0) return tmp @staticmethod def all(workflow=None, executioner=None): ''' Returns all valid process instances (excluding logically removed processes) ''' tmp = Process.objects.filter(removed=False) if workflow != None: tmp = tmp.filter(workflow=workflow) if executioner != None: tmp = tmp.filter(executioner=executioner) # else return tmp
class Maps(CMSPlugin): """ Integration of a map with support for different providers """ translatable_content_excluded_fields = [ 'address', 'zipcode', 'width', 'height' ] map_provider = models.CharField(_("map provider"), max_length=16, blank=False, null=False, choices=PROVIDERS, default=PROVIDERS[0][0]) title = models.CharField(_("map title"), max_length=100, blank=True, null=True) address = models.CharField(_("address"), max_length=150) zipcode = models.CharField(_("zip code"), max_length=30) city = models.CharField(_("city"), max_length=100) content = models.CharField( _("additional content"), max_length=255, blank=True, help_text=_('Displayed under address in the bubble.')) style = models.TextField( _("custom map style"), blank=True, help_text=_( 'Provide a valid JSON configuration (escaped). See ' 'developers.google.com/maps/documentation/javascript/styling')) ZOOM_LEVELS = [(c, str(c)) for c in range(22)] zoom = models.PositiveSmallIntegerField(_("zoom level"), choices=ZOOM_LEVELS, default=13) lat = models.DecimalField( _('latitude'), max_digits=10, decimal_places=6, null=True, blank=True, help_text=_('Use latitude & longitude to fine tune the map position.')) lng = models.DecimalField(_('longitude'), max_digits=10, decimal_places=6, null=True, blank=True) route_planer_title = models.CharField( _("route planner title"), max_length=150, blank=True, null=True, default=_('Calculate your fastest way to here')) route_planer = models.BooleanField(_("route planner"), default=False) width = models.CharField(_('width'), max_length=6, default='100%', help_text=_('Plugin width (in px, em, %).')) height = models.CharField(_('height'), max_length=6, default='400px', help_text=_('Plugin height (in px, em).')) info_window = models.BooleanField(_('info window'), default=True, help_text=_('Show textbox over marker')) scrollwheel = models.BooleanField( _('scrollwheel'), default=True, help_text=_('Enable scrollwheel zooming on the map')) double_click_zoom = models.BooleanField(_('double click zoom'), default=True) draggable = models.BooleanField(_('draggable'), default=True) keyboard_shortcuts = models.BooleanField(_('keyboard shortcuts'), default=True) pan_control = models.BooleanField(_('Pan control'), default=True) zoom_control = models.BooleanField(_('Zoom control'), default=True) street_view_control = models.BooleanField(_('Street View control'), default=True) layers_control = models.BooleanField(_('Layers control'), default=True) scale_bar = models.BooleanField(_('Scale bar'), default=False) def __str__(self): return "%s (%s, %s %s)" % ( self.get_title(), self.address, self.zipcode, self.city, ) def get_title(self): """Title displayed as a map header""" return _("Map") if self.title is None else self.title def get_lat_lng(self): """Lat/Lon tuple or None (if unset)""" if self.lat and self.lng: return self.lat, self.lng return None
class ProcessTask(models.Model): '''A task assignment, in the context of a Process. This model connects several workflow related tasks with a process instance. Defining a process implies setting up process tasks. Attributes: :process (Process): :class:`Process` related with this instance :task (Task): :class:`workflow.models.Task` related with this instance :status (smallint): Indicator of the status of execution of the process :deadline (datetime): Date this Process related Task should end ''' # Status literals, representing the translation to the statuses the process can be in WAITING = 1 RUNNING = 2 FINISHED = 3 CANCELED = 4 OVERDUE = 5 IMPROVING = 6 WAITING_AVAILABILITY = 7 REJECTED = 8 STATUS = ((WAITING, 'Task is waiting execution'), (RUNNING, 'Task is running'), (FINISHED, 'Task has ended successfully'), (CANCELED, 'Task was canceled'), (OVERDUE, 'Task has gone over end_date'), (IMPROVING, 'Task is running again to be improved'), (WAITING_AVAILABILITY, 'Task is waiting for users availability'), (REJECTED, 'Task has some users that rejected this task')) process = models.ForeignKey(Process) task = models.ForeignKey(Task) status = models.PositiveSmallIntegerField(choices=STATUS, default=WAITING) deadline = models.DateTimeField() hash = models.CharField(max_length=50) removed = models.BooleanField(default=False) allow_sbe = models.BooleanField(default=False) @staticmethod def statusCode(code): try: return dict(ProcessTask.STATUS)[code] except KeyError: return "Unknown" def __unicode__(self): return u'%s - %s' % (self.task, self.process) def rpr(self): ts = Task.all().get_subclass(id=self.task.id) return "%s/%s" % (ts.type(), self.hash) def users(self): return ProcessTaskUser.all(processtask=self) def user(self, user): return ProcessTaskUser.all(processtask=self).get(user=user) def refreshState(self): #translate #Verificar se todos aceitaram # Se sim, mudar estado para waiting # Se nao, manter estado de waitingavailability # Se alguem recusou, mudar estado para rejected allUser = ProcessTaskUser \ .all(processtask=self, reassigned=False) allAccepted = True for usr in allUser: #if usr.status == ProcessTaskUser.REJECTED: #self.status = ProcessTask.REJECTED if usr.status == ProcessTaskUser.WAITING: allAccepted = False if allAccepted: #Refresh the status of all taskuser and the task too self.status = ProcessTask.WAITING for usr in allUser: if usr.status == ProcessTaskUser.ACCEPTED: #Only change the accepted because the reject we want to keep rejected usr.status = ProcessTaskUser.WAITING usr.save() self.save() def resignRejectedUser(self, oldUser, newUser): tasks = ProcessTaskUser.all(processtask=self).filter(user=oldUser) exists = ProcessTaskUser.all(processtask=self).filter( user=newUser).count() if exists == 0 or int(oldUser) == int(newUser): for task in tasks: task.changeUser(newUser) History.new(event=History.ADD, actor=task.processtask.process.executioner, object=task.processtask.process, authorized=[newUser], related=[task.processtask.process]) else: for task in tasks: task.delete() self.save() def move(self, force=False, finishTask=True): missing = ProcessTaskUser\ .all(processtask=self, reassigned=False) \ .filter(~Q(status=ProcessTaskUser.REJECTED), finished=False).count() if missing == 0: if (finishTask): self.status = ProcessTask.FINISHED self.save() # IF WE ARE BEFORE A FORM TASK, UPLOAD THE EXPORT RESULTS PASSING THEM BELOW, bit of a hack task = Task.objects.get_subclass(id=self.task.id) self.__exportForm(task) #self.process.move() else: if force: self.__exportForm(Task.objects.get_subclass(id=self.task.id)) self.process.move() def getAllUsersEnvolved(self, notification=True): tmp = [] for taskUser in ProcessTaskUser.all(processtask=self): if taskUser.getUser() not in tmp: if ((notification and taskUser.getUser().profile.notification == True) or notification == False ) and taskUser.status != ProcessTaskUser.REJECTED: tmp += [taskUser.getUser()] return tmp def __exportForm(self, task): if task.type() == 'form.FormTask' and task.output_resources: exporter = task.get_exporter('xlsx', self) export = exporter.export(export_file=True) users = self.users() if len(users) > 0: result = users[0].getResult() if result: ex_files = list(result.outputs.all().select_subclasses()) for fil in ex_files: if fil.filename == export.filename: result.outputs.remove(fil) result.outputs.add(export) def calculateStart(self): deps = self.task.dependencies().values_list('id', flat=True) pdeps = ProcessTask.all().filter(task__in=deps).order_by('-deadline') if pdeps.count() > 0: return pdeps[0].deadline return self.process.start_date @staticmethod def all(process=None): ''' Returns all valid process task instances (excluding logically removed process tasks) ''' tmp = ProcessTask.objects.filter(removed=False) if process != None: tmp = tmp.filter(process=process) return tmp
class Migration(migrations.Migration): initial = True dependencies = [ ('profiles', '0001_initial'), ('contenttypes', '0002_remove_content_type_name'), ] operations = [ migrations.CreateModel( name='Answer', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('created_on', models.DateTimeField(auto_now_add=True)), ('updated_on', models.DateTimeField(auto_now=True)), ('uuid', shortuuidfield.fields.ShortUUIDField(blank=True, editable=False, max_length=22)), ('position', models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='Position')), ('object_id', models.PositiveIntegerField()), ('is_correct', models.BooleanField(default=False)), ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')), ], options={ 'ordering': ['position'], 'db_table': 'curricula_answers', }, ), migrations.CreateModel( name='Curriculum', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('created_on', models.DateTimeField(auto_now_add=True)), ('updated_on', models.DateTimeField(auto_now=True)), ('uuid', shortuuidfield.fields.ShortUUIDField(blank=True, editable=False, max_length=22)), ('name', models.CharField(db_index=True, max_length=200)), ('published_on', models.DateTimeField(blank=True, null=True, verbose_name='date published')), ('image', models.ImageField(blank=True, upload_to='')), ], options={ 'verbose_name_plural': 'curricula', 'db_table': 'curricula_curricula', }, ), migrations.CreateModel( name='Lesson', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('created_on', models.DateTimeField(auto_now_add=True)), ('updated_on', models.DateTimeField(auto_now=True)), ('uuid', shortuuidfield.fields.ShortUUIDField(blank=True, editable=False, max_length=22)), ('name', models.CharField(max_length=200)), ('published_on', models.DateTimeField(blank=True, null=True, verbose_name='date published')), ('image', models.ImageField(upload_to='')), ('position', models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='Position')), ], options={ 'ordering': ['position'], 'db_table': 'curricula_lessons', }, ), migrations.CreateModel( name='LessonProgress', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('created_on', models.DateTimeField(auto_now_add=True)), ('updated_on', models.DateTimeField(auto_now=True)), ('score', models.SmallIntegerField(default=0)), ('lesson', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='progress', to='curricula.Lesson')), ('profile', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='lesson_progress', to='profiles.Profile')), ], options={ 'db_table': 'curricula_lesson_progress', }, ), migrations.CreateModel( name='Module', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('created_on', models.DateTimeField(auto_now_add=True)), ('updated_on', models.DateTimeField(auto_now=True)), ('uuid', shortuuidfield.fields.ShortUUIDField(blank=True, editable=False, max_length=22)), ('name', models.CharField(max_length=200)), ('published_on', models.DateTimeField(blank=True, null=True, verbose_name='date published')), ('image', models.ImageField(upload_to='')), ('position', models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='Position')), ], options={ 'ordering': ['position'], 'db_table': 'curricula_modules', }, ), migrations.CreateModel( name='Question', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('created_on', models.DateTimeField(auto_now_add=True)), ('updated_on', models.DateTimeField(auto_now=True)), ('uuid', shortuuidfield.fields.ShortUUIDField(blank=True, editable=False, max_length=22)), ('text', models.CharField(max_length=200)), ('published_on', models.DateTimeField(blank=True, null=True, verbose_name='date published')), ('image', models.ImageField(blank=True, upload_to='')), ('question_type', django_light_enums.db.EnumField(choices=[ (10, 'SINGLE_ANSWER'), (20, 'MULTIPLE_CHOICE') ], default=10, enum_values=(10, 20))), ('position', models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='Position')), ('lesson', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='questions', to='curricula.Lesson')), ], options={ 'ordering': ['position'], 'db_table': 'curricula_questions', }, ), migrations.CreateModel( name='Text', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('created_on', models.DateTimeField(auto_now_add=True)), ('updated_on', models.DateTimeField(auto_now=True)), ('text', models.CharField(max_length=200)), ], options={ 'db_table': 'curricula_texts', }, ), migrations.CreateModel( name='Unit', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('created_on', models.DateTimeField(auto_now_add=True)), ('updated_on', models.DateTimeField(auto_now=True)), ('uuid', shortuuidfield.fields.ShortUUIDField(blank=True, editable=False, max_length=22)), ('name', models.CharField(max_length=200)), ('published_on', models.DateTimeField(blank=True, null=True, verbose_name='date published')), ('image', models.ImageField(blank=True, upload_to='')), ('position', models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='Position')), ('curriculum', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='units', to='curricula.Curriculum')), ], options={ 'ordering': ['position'], 'db_table': 'curricula_units', }, ), migrations.CreateModel( name='UserResponse', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('created_on', models.DateTimeField(auto_now_add=True)), ('updated_on', models.DateTimeField(auto_now=True)), ('object_id', models.PositiveIntegerField()), ('is_correct', models.BooleanField(default=False)), ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')), ('profile', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='responses', to='profiles.Profile')), ('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='responses', to='curricula.Question')), ], options={ 'db_table': 'curricula_user_responses', }, ), migrations.CreateModel( name='Vector', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('created_on', models.DateTimeField(auto_now_add=True)), ('updated_on', models.DateTimeField(auto_now=True)), ('magnitude', models.FloatField(blank=True, null=True, verbose_name='Magnitude')), ('angle', models.FloatField(blank=True, null=True, verbose_name='Angle')), ('x_component', models.FloatField(blank=True, null=True, verbose_name='x-Component')), ('y_component', models.FloatField(blank=True, null=True, verbose_name='y-Component')), ], options={ 'db_table': 'curricula_vectors', }, ), migrations.AddField( model_name='module', name='unit', field=models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, related_name='modules', to='curricula.Unit'), ), migrations.AddField( model_name='lesson', name='module', field=models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, related_name='lessons', to='curricula.Module'), ), migrations.AddField( model_name='answer', name='question', field=models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='curricula.Question'), ), ]
class ProcessTaskUser(models.Model): '''Model that connects a ProcessTask and a User Each task can have multiple users associated (or can be reassigned). Attributes: :user (User): :class:`django.contrib.auth.models.User` related with this instance :processtask (ProcessTask): class:`ProcessTask` related with this instance :reassigned (boolean): Indicates if this user was reassignment in the middle of a task :reassign_date (datetime): Timestamp of this user reassignment (if any) ... :status (smallint): Indicator of the status of the user decision ''' # Status literals, representing the translation to the statuses the process task can be in WAITING = 1 ACCEPTED = 2 REJECTED = 3 RUNNING = 4 FINISHED = 5 CANCELED = 6 OVERDUE = 7 IMPROVING = 8 STATUS = ((WAITING, 'Task is waiting confirmation from user'), (ACCEPTED, 'Task was accepted'), (REJECTED, 'Task was rejected'), (RUNNING, 'Task is running'), (FINISHED, 'Task has ended successfully'), (CANCELED, 'Task was canceled'), (OVERDUE, 'Task has gone over end_date'), (IMPROVING, 'Task is running again to be improved')) user = models.ForeignKey(User) processtask = models.ForeignKey(ProcessTask) reassigned = models.BooleanField(default=False) reassign_date = models.DateTimeField(null=True, blank=True) finished = models.BooleanField(default=False) hash = models.CharField(max_length=50) status = models.PositiveSmallIntegerField(choices=STATUS, default=WAITING) class Meta: ordering = ['-processtask__deadline'] def __unicode__(self): return u'%s - %s' % (self.processtask, self.user) def requests(self): return Request.objects.filter( Q(processtaskuser=self) | Q(processtaskuser__processtask=self.processtask, public=True)) def getUser(self): return self.user def getEnvolvedUser(self): if self.status != ProcessTaskUser.REJECTED: return self.user return None def getResult(self): from result.models import Result try: return Result.all(processtaskuser=self) except Result.DoesNotExist, IndexError: pass return None
class Migration(migrations.Migration): dependencies = [ ('intake', '0006_auto_20160614_2216'), ] operations = [ migrations.RemoveField( model_name='applicationlogentry', name='action_type', ), migrations.RemoveField( model_name='applicationlogentry', name='updated_field', ), migrations.RemoveField( model_name='formsubmission', name='confirmation_sent', ), migrations.RemoveField( model_name='formsubmission', name='due_for_followup', ), migrations.RemoveField( model_name='formsubmission', name='followup_answered', ), migrations.RemoveField( model_name='formsubmission', name='followup_sent', ), migrations.RemoveField( model_name='formsubmission', name='opened_by_agency', ), migrations.RemoveField( model_name='formsubmission', name='processed_by_agency', ), migrations.RemoveField( model_name='formsubmission', name='reviewed_by_staff', ), migrations.RemoveField( model_name='formsubmission', name='submitted_to_agency', ), migrations.RemoveField( model_name='formsubmission', name='told_eligible', ), migrations.RemoveField( model_name='formsubmission', name='told_ineligible', ), migrations.AddField( model_name='applicationlogentry', name='event_type', field=models.PositiveSmallIntegerField(choices=[(1, 'opened'), (2, 'referred'), (3, 'processed'), (4, 'deleted')], default=1), preserve_default=False, ), migrations.AlterField( model_name='formsubmission', name='old_uuid', field=models.CharField(default=intake.models.gen_uuid, max_length=34, unique=True), ), ]
class Request(models.Model): '''Represents a request made over a ProcessTask assignment. Each user assigned to a ProcessTask, is allowed to make requests about the task (such as asking for reassignments or for task clarification). Attributes: :processtaskuser (ProcessTaskUser): :class:`ProcessTaskUser` related with this request :type (smallint): Type of the request :title (str): Title of the request message (if any message annexed) :message (str): Content of the request message (if any message annexed) :date (datetime): Date the request we made on ''' # TYPE literals, representing the translation to the type of requests available REASSIGN = 1 CLARIFICATION = 2 TYPES = ( (REASSIGN, 'Ask for reassignment of task'), (CLARIFICATION, 'Ask for task clarification'), ) hash = models.CharField(max_length=50, default="ERROR") processtaskuser = models.ForeignKey(ProcessTaskUser) type = models.PositiveSmallIntegerField(choices=TYPES, default=CLARIFICATION) title = models.CharField(max_length=100, null=True) message = models.TextField(null=True) date = models.DateTimeField(auto_now_add=True) resolved = models.BooleanField(default=False) public = models.BooleanField(default=False) removed = models.BooleanField(default=False) class Meta: ordering = ['-id'] def process(self): return self.processtaskuser.processtask.process.hash def task(self): return self.processtaskuser.processtask.task.hash def resolve(self): try: if self.response: self.resolved = True else: self.resolved = False except RequestResponse.DoesNotExist: self.resolved = True self.save() def remove(self): self.removed = True self.save() @staticmethod def all(executioner=None, requester=None, process=None): tmp = Request.objects.filter(removed=False) if executioner != None: tmp = tmp.filter( processtaskuser__processtask__process__executioner=executioner) if requester != None: tmp = tmp.filter(processtaskuser__user=requester) if process != None: tmp = tmp.filter( processtaskuser__processtask__process__hash=process) return tmp def __unicode__(self): ptask = self.processtaskuser.processtask return u"Request for Task %s in Process %s" % (ptask.task, ptask.process)
class DetailedTiming(Timing): # Pixel clock in kHz pixel_clock = models.PositiveIntegerField() horizontal_active = models.PositiveSmallIntegerField() horizontal_blanking = models.PositiveSmallIntegerField() horizontal_sync_offset = models.PositiveSmallIntegerField() horizontal_sync_pulse_width = models.PositiveSmallIntegerField() horizontal_image_size = models.PositiveSmallIntegerField() horizontal_border = models.PositiveSmallIntegerField() vertical_active = models.PositiveSmallIntegerField() vertical_blanking = models.PositiveSmallIntegerField() vertical_sync_offset = models.PositiveSmallIntegerField() vertical_sync_pulse_width = models.PositiveSmallIntegerField() vertical_image_size = models.PositiveSmallIntegerField() vertical_border = models.PositiveSmallIntegerField() flags_interlaced = models.BooleanField('interlaced') Stereo_Mode = DisplayStereoMode STEREO_MODE_CHOICES = ( (Stereo_Mode.Normal_display, 'Normal display, no stereo.'), (Stereo_Mode.Field_sequential_right, 'Field sequential stereo, right image when stereo sync.'), (Stereo_Mode.Field_sequential_left, 'Field sequential stereo, left image when stereo sync.'), (Stereo_Mode.Interleaved_2_way_right, '2-way interleaved stereo, right image on even lines.'), (Stereo_Mode.Interleaved_2_way_left, '2-way interleaved stereo, left image on even lines.'), (Stereo_Mode.Interleaved_4_way, '4-way interleaved stereo.'), (Stereo_Mode.Interleaved_side_by_side, 'Side-by-Side interleaved stereo.'), ) flags_stereo_mode = models.PositiveSmallIntegerField( 'stereo mode', choices=STEREO_MODE_CHOICES ) Sync_Scheme = TimingSyncScheme SYNC_SCHEME_CHOICES = ( (Sync_Scheme.Analog_Composite, 'Analog Composite'), (Sync_Scheme.Bipolar_Analog_Composite, 'Bipolar Analog Composite'), (Sync_Scheme.Digital_Composite, 'Digital Composite'), (Sync_Scheme.Digital_Separate, 'Digital Separate'), ) flags_sync_scheme = models.PositiveSmallIntegerField( 'sync scheme', choices=SYNC_SCHEME_CHOICES ) # If flags_sync_scheme == Digital_Separate flags_horizontal_polarity = models.NullBooleanField('horizontal polarity') flags_vertical_polarity = models.NullBooleanField('vertical polarity') # If not flags_sync_scheme == Digital_Separate flags_serrate = models.NullBooleanField('serrate') # If flags_sync_scheme == Digital_Composite flags_composite_polarity = models.NullBooleanField('composite polarity') # If not flags_sync_scheme == Digital_Composite and # not flags_sync_scheme == Digital_Separate flags_sync_on_rgb = models.NullBooleanField('sync on RGB') def __unicode__(self): return "%dx%d@%dHz" % (self.horizontal_active, self.vertical_active, self.pixel_clock / 1000)
class OrganizationMember(Model): """ Identifies relationships between organizations and users. Users listed as team members are considered to have access to all projects and could be thought of as team owners (though their access level may not) be set to ownership. """ __core__ = True organization = FlexibleForeignKey("sentry.Organization", related_name="member_set") user = FlexibleForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, related_name="sentry_orgmember_set") email = models.EmailField(null=True, blank=True, max_length=75) role = models.CharField(max_length=32, default=six.text_type(roles.get_default().id)) flags = BitField(flags=((u"sso:linked", u"sso:linked"), (u"sso:invalid", u"sso:invalid")), default=0) token = models.CharField(max_length=64, null=True, blank=True, unique=True) date_added = models.DateTimeField(default=timezone.now) token_expires_at = models.DateTimeField(default=None, null=True) has_global_access = models.BooleanField(default=True) teams = models.ManyToManyField("sentry.Team", blank=True, through="sentry.OrganizationMemberTeam") inviter = FlexibleForeignKey( settings.AUTH_USER_MODEL, null=True, blank=True, related_name="sentry_inviter_set", on_delete=models.SET_NULL, ) invite_status = models.PositiveSmallIntegerField( choices=( (InviteStatus.APPROVED.value, _("Approved")), ( InviteStatus.REQUESTED_TO_BE_INVITED.value, _("Organization member requested to invite user"), ), (InviteStatus.REQUESTED_TO_JOIN.value, _("User requested to join organization")), ), default=InviteStatus.APPROVED.value, null=True, ) # Deprecated -- no longer used type = BoundedPositiveIntegerField(default=50, blank=True) class Meta: app_label = "sentry" db_table = "sentry_organizationmember" unique_together = (("organization", "user"), ("organization", "email")) __repr__ = sane_repr("organization_id", "user_id", "role") @transaction.atomic def save(self, *args, **kwargs): assert self.user_id or self.email, "Must set user or email" if self.token and not self.token_expires_at: self.refresh_expires_at() super(OrganizationMember, self).save(*args, **kwargs) def set_user(self, user): self.user = user self.email = None self.token = None self.token_expires_at = None def remove_user(self): self.email = self.get_email() self.user = None self.token = self.generate_token() def regenerate_token(self): self.token = self.generate_token() self.refresh_expires_at() def refresh_expires_at(self): now = timezone.now() self.token_expires_at = now + timedelta(days=INVITE_DAYS_VALID) def approve_invite(self): self.invite_status = InviteStatus.APPROVED.value self.regenerate_token() def get_invite_status_name(self): if self.invite_status is None: return return invite_status_names[self.invite_status] @property def invite_approved(self): return self.invite_status == InviteStatus.APPROVED.value @property def requested_to_join(self): return self.invite_status == InviteStatus.REQUESTED_TO_JOIN.value @property def requested_to_be_invited(self): return self.invite_status == InviteStatus.REQUESTED_TO_BE_INVITED.value @property def is_pending(self): return self.user_id is None @property def token_expired(self): # Old tokens don't expire to preserve compatibility and not require # a backfill migration. if self.token_expires_at is None: return False if self.token_expires_at > timezone.now(): return False return True @property def legacy_token(self): checksum = md5() checksum.update(six.text_type(self.organization_id).encode("utf-8")) checksum.update(self.get_email().encode("utf-8")) checksum.update(force_bytes(settings.SECRET_KEY)) return checksum.hexdigest() def generate_token(self): return uuid4().hex + uuid4().hex def get_invite_link(self): if not self.is_pending or not self.invite_approved: return None return absolute_uri( reverse( "sentry-accept-invite", kwargs={ "member_id": self.id, "token": self.token or self.legacy_token }, )) def send_invite_email(self): from sentry.utils.email import MessageBuilder context = { "email": self.email, "organization": self.organization, "url": self.get_invite_link(), } msg = MessageBuilder( subject="Join %s in using Sentry" % self.organization.name, template="sentry/emails/member-invite.txt", html_template="sentry/emails/member-invite.html", type="organization.invite", context=context, ) try: msg.send_async([self.get_email()]) except Exception as e: logger = get_logger(name="sentry.mail") logger.exception(e) def send_sso_link_email(self, actor, provider): from sentry.utils.email import MessageBuilder link_args = {"organization_slug": self.organization.slug} context = { "organization": self.organization, "actor": actor, "provider": provider, "url": absolute_uri(reverse("sentry-auth-organization", kwargs=link_args)), } msg = MessageBuilder( subject="Action Required for %s" % (self.organization.name, ), template="sentry/emails/auth-link-identity.txt", html_template="sentry/emails/auth-link-identity.html", type="organization.auth_link", context=context, ) msg.send_async([self.get_email()]) def send_sso_unlink_email(self, actor, provider): from sentry.utils.email import MessageBuilder from sentry.models import LostPasswordHash email = self.get_email() recover_uri = u"{path}?{query}".format( path=reverse("sentry-account-recover"), query=urlencode({"email": email})) # Nothing to send if this member isn't associated to a user if not self.user_id: return context = { "email": email, "recover_url": absolute_uri(recover_uri), "has_password": self.user.password, "organization": self.organization, "actor": actor, "provider": provider, } if not self.user.password: password_hash = LostPasswordHash.for_user(self.user) context["set_password_url"] = password_hash.get_absolute_url( mode="set_password") msg = MessageBuilder( subject="Action Required for %s" % (self.organization.name, ), template="sentry/emails/auth-sso-disabled.txt", html_template="sentry/emails/auth-sso-disabled.html", type="organization.auth_sso_disabled", context=context, ) msg.send_async([email]) def get_display_name(self): if self.user_id: return self.user.get_display_name() return self.email def get_label(self): if self.user_id: return self.user.get_label() return self.email or self.id def get_email(self): if self.user_id and self.user.email: return self.user.email return self.email def get_avatar_type(self): if self.user_id: return self.user.get_avatar_type() return "letter_avatar" def get_audit_log_data(self): from sentry.models import Team teams = list( Team.objects.filter(id__in=OrganizationMemberTeam.objects.filter( organizationmember=self, is_active=True).values_list( "team", flat=True)).values("id", "slug")) return { "email": self.get_email(), "user": self.user_id, "teams": [t["id"] for t in teams], "teams_slugs": [t["slug"] for t in teams], "has_global_access": self.has_global_access, "role": self.role, "invite_status": invite_status_names[self.invite_status], } def get_teams(self): from sentry.models import Team return Team.objects.filter( status=TeamStatus.VISIBLE, id__in=OrganizationMemberTeam.objects.filter( organizationmember=self, is_active=True).values("team"), ) def get_scopes(self): scopes = roles.get(self.role).scopes disabled_scopes = set() if self.role == "member": if not self.organization.get_option("sentry:events_member_admin", EVENTS_MEMBER_ADMIN_DEFAULT): disabled_scopes.add("event:admin") if not self.organization.get_option("sentry:alerts_member_write", ALERTS_MEMBER_WRITE_DEFAULT): disabled_scopes.add("alerts:write") scopes = frozenset(s for s in scopes if s not in disabled_scopes) return scopes @classmethod def delete_expired(cls, threshold): """ Delete un-accepted member invitations that expired ``threshold`` days ago. """ cls.objects.filter( token_expires_at__lt=threshold, user_id__exact=None).exclude(email__exact=None).delete()
class Migration(migrations.Migration): dependencies = [ ("problems", "0004_razstavirazliko"), ] operations = [ migrations.AlterModelOptions( name="iskanjenicelpolinoma", options={"verbose_name": "iskanje ničel polinoma"}, ), migrations.AlterModelOptions( name="krajsanjeulomkov", options={"verbose_name": "krajšanje ulomkov"}, ), migrations.AlterModelOptions( name="prostobesedilo", options={"verbose_name": "prosto besedilo"}, ), migrations.AlterModelOptions( name="razstavirazliko", options={"verbose_name": "razstavi razliko"}, ), migrations.AlterModelOptions( name="razstavivieta", options={"verbose_name": "razstavi Vieta"}, ), migrations.AlterField( model_name="iskanjenicelpolinoma", name="stevilo_nicel", field=models.PositiveSmallIntegerField( help_text="Največje število ničel polinoma (vedno bo vsaj 1).", verbose_name="število ničel", ), ), migrations.AlterField( model_name="iskanjenicelpolinoma", name="velikost_nicle", field=models.PositiveSmallIntegerField( help_text= "Največja velikost ničle glede na absolutno vrednost.", verbose_name="velikost ničle", ), ), migrations.AlterField( model_name="krajsanjeulomkov", name="najvecji_faktor", field=models.PositiveSmallIntegerField( help_text= "Največji faktor med neokrajšanim in okrajšanim ulomkom.", verbose_name="največji faktor", ), ), migrations.AlterField( model_name="krajsanjeulomkov", name="najvecji_imenovalec", field=models.PositiveSmallIntegerField( help_text= "Največji imenovalec, ki se bo pojavljal v okrajšanem ulomku.", verbose_name="največji imenovalec", ), ), migrations.AlterField( model_name="krajsanjeulomkov", name="najvecji_stevec", field=models.PositiveSmallIntegerField( help_text= "Največji števec, ki se bo pojavljal v okrajšanem ulomku.", verbose_name="največji števec", ), ), migrations.AlterField( model_name="prostobesedilo", name="odgovor", field=models.TextField(help_text="Poljubno besedilo odgovora.", verbose_name="odgovor"), ), migrations.AlterField( model_name="prostobesedilo", name="vprasanje", field=models.TextField(help_text="Poljubno besedilo vprašanja.", verbose_name="vprašanje"), ), migrations.AlterField( model_name="razstavirazliko", name="linearna_kombinacija", field=models.BooleanField( help_text= "Ali naj naloga vsebuje linearno kombinacijo dveh neznank ali enostaven dvočlenik?", verbose_name="linearna kombinacija", ), ), migrations.AlterField( model_name="razstavirazliko", name="najmanjsa_potenca", field=models.PositiveSmallIntegerField( help_text="Najmanjša možna potenca za razstavljanje.", verbose_name="najmanjša potenca", ), ), migrations.AlterField( model_name="razstavirazliko", name="najvecja_potenca", field=models.PositiveSmallIntegerField( help_text="Največja možna potenca za razstavljanje.", verbose_name="največja potenca", ), ), migrations.AlterField( model_name="razstavivieta", name="maksimalna_vrednost", field=models.PositiveSmallIntegerField( help_text= "Največja možna vrednost razstavljenega člena glede na absolutno vrednost", verbose_name="maksimalna vrednost", ), ), migrations.AlterField( model_name="razstavivieta", name="vodilni_koeficient", field=models.BooleanField( help_text="Ali naj bo vodilni koeficient različen od 1?", verbose_name="vodilni koeficient", ), ), ]
class Migration(migrations.Migration): dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ migrations.CreateModel( name='Game', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('date', models.DateTimeField(default=django.utils.timezone.now)), ('game_map', models.CharField(choices=[('Tharsis', 'Tharsis'), ('Elysium', 'Elysium'), ('Hellas', 'Hellas')], default='Tharsis', max_length=16)), ('draft_variant', models.BooleanField(default=True)), ('prelude', models.BooleanField(default=False)), ('venus_next', models.BooleanField(default=False)), ('colonies', models.BooleanField(default=False)), ], ), migrations.CreateModel( name='Player', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('nickname', models.CharField(max_length=32, unique=True)), ('motto', models.CharField(blank=True, max_length=128, null=True)), ('user', models.OneToOneField( blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ], ), migrations.CreateModel( name='PlayerScore', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('corporation', models.CharField(choices=[ ('Aphrodite', 'Aphrodite'), ('Aridor', 'Aridor'), ('Arklight', 'Arklight'), ('Celestic', 'Celestic'), ('Cheung Shing Mars', 'Cheung Shing Mars'), ('Credicor', 'Credicor'), ('Ecoline', 'Ecoline'), ('Helion', 'Helion'), ('Interplanetary Cinematics', 'Interplanetary Cinematics'), ('Inventrix', 'Inventrix'), ('Manutech', 'Manutech'), ('Mining Guild', 'Mining Guild'), ('Morning Star Inc.', 'Morning Star Inc.'), ('Phobolog', 'Phobolog'), ('Point Luna', 'Point Luna'), ('Polyphemos', 'Polyphemos'), ('Poseidon', 'Poseidon'), ('Robinson Industries', 'Robinson Industries'), ('Saturn Systems', 'Saturn Systems'), ('Storm Craft Incorporated', 'Storm Craft Incorporated'), ('Terractor', 'Terractor'), ('Tharsis Republic', 'Tharsis Republic'), ('Thorgate', 'Thorgate'), ('United Nations Mars Initiative', 'United Nations Mars Initiative'), ('Valley Trust', 'Valley Trust'), ('Viron', 'Viron'), ('Vitor', 'Vitor') ], max_length=64)), ('terraform_rating', models.PositiveSmallIntegerField(default=20)), ('milestones', models.PositiveSmallIntegerField(default=0)), ('awards', models.PositiveSmallIntegerField(default=0)), ('greeneries', models.PositiveSmallIntegerField(default=0)), ('cities', models.PositiveSmallIntegerField(default=0)), ('event_cards', models.SmallIntegerField(default=0)), ('automated_cards', models.SmallIntegerField(default=0)), ('active_cards', models.SmallIntegerField(default=0)), ('resources', models.SmallIntegerField(default=0)), ('game', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='scores', to='mars_api.game')), ('player', models.ForeignKey( null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='scores', to='mars_api.player')), ], options={ 'default_related_name': 'scores', }, ), migrations.AddConstraint( model_name='game', constraint=models.CheckConstraint( check=models.Q(game_map__in={'Hellas', 'Tharsis', 'Elysium'}), name="Only {'Hellas', 'Elysium', 'Tharsis'} maps are allowed." ), ), migrations.AddConstraint( model_name='playerscore', constraint=models.UniqueConstraint( fields=('player', 'game'), name='one_score_per_player_per_game'), ), migrations.AddConstraint( model_name='playerscore', constraint=models.UniqueConstraint( fields=('corporation', 'game'), name='only_unique_corporations_per_game'), ), migrations.AddConstraint( model_name='playerscore', constraint=models.CheckConstraint( check=models.Q( corporation__in={ 'Celestic', 'Thorgate', 'Cheung Shing Mars', 'Poseidon', 'Storm Craft Incorporated', 'Helion', 'Inventrix', 'Aridor', 'Valley Trust', 'Viron', 'Robinson Industries', 'United Nations Mars Initiative', 'Vitor', 'Point Luna', 'Arklight', 'Aphrodite', 'Polyphemos', 'Phobolog', 'Manutech', 'Terractor', 'Ecoline', 'Tharsis Republic', 'Morning Star Inc.', 'Mining Guild', 'Saturn Systems', 'Interplanetary Cinematics', 'Credicor' }), name='Only defined corporations are allowed.'), ), migrations.RemoveConstraint( model_name='game', name="Only {'Hellas', 'Elysium', 'Tharsis'} maps are allowed.", ), migrations.AddConstraint( model_name='game', constraint=models.CheckConstraint( check=models.Q(game_map__in={'Hellas', 'Tharsis', 'Elysium'}), name="Only {'Elysium', 'Hellas', 'Tharsis'} maps are allowed." ), ), migrations.RemoveConstraint( model_name='game', name="Only {'Elysium', 'Hellas', 'Tharsis'} maps are allowed.", ), migrations.AddConstraint( model_name='game', constraint=models.CheckConstraint( check=models.Q(game_map__in={'Hellas', 'Tharsis', 'Elysium'}), name="Only {'Hellas', 'Elysium', 'Tharsis'} maps are allowed." ), ), migrations.RemoveConstraint( model_name='game', name="Only {'Hellas', 'Elysium', 'Tharsis'} maps are allowed.", ), migrations.AddConstraint( model_name='game', constraint=models.CheckConstraint( check=models.Q(game_map__in={'Hellas', 'Tharsis', 'Elysium'}), name="Only {'Elysium', 'Hellas', 'Tharsis'} maps are allowed." ), ), migrations.RemoveConstraint( model_name='game', name="Only {'Elysium', 'Hellas', 'Tharsis'} maps are allowed.", ), migrations.AddConstraint( model_name='game', constraint=models.CheckConstraint( check=models.Q(game_map__in={'Hellas', 'Tharsis', 'Elysium'}), name="Only {'Hellas', 'Elysium', 'Tharsis'} maps are allowed." ), ), migrations.RemoveConstraint( model_name='game', name="Only {'Hellas', 'Elysium', 'Tharsis'} maps are allowed.", ), migrations.AddConstraint( model_name='game', constraint=models.CheckConstraint( check=models.Q(game_map__in={'Hellas', 'Tharsis', 'Elysium'}), name="Only {'Elysium', 'Hellas', 'Tharsis'} maps are allowed." ), ), migrations.RemoveConstraint( model_name='game', name="Only {'Elysium', 'Hellas', 'Tharsis'} maps are allowed.", ), migrations.AddConstraint( model_name='game', constraint=models.CheckConstraint( check=models.Q(game_map__in={'Hellas', 'Tharsis', 'Elysium'}), name="Only {'Elysium', 'Tharsis', 'Hellas'} maps are allowed." ), ), migrations.RemoveConstraint( model_name='game', name="Only {'Elysium', 'Tharsis', 'Hellas'} maps are allowed.", ), migrations.AddConstraint( model_name='game', constraint=models.CheckConstraint( check=models.Q(game_map__in={'Hellas', 'Tharsis', 'Elysium'}), name='Only defined maps are allowed.'), ), migrations.RemoveConstraint( model_name='playerscore', name='Only defined corporations are allowed.', ), migrations.AddField( model_name='game', name='number_of_generations', field=models.PositiveSmallIntegerField(default=10), ), migrations.AlterField( model_name='playerscore', name='corporation', field=models.CharField(choices=[ ('Aphrodite', 'Aphrodite'), ('Aridor', 'Aridor'), ('Arklight', 'Arklight'), ('Celestic', 'Celestic'), ('Cheung Shing Mars', 'Cheung Shing Mars'), ('Credicor', 'Credicor'), ('Ecoline', 'Ecoline'), ('Helion', 'Helion'), ('Interplanetary Cinematics', 'Interplanetary Cinematics'), ('Inventrix', 'Inventrix'), ('N/A', 'N/A'), ('Manutech', 'Manutech'), ('Mining Guild', 'Mining Guild'), ('Morning Star Inc.', 'Morning Star Inc.'), ('Phobolog', 'Phobolog'), ('Point Luna', 'Point Luna'), ('Polyphemos', 'Polyphemos'), ('Poseidon', 'Poseidon'), ('Robinson Industries', 'Robinson Industries'), ('Saturn Systems', 'Saturn Systems'), ('Storm Craft Incorporated', 'Storm Craft Incorporated'), ('Teractor', 'Teractor'), ('Tharsis Republic', 'Tharsis Republic'), ('Thorgate', 'Thorgate'), ('United Nations Mars Initiative', 'United Nations Mars Initiative'), ('Valley Trust', 'Valley Trust'), ('Viron', 'Viron'), ('Vitor', 'Vitor') ], max_length=64), ), migrations.AddConstraint( model_name='playerscore', constraint=models.CheckConstraint( check=models.Q( corporation__in={ 'Celestic', 'Thorgate', 'Poseidon', 'Cheung Shing Mars', 'Storm Craft Incorporated', 'Helion', 'Inventrix', 'Aridor', 'Valley Trust', 'Viron', 'Robinson Industries', 'Teractor', 'United Nations Mars Initiative', 'Vitor', 'Point Luna', 'Arklight', 'Aphrodite', 'Phobolog', 'Polyphemos', 'Manutech', 'N/A', 'Ecoline', 'Tharsis Republic', 'Morning Star Inc.', 'Mining Guild', 'Saturn Systems', 'Interplanetary Cinematics', 'Credicor' }), name='Only defined corporations are allowed.'), ), migrations.RemoveConstraint( model_name='playerscore', name='only_unique_corporations_per_game', ), migrations.AddConstraint( model_name='playerscore', constraint=models.UniqueConstraint( condition=models.Q(_negated=True, corporation__startswith='N/A'), fields=('corporation', 'game'), name='only_unique_corporations_per_game'), ), migrations.RemoveConstraint( model_name='playerscore', name='only_unique_corporations_per_game', ), migrations.AddConstraint( model_name='playerscore', constraint=models.UniqueConstraint( fields=('corporation', 'game'), name='only_unique_corporations_per_game'), ), migrations.RemoveConstraint( model_name='playerscore', name='only_unique_corporations_per_game', ), migrations.AddConstraint( model_name='playerscore', constraint=models.UniqueConstraint( condition=models.Q(_negated=True, corporation__startswith='N/A'), fields=('corporation', 'game'), name='only_unique_corporations_per_game'), ), ]
class PositiveSmallIntegerPKData(models.Model): data = models.PositiveSmallIntegerField(primary_key=True)
class Migration(migrations.Migration): initial = True dependencies = [ ] operations = [ migrations.CreateModel( name='CarBodyType', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=20)), ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), ], options={ 'abstract': False, }, ), migrations.CreateModel( name='CarColor', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=20)), ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), ], options={ 'abstract': False, }, ), migrations.CreateModel( name='CarFuelType', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=20)), ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), ], options={ 'abstract': False, }, ), migrations.CreateModel( name='CarMake', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('slug', models.SlugField(editable=False)), ('name', models.CharField(max_length=50)), ('active', models.BooleanField(default=False)), ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), ], ), migrations.CreateModel( name='CarModel', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('slug', models.SlugField(editable=False)), ('name', models.CharField(max_length=50)), ('active', models.BooleanField(default=False)), ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), ('make', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='store.carmake')), ], ), migrations.CreateModel( name='CarTransmission', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=20)), ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), ], options={ 'abstract': False, }, ), migrations.CreateModel( name='CarSubmodel', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('slug', models.SlugField(editable=False)), ('name', models.CharField(blank=True, max_length=50, null=True)), ('active', models.BooleanField(default=False)), ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), ('model', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='store.carmodel')), ], ), migrations.CreateModel( name='Car', fields=[ ('id', models.UUIDField(db_index=True, default=uuid.uuid4, primary_key=True, serialize=False)), ('active', models.BooleanField(default=False)), ('year', models.PositiveSmallIntegerField(validators=[django.core.validators.MinValueValidator(1900), django.core.validators.MaxValueValidator(2050)])), ('mileage', models.PositiveIntegerField(blank=True, null=True)), ('price', models.PositiveIntegerField(blank=True, null=True)), ('created_at', models.DateTimeField()), ('updated_at', models.DateTimeField()), ('body_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='store.carbodytype')), ('exterior_color', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='store.carcolor')), ('fuel_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='store.carfueltype')), ('make', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='store.carmake')), ('model', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='store.carmodel')), ('submodel', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='store.carsubmodel')), ('transmission', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='store.cartransmission')), ], ), ]
class Partner(models.Model): """ A partner organization which provides access grants to paywalled resources. This model tracks contact information for the partner as well as extra information they require on access grant applications. """ class Meta: app_label = 'resources' verbose_name = 'partner' verbose_name_plural = 'partners' ordering = ['company_name'] # -------------------------------------------------------------------------- # Managers # -------------------------------------------------------------------------- # Define managers. Note that the basic manager must be first to make # Django internals work as expected, but we define objects as our custom # manager so that we don't inadvertently expose unavailable Partners to # end users. even_not_available = models.Manager() objects = AvailablePartnerManager() # -------------------------------------------------------------------------- # Attributes # -------------------------------------------------------------------------- company_name = models.CharField(max_length=40, # Translators: In the administrator interface, this text is help text for a field where staff can enter the name of the partner. Don't translate McFarland. help_text=_("Partner's name (e.g. McFarland). Note: " "this will be user-visible and *not translated*.")) date_created = models.DateField(auto_now_add=True) coordinator = models.ForeignKey(User, blank=True, null=True, on_delete=models.SET_NULL, # Translators: In the administrator interface, this text is help text for a field where staff can specify the username of the account coordinator for this partner. help_text=_('The coordinator for this Partner, if any.')) featured = models.BooleanField(default=False, # Translators: In the administrator interface, this text is help text for a check box where staff can select whether a publisher will be featured on the website's front page. help_text=_("Mark as true to feature this partner on the front page.")) company_location = CountryField(null=True, # Translators: In the administrator interface, this text is help text for a field where staff can enter the partner organisation's country. help_text=_("Partner's primary location.")) # Status metadata # -------------------------------------------------------------------------- # AVAILABLE partners are displayed to users. # NOT AVAILABLE partners are only accessible through the admin interface. # These may be, e.g., partners TWL used to work with but no longer does # (kept in the database for recordkeeping), or they may be partners TWL # is setting up a relationship with but isn't ready to expose to public # view. # We default to NOT_AVAILABLE to avoid inadvertently exposing Partners to # the application process when they're not ready yet, and to give staff # a chance to build their record incrementally and fix errors. AVAILABLE = 0 NOT_AVAILABLE = 1 WAITLIST = 2 STATUS_CHOICES = ( # Translators: This is a status for a Partner, denoting that editors can apply for access. (AVAILABLE, _('Available')), # Translators: This is a status for a Partner, denoting that editors cannot apply for access and the Partner will not be displayed to them. (NOT_AVAILABLE, _('Not available')), # Translators: This is a status for a Partner, denoting that it has no access grants available at this time (but should later). (WAITLIST, _('Waitlisted')), ) EMAIL = 0 CODES = 1 PROXY = 2 BUNDLE = 3 AUTHORIZATION_METHODS = ( # Translators: This is the name of the authorization method whereby user accounts are set up by email. (EMAIL, _('Email')), # Translators: This is the name of the authorization method whereby user accounts are set up via an access code. (CODES, _('Access codes')), # Translators: This is the name of the authorization method whereby users access resources via an IP proxy. (PROXY, _('Proxy')), # Translators: This is the name of the authorization method whereby users access resources automatically via the library bundle. (BUNDLE, _('Library Bundle')), ) status = models.IntegerField(choices=STATUS_CHOICES, default=NOT_AVAILABLE, # Translators: In the administrator interface, this text is help text for a field where staff can specify whether this partner should be displayed to users. help_text=_('Should this Partner be displayed to users? Is it ' 'open for applications right now?')) renewals_available = models.BooleanField(default=False, # Translators: In the administrator interface, this text is help text for a field where staff specify whether users can request their account be renewed/extended for this partner. help_text=_('Can access grants to this partner be renewed? If so, ' 'users will be able to request renewals at any time.')) accounts_available = models.PositiveSmallIntegerField(blank=True, null=True, # Translators: In the administrator interface, this text is help text for a field where staff specify the total number of available accounts. help_text=_('Add number of new accounts to the existing value, not by reseting it to zero.')) # Optional resource metadata # -------------------------------------------------------------------------- terms_of_use = models.URLField(blank=True, null=True, # Translators: In the administrator interface, this text is help text for a field where staff can link to a partner's Terms of Use. help_text=_("Link to terms of use. Required if users must agree to " "terms of use to get access; optional otherwise.")) short_description = models.TextField(max_length=1000, blank=True, null=True, # Translators: In the administrator interface, this text is help text for a field where staff can provide a description of a partner's available resources. help_text=_("Optional short description of this partner's resources.")) description = models.TextField("long description", blank=True, # Translators: In the administrator interface, this text is help text for a field where staff can provide a long description of a partner's available resources. help_text=_("Optional detailed description in addition to the short " "description such as collections, instructions, notes, special " "requirements, alternate access options, unique features, citations notes.")) send_instructions = models.TextField(blank=True, null=True, # Translators: In the administrator interface, this text is help text for a field where staff can provide instructions to coordinators on sending user data to partners. help_text=_("Optional instructions for sending application data to " "this partner.")) excerpt_limit = models.PositiveSmallIntegerField(blank=True, null=True, # Translators: In the administrator interface, this text is help text for a field where staff can optionally provide a excerpt word limit per article. help_text=_("Optional excerpt limit in terms of number of words per article. Leave empty if no limit.")) excerpt_limit_percentage = models.PositiveSmallIntegerField(blank=True, null=True, validators = [MaxValueValidator(100)], # Translators: In the administrator interface, this text is help text for a field where staff can optionally provide a excerpt word limit per article in terms of percentage per article. help_text=_("Optional excerpt limit in terms of percentage (%) of an article. Leave empty if no limit.")) authorization_method = models.IntegerField(choices=AUTHORIZATION_METHODS, default=EMAIL, # Translators: In the administrator interface, this text is help text for a field where staff can specify which method of account distribution this partner uses. help_text=_("Which authorization method does this partner use? " "'Email' means the accounts are set up via email, and is the default. " "Select 'Access Codes' if we send individual, or group, login details " "or access codes. 'Proxy' means access delivered directly via EZProxy, " "and Library Bundle is automated proxy-based access.")) mutually_exclusive = models.NullBooleanField( blank=True, null=True, default=None, # Translators: In the administrator interface, this text is help text for a field where staff can specify whether users can apply for one or multiple collections of resources. Streams means 'collections'. help_text=_("If True, users can only apply for one Stream at a time " "from this Partner. If False, users can apply for multiple Streams at " "a time. This field must be filled in when Partners have multiple " "Streams, but may be left blank otherwise.")) languages = models.ManyToManyField(Language, blank=True, # Translators: In the administrator interface, this text is help text for a field where staff can specify the languages a partner has resources in. help_text=_("Select all languages in which this partner publishes " "content.") ) tags = TaggableManager(through=TaggedTextField, blank=True) # This field has to stick around until all servers are using the new tags. old_tags = TaggableManager(through=None, blank=True, verbose_name=_('Old Tags')) # Non-universal form fields # -------------------------------------------------------------------------- # Some fields are required by all resources for all access grants. # Some fields are only required by some resources. This is where we track # whether *this* resource requires those optional fields. registration_url = models.URLField(blank=True, null=True, # Translators: In the administrator interface, this text is help text for a field where staff can link to a partner's registration page. help_text=_("Link to registration page. Required if users must sign up " "on the partner's website in advance; optional otherwise.")) real_name = models.BooleanField(default=False, # Translators: In the administrator interface, this text is help text for a check box where staff can select whether users must specify their real name when applying help_text=_('Mark as true if this partner requires applicant names.')) country_of_residence = models.BooleanField(default=False, # Translators: In the administrator interface, this text is help text for a check box where staff can select whether users must specify the country in which they live when applying. help_text=_('Mark as true if this partner requires applicant countries ' 'of residence.')) specific_title = models.BooleanField(default=False, # Translators: In the administrator interface, this text is help text for a check box where staff can select whether users must specify a title for the resource they want to access when applying. help_text=_('Mark as true if this partner requires applicants to ' 'specify the title they want to access.')) specific_stream = models.BooleanField(default=False, # Translators: In the administrator interface, this text is help text for a check box where staff can select whether users must specify a collection of resources when applying. help_text=_('Mark as true if this partner requires applicants to ' 'specify the database they want to access.')) occupation = models.BooleanField(default=False, # Translators: In the administrator interface, this text is help text for a check box where staff can select whether users must specify their occupation when applying. help_text=_('Mark as true if this partner requires applicants to ' 'specify their occupation.')) affiliation = models.BooleanField(default=False, # Translators: In the administrator interface, this text is help text for a check box where staff can select whether users must specify their institutional affiliation (e.g. university) when applying. help_text=_('Mark as true if this partner requires applicants to ' 'specify their institutional affiliation.')) agreement_with_terms_of_use = models.BooleanField(default=False, # Translators: In the administrator interface, this text is help text for a check box where staff can select whether users must agree to Terms of Use when applying. help_text=_("Mark as true if this partner requires applicants to agree " "with the partner's terms of use.")) account_email = models.BooleanField(default=False, # Translators: In the administrator interface, this text is help text for a check box where staff can select whether users must first register at the organisation's website before finishing their application. help_text=_("Mark as true if this partner requires applicants to have " "already signed up at the partner website.")) def __unicode__(self): return self.company_name def clean(self): if self.agreement_with_terms_of_use and not self.terms_of_use: raise ValidationError('When agreement with terms of use is ' 'required, a link to terms of use must be provided.') if self.streams.count() > 1: if self.mutually_exclusive is None: raise ValidationError('Since this resource has multiple ' 'Streams, you must specify a value for mutually_exclusive.') if self.account_email and not self.registration_url: raise ValidationError('When pre-registration is required, ' 'a link to the registration page must be provided.') def get_absolute_url(self): return reverse_lazy('partners:detail', kwargs={'pk': self.pk}) def save(self, *args, **kwargs): """Invalidate this partner's pandoc-rendered html from cache""" super(Partner, self).save(*args, **kwargs) for code in RESOURCE_LANGUAGE_CODES: short_description_cache_key = make_template_fragment_key( 'partner_short_description', [code, self.pk] ) description_cache_key = make_template_fragment_key( 'partner_description', [code, self.pk] ) send_instructions_cache_key = make_template_fragment_key( 'partner_send_instructions', [code, self.pk] ) cache.delete(short_description_cache_key) cache.delete(description_cache_key) cache.delete(send_instructions_cache_key) @property def get_languages(self): return self.languages.all() @property def is_waitlisted(self): return self.status == self.WAITLIST @property def is_not_available(self): return self.status == self.NOT_AVAILABLE
class Email(models.Model): """ A model to hold email information. """ PRIORITY_CHOICES = [(PRIORITY.low, _("low")), (PRIORITY.medium, _("medium")), (PRIORITY.high, _("high")), (PRIORITY.now, _("now"))] STATUS_CHOICES = [(STATUS.sent, _("sent")), (STATUS.failed, _("failed")), (STATUS.queued, _("queued")), (STATUS.requeued, _("requeued"))] from_email = models.CharField(_("Email From"), max_length=254, validators=[validate_email_with_name]) to = CommaSeparatedEmailField(_("Email To")) cc = CommaSeparatedEmailField(_("Cc")) bcc = CommaSeparatedEmailField(_("Bcc")) subject = models.CharField(_("Subject"), max_length=989, blank=True) message = models.TextField(_("Message"), blank=True) html_message = models.TextField(_("HTML Message"), blank=True) """ Emails with 'queued' status will get processed by ``send_queued`` command. Status field will then be set to ``failed`` or ``sent`` depending on whether it's successfully delivered. """ status = models.PositiveSmallIntegerField( _("Status"), choices=STATUS_CHOICES, db_index=True, blank=True, null=True) priority = models.PositiveSmallIntegerField(_("Priority"), choices=PRIORITY_CHOICES, blank=True, null=True) created = models.DateTimeField(auto_now_add=True, db_index=True) last_updated = models.DateTimeField(db_index=True, auto_now=True) scheduled_time = models.DateTimeField(_("Scheduled Time"), blank=True, null=True, db_index=True, help_text=_("The scheduled sending time")) expires_at = models.DateTimeField(_("Expires"), blank=True, null=True, help_text=_("Email won't be sent after this timestamp")) message_id = models.CharField("Message-ID", null=True, max_length=255, editable=False) number_of_retries = models.PositiveIntegerField(null=True, blank=True) headers = models.JSONField(_('Headers'), blank=True, null=True) template = models.ForeignKey('post_office.EmailTemplate', blank=True, null=True, verbose_name=_("Email template"), on_delete=models.CASCADE) context = context_field_class(_('Context'), blank=True, null=True) backend_alias = models.CharField(_("Backend alias"), blank=True, default='', max_length=64) class Meta: app_label = 'post_office' verbose_name = pgettext_lazy("Email address", "Email") verbose_name_plural = pgettext_lazy("Email addresses", "Emails") def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._cached_email_message = None def __str__(self): return '%s' % self.to def email_message(self): """ Returns Django EmailMessage object for sending. """ if self._cached_email_message: return self._cached_email_message return self.prepare_email_message() def prepare_email_message(self): """ Returns a django ``EmailMessage`` or ``EmailMultiAlternatives`` object, depending on whether html_message is empty. """ if get_override_recipients(): self.to = get_override_recipients() if self.template is not None: engine = get_template_engine() subject = engine.from_string(self.template.subject).render(self.context) plaintext_message = engine.from_string(self.template.content).render(self.context) multipart_template = engine.from_string(self.template.html_content) html_message = multipart_template.render(self.context) else: subject = smart_str(self.subject) plaintext_message = self.message multipart_template = None html_message = self.html_message connection = connections[self.backend_alias or 'default'] if isinstance(self.headers, dict) or self.expires_at or self.message_id: headers = dict(self.headers or {}) if self.expires_at: headers.update({'Expires': self.expires_at.strftime("%a, %-d %b %H:%M:%S %z")}) if self.message_id: headers.update({'Message-ID': self.message_id}) else: headers = None if html_message: if plaintext_message: msg = EmailMultiAlternatives( subject=subject, body=plaintext_message, from_email=self.from_email, to=self.to, bcc=self.bcc, cc=self.cc, headers=headers, connection=connection) msg.attach_alternative(html_message, "text/html") else: msg = EmailMultiAlternatives( subject=subject, body=html_message, from_email=self.from_email, to=self.to, bcc=self.bcc, cc=self.cc, headers=headers, connection=connection) msg.content_subtype = 'html' if hasattr(multipart_template, 'attach_related'): multipart_template.attach_related(msg) else: msg = EmailMessage( subject=subject, body=plaintext_message, from_email=self.from_email, to=self.to, bcc=self.bcc, cc=self.cc, headers=headers, connection=connection) for attachment in self.attachments.all(): if attachment.headers: mime_part = MIMENonMultipart(*attachment.mimetype.split('/')) mime_part.set_payload(attachment.file.read()) for key, val in attachment.headers.items(): try: mime_part.replace_header(key, val) except KeyError: mime_part.add_header(key, val) msg.attach(mime_part) else: msg.attach(attachment.name, attachment.file.read(), mimetype=attachment.mimetype or None) attachment.file.close() self._cached_email_message = msg return msg def dispatch(self, log_level=None, disconnect_after_delivery=True, commit=True): """ Sends email and log the result. """ try: self.email_message().send() status = STATUS.sent message = '' exception_type = '' except Exception as e: status = STATUS.failed message = str(e) exception_type = type(e).__name__ # If run in a bulk sending mode, reraise and let the outer # layer handle the exception if not commit: raise if disconnect_after_delivery: connections.close() if commit: self.status = status self.save(update_fields=['status']) if log_level is None: log_level = get_log_level() # If log level is 0, log nothing, 1 logs only sending failures # and 2 means log both successes and failures if log_level == 1: if status == STATUS.failed: self.logs.create(status=status, message=message, exception_type=exception_type) elif log_level == 2: self.logs.create(status=status, message=message, exception_type=exception_type) return status def clean(self): if self.scheduled_time and self.expires_at and self.scheduled_time > self.expires_at: raise ValidationError(_("The scheduled time may not be later than the expires time.")) def save(self, *args, **kwargs): self.full_clean() return super().save(*args, **kwargs)