class AboutUsImage(models.Model): image = models.ImageField('Image', upload_to='media/', null=True, blank=True) cropping = ImageRatioField('image', '677x218')
class Product(models.Model): name = models.CharField(max_length=100, verbose_name="Titolo:") name_uk = models.CharField('Titolo Inglese', max_length=250, null=True, blank=True) name_fr = models.CharField('Titolo Francese', max_length=250, null=True, blank=True) code = models.CharField('Codice', max_length=250, null=True, blank=True) category = models.ManyToManyField(Category, null=True, blank=True, verbose_name="Seleziona Categorie") ## composizione #composition = models.ManyToManyField(Composition, null=True, blank=True, verbose_name="Composizioni") quantity = models.IntegerField( blank=True, null=True, verbose_name="quantita", help_text="quantita quando non e composizione") ##PRICE price = models.DecimalField('Prezzo', max_digits=10, decimal_places=2, blank=True, null=True, help_text="prezzo base") discount = models.IntegerField(blank=True, null=True, default=0, verbose_name="sconto percentuale") price_offer = models.DecimalField('Prezzo Scontato', max_digits=10, decimal_places=2, blank=True, null=True) ##MULTIMEDIA image = models.ImageField(blank=True, null=True, upload_to='product', verbose_name="Immagine") slider = ImageRatioField('image', '1170x600', verbose_name="Slider") thumb = ImageRatioField('image', '800x578', verbose_name="Miniatura") thumbdue = ImageRatioField('image', '745x558', verbose_name="Miniatura pagina dettaglio") croplibero = ImageRatioField('image', '595x335', free_crop=True, verbose_name="Ritaglio Libero") album = FilerFolderField(null=True, blank=True) ## Data color = models.ManyToManyField(Color, null=True, blank=True, verbose_name="Seleziona Colori", help_text="solo se a 40 giorni") material = models.ManyToManyField(Material, null=True, blank=True, verbose_name="Seleziona Metallo", editable=False) scarpemisura = models.ManyToManyField(TagliaScarpe, null=True, blank=True, verbose_name="Taglia Scarpe", editable=False) cintureLunghezza = models.ManyToManyField(CintureLunghezza, null=True, blank=True, verbose_name="Lungheza Cinture", editable=False) size = models.CharField('Misure', max_length=250, null=True, blank=True) width = models.DecimalField(blank=True, max_digits=10, decimal_places=2, null=True, verbose_name="larghezza") lenght = models.DecimalField(blank=True, max_digits=10, decimal_places=2, null=True, verbose_name="lunghezza") depth = models.DecimalField(blank=True, max_digits=10, decimal_places=2, null=True, verbose_name="Profondita") height = models.DecimalField(blank=True, max_digits=10, decimal_places=2, null=True, verbose_name="altezza") volume = models.DecimalField('Volume', max_digits=10, decimal_places=2, blank=True, null=True) descrizione = models.TextField(null=True, blank=True, verbose_name="Descrizione") descrizione_uk = models.TextField(null=True, blank=True, verbose_name="Descrizione Inglese") descrizione_fr = models.TextField(null=True, blank=True, verbose_name="Descrizione Francese") ## Delivery prompt_delivery = models.BooleanField('Pronta Consegna', default=False) delivery = models.BooleanField('Consegna 40gg', default=False) summer = models.BooleanField('Estate', default=False) winter = models.BooleanField('Winter', default=False) start_season = models.DateField('Inizio Stagione', blank=True, null=True) end_season = models.DateField('Fine Stagione', blank=True, null=True) ## Accessory tags = TaggableManager(verbose_name="Parole chiave", blank=True) pub_date = models.DateTimeField('date published', editable=False) active = models.BooleanField('attiva', default=False) slide = models.BooleanField('Mostra in Slide', default=False) promo = models.BooleanField('Mostra in Promo', default=False) top_seller = models.BooleanField('Mostra in Piu Venduti', default=False) def save(self, *args, **kwargs): self.price_offer = self.price - (self.price * self.discount / 100) self.pub_date = datetime.now() super(Product, self).save(*args, **kwargs) # Call the "real" save() method. def image_img(self): if self.image: return u'<img src="%s" style="width:300px"/>' % self.image.url else: return '(Sin imagen)' image_img.short_description = 'Thumb' image_img.allow_tags = True def __unicode__(self): return self.name class Meta: verbose_name_plural = "Prodotti" ordering = ['id']
class Artwork(models.Model): artists = models.ManyToManyField(Artist, blank=True,related_name='artworks') crews = models.ManyToManyField(Crew, blank=True, related_name='artworks') category = models.ForeignKey(Artwork_Category, on_delete=models.SET_NULL, blank=True, null=True) title = models.CharField(max_length=200, blank=True, null=True) commission_date = models.CharField(max_length=200, blank=True, null=True, verbose_name='date commissioned') status = models.ForeignKey(Status, on_delete=models.SET_NULL, blank=True, null=True) decommission_date = models.CharField(max_length=200, blank=True, null=True, verbose_name='date decommissioned') description = models.TextField(blank=True, null=True) image = models.ImageField(upload_to='artwork/', max_length=500) watermarked_image = models.ImageField(null=True, upload_to='API_artwork/', max_length=500) cropping = ImageRatioField('image', '404x250') cropped_image = models.ImageField(upload_to='artwork/', blank=True, null=True, max_length=500) def image_thumbnail(self): thumbnailer = get_thumbnailer(self.image) thumbnail_options = {'size': (404, 250)} thumbnailer.get_thumbnail(thumbnail_options) return '<img src="%s" />' % thumbnailer.get_thumbnail(thumbnail_options).url image_thumbnail.short_description = 'Uploaded Image' image_thumbnail.allow_tags = True photo_credit = models.CharField(max_length=200, blank=True, null=True) photo_credit_email = models.EmailField(blank=True, null=True, verbose_name="Photo Credit's Email Address") city = models.CharField(max_length=200, blank=True, null=True) link = models.URLField(blank=True, null=True) location = models.PointField(srid=4326) objects = models.GeoManager() validated = models.BooleanField(default=False) street = models.CharField(max_length=200, blank=True, null=True, verbose_name="What street is the artwork on (to help in identifying)") admin_notes = models.TextField(blank=True, null=True, verbose_name="Write any notes about the artwork here (will not be shown on map)") map_enabled = models.BooleanField(default=True, verbose_name="Show this artwork on the map") smart_cities = models.BooleanField(default=True,verbose_name="Allow this artwork to be accessed by smartcities") slug = models.SlugField(max_length=255, blank=True, null=True) likes = models.ManyToManyField(User, related_name='likes', blank=True) checkins = models.ManyToManyField(User, related_name='checkins', blank=True) submitter_description = models.TextField(blank=True, null=True, verbose_name="Submitter's Description") submitter_name = models.CharField(blank=True, null=True, max_length=200, verbose_name="Submitter's Name") submitter_email = models.EmailField(blank=True, null=True, verbose_name="Submitter's Email Address") video_url = models.URLField(blank=True, null=True, verbose_name="Video URL") def get_absolute_url(self): return "/artwork/%d" % self.id def get_artists(self): return "\n".join([p.name for p in self.artists.all()]) @property def total_likes(self): """ Likes for the artwork :return: Integer: Likes for the artwork """ return self.likes.count() @property def total_checkins(self): """ Check ins for the artwork :return: Integer: Check ins for the artwork """ return self.checkins.count() @property def comments(self): ct = ContentType.objects.get_for_model(Artwork) obj_pk = self.id return Comment.objects.filter(content_type=ct,object_pk=obj_pk) def save(self, *args, **kwargs): if self.image != self.__original_image: self.image = convert_rgba(self.image) self.watermarked_image = add_watermark(self.image, Image.open(os.path.join(STATIC_ROOT, 'img/wts-watermark-logo-white.png'))) if self.pk and self.image == self.__original_image: self.cropped_image = get_thumbnailer(self.image).get_thumbnail( { 'size': (10000, 10000), 'box': self.cropping, 'crop': True, 'detail': True, } ).name if self.title != None and self.title != '': self.slug = slugify(self.title) else: self.slug = slugify(self.pk) super(Artwork, self).save(*args, **kwargs) def __str__(self): if self.pk and (self.title != "" or (self.artists.all().count() > 1 or (self.artists.all().count() == 1 and self.artists.filter(name="").count() != 1))): return_string = "" if self.title and self.title != "": return_string += self.title else: return_string += "Untitled" if self.artists.all().count() > 0: return_string += " by " + ", ".join([artist.__str__() for artist in self.artists.all()]) if self.street and self.street != "": return_string += ", on " + self.street return return_string else: return "Unknown Artwork" + ((", on " + self.street) if (self.street and self.street != "") else "") def __init__(self, *args, **kwargs): super(Artwork, self).__init__(*args, **kwargs) self.__original_image = self.image
class Activity(models.Model): objects = ActivityManager() created_at = models.DateTimeField(_('Created At'), auto_now_add=True) updated_at = models.DateTimeField(_('Updated At'), auto_now=True) event = models.ForeignKey(Event, verbose_name=_('Event')) title = models.CharField(_('Title'), max_length=100, blank=False, null=False) long_description = models.TextField(_('Long Description')) abstract = models.TextField(_('Abstract'), help_text=_('Short idea of the talk (Two or three sentences)')) justification = models.TextField(_('Justification'), blank=True, null=True, help_text=_('Why do you reject this proposal?')) room = models.ForeignKey(Room, verbose_name=_('Room'), blank=True, null=True) start_date = models.DateTimeField(_('Start Time'), blank=True, null=True) end_date = models.DateTimeField(_('End Time'), blank=True, null=True) activity_type_choices = ( ('1', _('Talk')), ('2', _('Workshop')), ('3', _('Lightning talk')), ('4', _('Other')) ) type = models.CharField( _('Type'), choices=activity_type_choices, max_length=200, null=True, blank=True) speakers_names = models.CharField(_('Speakers Names'), max_length=600, help_text=_("Comma separated speaker's names")) speaker_contact = models.EmailField(_('Speaker Contact'), help_text=_('Where can whe reach you \ from the organization team?')) labels = models.CharField(_('Labels'), max_length=200, help_text=_('Comma separated tags. i.e. Linux, \ Free Software, Archlinux')) presentation = models.FileField(_('Presentation'), upload_to='talks', blank=True, null=True, help_text=_('Any material you are going to use \ for the talk (optional, but recommended)')) level_choices = ( ('1', _('Beginner')), ('2', _('Medium')), ('3', _('Advanced')), ) level = models.CharField(_('Level'), choices=level_choices, max_length=100, help_text=_("Talk's Technical level")) additional_info = models.TextField(_('Additional Info'), blank=True, null=True, help_text=_('Any info you consider relevant \ for the organizer: i.e. Write here \ if your activity has any special requirement')) status_choices = ( ('1', _('Proposal')), ('2', _('Accepted')), ('3', _('Rejected')), ) status = models.CharField(_('Status'), choices=status_choices, max_length=20, help_text=_('Activity proposal status')) image = ImageCropField(upload_to='images_thumbnails', verbose_name=_('Image'), blank=True, null=True) cropping = ImageRatioField('image', '700x450', size_warning=True, verbose_name=_('Cropping'), help_text=_('The image must be 700x450 px. You can crop it here.')) is_dummy = models.BooleanField(_('Is a dummy Activity?'), default=False, help_text=_('A dummy activity is used for example for coffee \ breaks. We use this to exclude it from the index \ page and other places')) def __cmp__(self, other): return -1 if self.start_date.time() < other.start_date.time() else 1 def __str__(self): return '{} - {}'.format(self.event, self.title) def get_absolute_url(self): return reverse('activity_detail', args=(self.event.slug, self.event.uid, self.pk)) def get_schedule_info(self): schedule_info = { 'resourceId': self.room.pk, 'start': self.start_date.isoformat(), 'end': self.end_date.isoformat(), 'title': self.title, 'id': self.pk, 'url': "" } if not self.is_dummy: schedule_info['url'] = self.get_absolute_url() return schedule_info def schedule(self): if self.start_date and self.end_date: date = date_format(self.start_date, format='SHORT_DATE_FORMAT', use_l10n=True) return "{} - {} - {}".format( self.start_date.strftime("%H:%M"), self.end_date.strftime("%H:%M"), date) return _('Schedule not confirmed yet') @classmethod def check_status(cls, message, error=None, request=None): if error: raise ValidationError(message) if request: messages.error(request, message) #pylint: disable=too-many-arguments @classmethod def room_available(cls, request, proposal, event_uid, event_date, error=False): activities_room = Activity.objects.filter( room=proposal.room, event__uid=event_uid, start_date__date=event_date) if proposal.start_date == proposal.end_date: message = _("The talk couldn't be registered because the schedule not \ available (start time equals end time)") cls.check_status(message, error=error, request=request) return False if proposal.end_date < proposal.start_date: message = _("The talk couldn't be registered because the schedule is not \ available (start time is after end time)") cls.check_status(message, error=error, request=request) return False one_second = datetime.timedelta(seconds=1) if activities_room.filter( end_date__range=( proposal.start_date + one_second, proposal.end_date - one_second)) \ .exclude(pk=proposal.pk).exists() \ or activities_room.filter( end_date__gt=proposal.end_date, start_date__lt=proposal.start_date).exclude(pk=proposal.pk).exists() \ or activities_room.filter( start_date__range=( proposal.start_date + one_second, proposal.end_date - one_second)) \ .exclude(pk=proposal.pk).exists() \ or activities_room.filter( end_date=proposal.end_date, start_date=proposal.start_date).exclude(pk=proposal.pk).exists(): message = _("The talk couldn't be registered because the \ room or the schedule is not available") cls.check_status(message, error=error, request=request) return False return True class Meta(object): ordering = ['title'] verbose_name = _('Activity') verbose_name_plural = _('Activities')
class User(AbstractBaseUser, PermissionsMixin): objects = UserManager() USERNAME_FIELD = 'email' email = models.EmailField(_('email address'), unique=True) first_name = models.CharField(_('first name'), max_length=30, blank=True) last_name = models.CharField(_('last name'), max_length=30, blank=True) is_staff = models.BooleanField( _('staff status'), default=False, help_text=_('Designates whether the user can log into this admin ' 'site.')) is_active = models.BooleanField( _('active'), default=True, help_text=_('Designates whether this user should be treated as ' 'active. Unselect this instead of deleting accounts.')) date_joined = models.DateTimeField(_('date joined'), default=timezone.now) # ------------------------------------------------- avatar = ImageCropField(upload_to="avatars/", verbose_name=_('Avatar'), validators=[avatar_validation], null=True, blank=True) cropping = ImageRatioField( 'avatar', '128x128', verbose_name=_('Seleção (Enquadramento)'), help_text=_('A configuração do Avatar ' 'é possível após a atualização da fotografia.')) pwd_created = models.BooleanField( _('Usuário de Rede Social Customizou Senha?'), default=False) be_notified_by_email = models.BooleanField( _('Receber Notificações por email?'), default=True) class Meta(AbstractBaseUser.Meta): abstract = False permissions = MENU_PERMS_FOR_USERS ordering = ('first_name', 'last_name') def __str__(self): return self.get_display_name() @property def username(self): return self.get_username() def get_full_name(self): """ Returns the first_name plus the last_name, with a space in between. """ return ' '.join([self.first_name, self.last_name]).strip() def get_short_name(self): """ Returns the short name for the user. """ return self.first_name def get_display_name(self): return self.get_full_name() or self.email @permalink def get_absolute_url(self): return 'users_profile', [self.pk], {} def delete(self, using=None, keep_parents=False): if self.groups.all().exclude(name=GROUP_SOCIAL_USERS).exists(): raise PermissionDenied( _('Você não possui permissão para se autoremover do Portal!')) return AbstractBaseUser.delete(self, using=using, keep_parents=keep_parents)
class Image(models.Model): jsonld_type = 'ImageObject' """ Tavastia Events data_source blank=True lisätty license default arvo muutettu event_only """ # Properties from schema.org/Thing name = models.CharField(verbose_name=_('Name'), max_length=255, db_index=True, default='') data_source = models.ForeignKey(DataSource, related_name='provided_%(class)s_data', db_index=True, null=True, blank=True) publisher = models.ForeignKey('django_orghierarchy.Organization', verbose_name=_('Publisher'), db_index=True, null=True, blank=True, related_name='Published_images') created_time = models.DateTimeField(auto_now_add=True) last_modified_time = models.DateTimeField(auto_now=True, db_index=True) created_by = models.ForeignKey(User, null=True, blank=True, related_name='EventImage_created_by') last_modified_by = models.ForeignKey( User, related_name='EventImage_last_modified_by', null=True, blank=True) image = models.ImageField(upload_to='images', null=True, blank=True) url = models.URLField(verbose_name=_('Image'), max_length=400, null=True, blank=True) cropping = ImageRatioField('image', '800x800', verbose_name=_('Cropping')) license = models.ForeignKey(License, verbose_name=_('License'), related_name='images', default='event_only') photographer_name = models.CharField(verbose_name=_('Photographer name'), max_length=255, null=True, blank=True) def save(self, *args, **kwargs): if not self.publisher: try: self.publisher = self.created_by.get_default_organization() except AttributeError: pass # ensure that either image or url is provided if not self.url and not self.image: raise ValidationError(_('You must provide either image or url.')) if self.url and self.image: raise ValidationError( _('You can only provide image or url, not both.')) self.last_modified_time = BaseModel.now() super(Image, self).save(*args, **kwargs) def is_user_editable(self): return self.data_source.user_editable def is_user_edited(self): return bool(self.data_source.user_editable and self.last_modified_by) def can_be_edited_by(self, user): """Check if current event can be edited by the given user""" if user.is_superuser: return True return user.is_admin(self.publisher) """ Tavastia Events Admin puolelle nimen palautus """ def __str__(self): name_to_admin = "" if self.name is not None: name_to_admin = self.name else: name_to_admin = "Ei nimeä" return name_to_admin
class Vlesson(models.Model): name = models.CharField(max_length=250, blank=True, verbose_name=_(u'Name')) desc = models.TextField(blank=True, verbose_name=_(u'Description')) is_active = models.BooleanField(verbose_name=_('Is main?'), default=False) owner = models.ForeignKey(User, verbose_name=_(u'Owner')) course = models.ForeignKey(Vcourse, verbose_name=_(u'Course'), blank=True, null=True) video = models.FileField(blank=True, verbose_name=_(u'Video'), upload_to=path_and_rename('vcourse_video'), null=True) is_converted = models.BooleanField(verbose_name=_('Is converted?'), default=False) is_error = models.BooleanField(verbose_name=_('Is converted?'), default=False) error_desc = models.TextField(blank=True, verbose_name=_(u'Error description')) is_free = models.BooleanField(verbose_name=_('Is free?'), default=False) name_slug = models.CharField(verbose_name='Name slug', max_length=250, blank=True) duration = models.CharField(verbose_name='Duration', max_length=250, blank=True) price = models.DecimalField(default=0, max_digits=5, decimal_places=2) is_public = models.BooleanField(verbose_name=_('Is public?'), default=True) image = models.ImageField(blank=True, verbose_name=_(u'Image'), upload_to='vcourse_images', null=True) cropping = ImageRatioField('image', '200x155', size_warning=True) number = models.PositiveIntegerField(verbose_name=_(u'Number'), default=0) def get_absolute_url(self): return reverse("start-lecture", kwargs={"id": self.id}) @property def file_name(self): return str(self.video).split('/')[1] @property def screenshot(self): try: thumbnail_url = get_thumbnailer(self.image).get_thumbnail({ 'size': (200, 155), 'box': self.cropping, 'crop': True, 'detail': True, }).url return mark_safe(u'<img src="%s" />' % thumbnail_url) except: return 'no image' return 'no' @property def price_str(self): if self.is_free or self.price == 0: return u'free' else: return self.price def __unicode__(self): return self.name def save(self, **kwargs): if not self.id: self.name_slug = pytils.translit.slugify(self.name) if self.video.path.split('.')[-1] == 'flv': self.is_converted = True return super(Vlesson, self).save(**kwargs)
class Product(models.Model): # pragma: no cover name = models.CharField(max_length=200, verbose_name=_("name")) slug = models.SlugField(max_length=200, db_index=True, unique=True, verbose_name=_("slug")) size = models.ManyToManyField(Size, related_name="products", verbose_name=_("size"), blank=True) color = models.ManyToManyField(Color, related_name="products", verbose_name=_("color"), blank=True) category = models.ManyToManyField(Category, related_name="products", blank=True, verbose_name=_("categories")) custom_image = models.BooleanField( default=False, verbose_name=_("Customer can choose an Image")) custom_color = models.BooleanField( default=False, verbose_name=_("Customer can choose a Color")) description = RichTextField(_("description"), null=True, blank=True) extra_info = RichTextField(_("extra info"), null=True, blank=True) image = models.ImageField(upload_to=product_image_upload, verbose_name=_("image from Product Detail Page")) cropping = ImageRatioField("image", "270x300", verbose_name=_("image ration")) cropping_home = ImageRatioField("image", "225x250", verbose_name=_("image ration")) cropping_category = ImageRatioField("image", "175x194", verbose_name=_("image ration")) cropping_related = ImageRatioField("image", "84x93", verbose_name=_("image ration")) featured = models.BooleanField(default=False, verbose_name=_("is featured")) min_order = models.IntegerField( default=1, validators=[MaxValueValidator(10000), MinValueValidator(1)], verbose_name=_("minimum order"), ) related = models.ManyToManyField( "self", related_name="related_products", blank=True, verbose_name=_("related products"), ) def __str__(self): return f"{self.name}" class Meta: verbose_name = _("Product") verbose_name_plural = _("Products") def save(self, *args, **kwargs): if not self.slug: slug = slugify(self.name) self.slug = slug return super().save(*args, **kwargs) def all_variations(self): return self.prices.all().order_by("price") def get_minimum_price(self): minimum_price = None prices = self.prices.all().order_by("price") if prices: minimum_price = prices[0] return minimum_price def get_minimum_quantity(self): minimum_quantity = None quantities = self.prices.all().order_by("min_quantity") if quantities: minimum_quantity = quantities[0] return minimum_quantity def get_maximum_quantity(self): maximum_quantity = None quantities = self.prices.all().order_by("-max_quantity") if quantities: maximum_quantity = quantities[0] return maximum_quantity def get_maximum_price(self): maximum_price = None prices = self.prices.all().order_by("-price") if prices: maximum_price = prices[0] return maximum_price def get_price(self, quantity=1): prices = self.prices.filter( min_quantity__lte=quantity, max_quantity__gte=quantity).order_by("price") price = self.prices.first() if prices: price = prices[0] return price
class Image(models.Model): jsonld_type = 'ImageObject' objects = BaseQuerySet.as_manager() # Properties from schema.org/Thing name = models.CharField(verbose_name=_('Name'), max_length=255, db_index=True, default='') data_source = models.ForeignKey(DataSource, on_delete=models.CASCADE, related_name='provided_%(class)s_data', db_index=True, null=True) publisher = models.ForeignKey('django_orghierarchy.Organization', on_delete=models.CASCADE, verbose_name=_('Publisher'), db_index=True, null=True, blank=True, related_name='Published_images') created_time = models.DateTimeField(auto_now_add=True) last_modified_time = models.DateTimeField(auto_now=True, db_index=True) created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, related_name='EventImage_created_by') last_modified_by = models.ForeignKey( User, on_delete=models.SET_NULL, related_name='EventImage_last_modified_by', null=True, blank=True) image = models.ImageField(upload_to='images', null=True, blank=True) url = models.URLField(verbose_name=_('Image'), max_length=400, null=True, blank=True) cropping = ImageRatioField('image', '800x800', verbose_name=_('Cropping')) license = models.ForeignKey(License, on_delete=models.SET_NULL, verbose_name=_('License'), related_name='images', default='event_only', null=True) photographer_name = models.CharField(verbose_name=_('Photographer name'), max_length=255, null=True, blank=True) alt_text = models.CharField(verbose_name=_('Alt text'), max_length=320, null=True, blank=True) def save(self, *args, **kwargs): if not self.publisher: try: self.publisher = self.created_by.get_default_organization() except AttributeError: pass # ensure that either image or url is provided if not self.url and not self.image: raise ValidationError(_('You must provide either image or url.')) if self.url and self.image: raise ValidationError( _('You can only provide image or url, not both.')) self.last_modified_time = BaseModel.now() super(Image, self).save(*args, **kwargs) def is_user_editable(self): return bool(self.data_source and self.data_source.user_editable) def is_user_edited(self): return bool(self.is_user_editable() and self.last_modified_by) def can_be_edited_by(self, user): """Check if current image can be edited by the given user""" if user.is_superuser: return True return user.is_admin(self.publisher)
class Member(models.Model): """ Represents a member of Cambridge South Hockey Club. Alternatively this can be thought of as a 'Player' model. User accounts will be associated with a member instance wherever possible. """ user = models.OneToOneField(settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.SET_NULL) """ The user (if any) associated with this member """ first_name = models.CharField(max_length=100, default=None) """ Members first name (required) """ known_as = models.CharField(max_length=100, default=None, null=True, blank=True) """ The first name by which the member is typically known (optional) """ last_name = models.CharField(max_length=100, default=None) """ Members surname (required) """ profile_pic = ResizedImageField("Profile picture", size=[400, 400], upload_to=get_file_name, null=True, blank=True) """ An optional profile picture of the member """ profile_pic_cropping = ImageRatioField('profile_pic', '400x400') """ Image cropping support """ gender = models.CharField("Gender", max_length=6, choices=Gender.Choices, default=Gender.Male) """ The member's gender """ pref_position = models.IntegerField("Preferred position", choices=Position.Choices, default=Position.Other) """ The member's preferred playing position. Defaults to 'not known'. """ is_current = models.BooleanField( "Current", help_text="Is this member currently part of the club?", default=True) """ Indicates whether this member is a current member of the club. Useful for filtering etc. """ shirt_number = models.CharField(max_length=4, blank=True) """ Players shirt number """ is_coach = models.NullBooleanField( "Coach?", null=True, blank=True, default=False, help_text='Does this member possess a hockey coaching qualification?') """ Indicates whether this member is a coach """ is_umpire = models.NullBooleanField( "Umpire?", null=True, blank=True, default=False, help_text= 'Is this member a qualified hockey umpire (including probationer)?') """ Indicates whether this member is a umpire """ dob = models.DateField('Date of birth', help_text="Used for medical information", null=True, blank=True) """ Member's date of birth - used for medical information """ emergency_contact = models.CharField( max_length=255, null=True, blank=True, help_text="Name of person to contact in an emergency") """ Name of person to contact in an emergency """ emergency_relationship = models.CharField( "Emergency contact relationship", help_text="The member's emergency contact's relationship to them", max_length=100, choices=EmergencyContactRelationship, null=True, blank=True, default=EmergencyContactRelationship.Other) """ The member's emergency contact's relationship to them """ emergency_phone = models.CharField( "Emergency contact phone", max_length=15, null=True, blank=True, help_text="Phone number of person to contact in an emergency") """ Phone number of person to contact in an emergency """ medical_notes = models.TextField( help_text="E.g. allergies, etc. in case of medical treatment", null=True, blank=True) """Any additional medical notes about this member """ email = models.EmailField(null=True, blank=True) """ Member's email address """ phone = models.CharField("Phone number", max_length=15, null=True, blank=True) """ Member's phone number """ addr_street = models.CharField("Address (street)", max_length=255, null=True, blank=True) """ Member's home address: house number and street """ addr_line2 = models.CharField("Address (line 2)", max_length=255, null=True, blank=True) """ Member's home address: optional second line """ addr_town = models.CharField("Address (town)", max_length=255, null=True, blank=True) """ Member's home address: city/town """ addr_postcode = models.CharField("Address (post code)", max_length=10, null=True, blank=True) """ Member's home address: post code """ addr_position = GeopositionField("Address (lat/long)", null=True, blank=True) """ Member's home address: lat/Long location (used for Google Maps etc) """ objects = MemberManager() class Meta: """ Meta-info for the Member model.""" app_label = 'members' ordering = ['first_name', 'last_name'] permissions = (( "view_personal_data", "Can see the personal data (address, phone, email, medical notes etc) of a member" ), ) def __str__(self): return str(self.full_name()) def save(self, *args, **kwargs): # Try to do a geocode lookup if the address is set and the position isn't known if self.addr_postcode and not self.addr_position: try: g = geocoder.google(self.full_address()) if g.latlng: self.addr_position = "{},{}".format( g.latlng[0], g.latlng[1]) else: LOG.error("Failed to geocode position for member %s", self.full_name(), exc_info=True) except: LOG.error("Failed to geocode position for member %s", self.full_name(), exc_info=True) super(Member, self).save(*args, **kwargs) # If the first and/or last name has been changed, update the corresponding user fields # if there is a user associated with this member if self.user is not None: modified = False if self.user.first_name != self.first_name: self.user.first_name = self.first_name modified = True if self.user.last_name != self.last_name: self.user.last_name = self.last_name modified = True if modified: self.user.save() @models.permalink def get_absolute_url(self): """ Returns the url for this member instance.""" return ('member_detail', [self.pk]) def pref_first_name(self): """ Returns the member's preferred first name (known_as if set; otherwise first_name) """ return self.known_as if self.known_as else self.first_name def full_name(self): """ Returns the member's full name.""" return u"{} {}".format(self.pref_first_name(), self.last_name) def first_name_and_initial(self): """ Returns the shortened name display for this member.""" return u"{} {}".format(self.pref_first_name(), self.last_name[0]) @property def address_known(self): """ Returns True if the member's address is known. Currently this just checks if the postcode or position fields are populated. """ return True if self.addr_postcode or self.addr_position else False def full_address(self, separator=", "): """ Returns the member's full home address with (not None) address items separated by commas. If the address is empty, returns 'Address unknown'. """ addr = separator.join( filter(None, (self.addr_street, self.addr_line2, self.addr_town, self.addr_postcode))) if not addr.strip(): return 'Address unknown' return addr def current_squad(self): """ Returns the member's current squad membership (if they are currently in a squad; otherwise None) """ try: return self.squadmembership_set.current().first() except: return None
class Teacher(models.Model): """ Teacher model Represents options, specific to a teacher. Usualy accessable via `user.teacher_data` Acceptable lessons ================== Before teacher can host an event, he should be allowed to do that by adding event type to the `allowed_lessons` property. """ ENABLED = ( (0, 'Inactive'), (1, 'Active'), ) objects = TeacherManager() user = models.OneToOneField(User, on_delete=models.PROTECT, related_name='teacher_data', limit_choices_to={ 'is_staff': 1, 'crm__isnull': False }) allowed_lessons = models.ManyToManyField( ContentType, related_name='+', blank=True, limit_choices_to={'app_label': 'lessons'}) teacher_photo = models.ImageField(upload_to='teachers/', null=True, blank=True) teacher_photo_cropping = ImageRatioField('teacher_photo', '500x500') teacher_avatar_cropping = ImageRatioField('teacher_photo', '80x80') title = models.TextField(max_length=32, blank=True) announce = models.TextField(max_length=140) active = models.IntegerField(default=1, choices=ENABLED) class Meta: verbose_name = 'Teacher profile' ordering = ['user__last_name'] def save(self, *args, **kwargs): """ Add new teachers to the 'teachers' group """ if not self.pk: try: group = Group.objects.get(pk=settings.TEACHER_GROUP_ID) self.user.groups.add(group) self.user.save() except Group.DoesNotExist: pass super().save(*args, **kwargs) def __str__(self): return '%s (%s)' % (self.user.crm.full_name, self.user.username) def get_teacher_photo(self): """ Get, if exists, big teachers photo """ if self.teacher_photo: return cropped_thumbnail(context={}, instance=self, ratiofieldname='teacher_photo_cropping') def get_teacher_avatar(self): """ Get, if exists, small teacher photo """ if self.teacher_photo: return cropped_thumbnail(context={}, instance=self, ratiofieldname='teacher_avatar_cropping') def get_title(self): """ Get teacher title, currently — the value of the :model:`teachers.Teacher`.title property. """ return self.title def find_free_slots(self, date, period=datetime.timedelta(minutes=30), **kwargs): """ Get datetime.datetime objects for free slots for a date. Accepts keyword arguments for filtering output of :model:`timeline.Entry`. Returns an iterable of available slots in format ['15:00', '15:30', '16:00'] """ self.__delete_lesson_types_that_dont_require_a_timeline_entry(kwargs) # if there are any filters left — find timeline entries if len(kwargs.keys()): return SlotList(self.__find_timeline_entries(date=date, **kwargs)) # otherwise — return all available time based on working hours hours = self.working_hours.for_date(date=date) if hours is None: return None if hours.end > timezone.make_aware(minute_till_midnight(date)): hours.end = timezone.make_aware(minute_after_midnight(date)) auto_schedule = AutoSchedule(teacher=self) return auto_schedule.slots(hours.start, hours.end, period) def free_slots_for_dates(self, dates): """ Get an iterable of by-day auto schedule """ for date in dates: yield {'date': date, 'slots': self.find_free_slots(date)} def available_lessons(self, lesson_type): """ Get list of lessons, that teacher can lead """ for i in self.allowed_lessons.all(): if i == lesson_type: Model = i.model_class() if hasattr(Model, 'host'): return Model.objects.filter(host=self) else: return [ Model.get_default() ] # all non-hosted lessons except the default one are for subscriptions, nobody needs to host or plan them return [] def available_lesson_types(self): """ Get contenttypes of lessons, allowed to host """ lesson_types = {} for i in self.allowed_lessons.all(): Model = i.model_class() if not hasattr(Model, 'sort_order'): continue if hasattr(Model, 'host') and not self.available_lessons( i ): # hosted lessons should be returned only if they have lessons continue lesson_types[Model.sort_order()] = i for i in sorted(list(lesson_types.keys())): yield lesson_types[i] def get_absolute_url(self): """ Teacher detail page """ return reverse('teachers:detail', kwargs={'username': self.user.username}) def timeline_url(self): """ Get teacher's timeline URL """ return reverse('timeline:timeline', kwargs={'username': self.user.username}) def __find_timeline_entries(self, date, **kwargs): """ Find timeline entries of lessons with specific type, assigned to current teachers. Accepts kwargs for filtering output of :model:`timeline.Entry`. Returns an iterable of slots as datetime objects. """ TimelineEntry = apps.get_model('timeline.entry') for entry in TimelineEntry.objects.filter(teacher=self, start__range=day_range(date), **kwargs): if entry.is_free: try: entry.clean() except (AutoScheduleExpcetion, DoesNotFitWorkingHours) as e: continue yield entry.start def __delete_lesson_types_that_dont_require_a_timeline_entry(self, kwargs): """ Check if lesson class, passed as filter to free_slots() requires a timeline slot. If not — delete this filter argument from kwargs. """ lesson_type = kwargs.get('lesson_type') if lesson_type is None: return try: Lesson = ContentType.objects.get(pk=lesson_type).model_class() except ContentType.DoesNotExist: return if not Lesson.timeline_entry_required(): del kwargs['lesson_type']
class Advices(models.Model): title = models.CharField(max_length=150, null=True, blank=True) text = models.TextField(max_length=10000, null=True, blank=True) image = models.ImageField('Image', upload_to='media/', null=True, blank=True) cropping = ImageRatioField('image', '900x300')
class Doctor(models.Model): name = models.CharField('Name', max_length=250, null=True, blank=True) image = models.ImageField('Photo', upload_to='media/', null=True, blank=True) cropping = ImageRatioField('image', '430x500') portfolio = models.TextField('Портфолио', max_length=2000, null=True, blank=True)
class Image(models.Model): image = models.ImageField('Image', upload_to='media/', null=True, blank=True) cropping = ImageRatioField('image', '460x220')
class Slide(models.Model): description = models.CharField(max_length=200, blank=True) picture = ImageCropField(upload_to='codelab-slides', blank=True) cropPicture = ImageRatioField('picture', '1200x550', allow_fullsize=True) def __unicode__(self): return self.description
class Survey(models.Model): class Meta: verbose_name_plural = 'Surveys' ordering = ['the_order'] FONT_CHOICES = ( ('Times', "'Times New Roman', Times, serif"), ('Monospace', "'Courier New', Courier, monospace"), ('Sans', "Arial, Helvetica, sans-serif"), ('Century Gothic', "'Century Gothic', CenturyGothic, AppleGothic, sans-serif;"), ('Futura', "Futura, 'Trebuchet MS', Arial, sans-serif"), ('Garamond', "Garamond, Baskerville, 'Baskerville Old Face', 'Hoefler Text', 'Times New Roman', serif"), ('Rockwel', "Rockwell, 'Courier Bold', Courier, Georgia, Times, 'Times New Roman', serif"), ) user = models.ForeignKey(User, null=True) title = models.CharField(max_length=100) language = models.CharField(max_length=30) description = models.CharField(max_length=1000) created = models.DateTimeField(auto_now_add=True) notify = models.BooleanField(default=False, verbose_name='Receive email notification for every submit') the_order = models.PositiveIntegerField(default=0, editable=False, db_index=True) hide_ghost = models.BooleanField(default=True) logo = ImageCropField(null=True, blank=True, upload_to='media/',) cropping = ImageRatioField('logo', '430x360', free_crop=True) logo_height = models.IntegerField(default=20) header_size = models.IntegerField(default=180, verbose_name='Title Size') description_size = models.IntegerField(default=150) question_size = models.IntegerField(default=130) choice_size = models.IntegerField(default=100) left_margin = models.IntegerField(default=10) top_margin = models.IntegerField(default=5) choice_indent = models.IntegerField(default=5) nested_indent = models.IntegerField(default=5) background_color = models.CharField(max_length=40, default='white') header_color = models.CharField(max_length=40, default='black', verbose_name='Title Color') description_color = models.CharField(max_length=40, default='black') question_color = models.CharField(max_length=40, default='black') choice_color = models.CharField(max_length=40, default='black') font = models.CharField(max_length=30, choices=FONT_CHOICES, default='Sans', verbose_name='Font Family') welcome_letter = models.ForeignKey( Elmail, null=True, blank=True, related_name='survey_welcome') newsletter = models.ForeignKey( Elmail, on_delete=models.SET_NULL, null=True, blank=True, related_name='survey_newsletter') publish_url = models.URLField(null=True, blank=True) def url(self): self.publish_url = '/{0}/survey/'.format(self.pk) # self.save() return format_html('<a href="{0}">{0}</a>'.format(self.publish_url)) def __str__(self): time = str(self.created)[:16] return self.title + ' -- ' + 'created: ' + time def send_newsletter(self): pass
class Flagmans(models.Model): def user_directory_path(instance, filename): return '{0}/{1}/{2}'.format(instance._meta.app_label, instance.id, filename) title = models.CharField(max_length=150, verbose_name="Название флагмана", blank=False, default='') imageOld = models.ImageField(validators=[validate_image], blank=True, default='', verbose_name="Картинка", upload_to=user_directory_path) image = ImageRatioField( 'imageOld', '320x300', help_text="Выберите область для отображения картинки", verbose_name="Отображение картинки") address = models.CharField(blank=True, default="", max_length=301, verbose_name="Место проведения") url = models.CharField(blank=True, default="", max_length=201, verbose_name="Ссылка") map = models.CharField(blank=True, default="", max_length=1501, verbose_name="Ссылка на яндекс-карту") dateStart = models.DateField(default=timezone.now, blank=False, verbose_name="Дата начала") dateEnd = models.DateField( blank=True, verbose_name= "Дата окончания/проведения(ОСТАВЬТЕ ПУСТЫМ, ЕСЛИ У ФЛАГМАНА НЕТ ПЕРИОДА ПРОВЕДЕНИЯ)", null=True) date = models.CharField(max_length=100, verbose_name="Строковое представление даты", default="", blank=False) def __str__(self): return self.title def save(self, *args, **kwargs): if self.id: import os, glob path = './media/{0}/{1}/*.*'.format(self._meta.app_label, self.id) pathOld = '.{0}*.*'.format(self.imageOld.url) filesOld = glob.glob(pathOld) filesOld.append("." + self.imageOld.url) for file in glob.glob(path): if file not in filesOld: os.remove(file) else: saved_image = self.imageOld self.imageOld = None super(Flagmans, self).save(*args, **kwargs) self.imageOld = saved_image return super(Flagmans, self).save(*args, **kwargs) def delete(self, *args, **kwargs): import os, shutil path = './media/{0}/{1}'.format(self._meta.app_label, self.id) if os.path.exists(path): shutil.rmtree(path) return super(Flagmans, self).delete(*args, **kwargs) class Meta(object): verbose_name = "Флагман" verbose_name_plural = "Флагманы" ordering = ['dateStart', 'dateEnd'] indexes = ( models.Index(fields=['title']), models.Index(fields=['address']), )
class Team(models.Model): creator = models.ForeignKey(User, blank=True) name = models.CharField(max_length=255, unique=True) position = models.CharField(max_length=255) alumni = models.BooleanField(default=False) original_image_width = models.PositiveIntegerField(null=True) original_image_height = models.PositiveIntegerField(null=True) thumb_image_width = models.PositiveIntegerField(null=True, blank=False) thumb_image_height = models.PositiveIntegerField(null=True, blank=False) image = ImageCropField(upload_to='uploaded_images') mini_image = ImageRatioField('image', free_crop=True) email = models.CharField(max_length=255, null=True, blank=True) show_email = models.BooleanField(default=False) yahoo = models.CharField(max_length=255, null=True, blank=True) picasa = models.CharField(max_length=255, null=True, blank=True) youtube = models.CharField(max_length=255, null=True, blank=True) OSF_url = models.CharField(max_length=255, null=True, blank=True) pinterest = models.CharField(max_length=255, null=True, blank=True) wordpress = models.CharField(max_length=255, null=True, blank=True) tumblr_url = models.CharField(max_length=255, null=True, blank=True) google_url = models.CharField(max_length=255, null=True, blank=True) github_url = models.CharField(max_length=255, null=True, blank=True) twitter_url = models.CharField(max_length=255, null=True, blank=True) facebook_url = models.CharField(max_length=255, null=True, blank=True) linkedin_url = models.CharField(max_length=255, null=True, blank=True) personal_website = models.CharField(max_length=255, null=True, blank=True) mailing_lists = models.ManyToManyField(MailingList, null=True, blank=True) def __unicode__(self): return self.name def get_thumb_max_size(self): return str(self.thumb_image_width) + 'x' + str(self.thumb_image_height) def add_to_group(self, mailing_list): storage = Storage(CredentialsModel, 'id', self.creator, 'credential') credential = storage.get() if credential is None or credential.invalid: return False mail = mailing_list.email post_data = {'email': self.email, 'role': 'MEMBER'} http_auth = credential.authorize(httplib2.Http()) service = build('admin', 'directory_v1', http=http_auth) create = service.members().insert(groupKey=mail, body=post_data) return create.execute() def remove_from_group(self, mailing_list): storage = Storage(CredentialsModel, 'id', self.creator, 'credential') credential = storage.get() if credential is None or credential.invalid: return False mail = mailing_list.email http_auth = credential.authorize(httplib2.Http()) service = build('admin', 'directory_v1', http=http_auth) create = service.members().delete(groupKey=mail, memberKey=self.email) return create.execute() # def delete(self, using=None): # for group in self.mailing_lists.all(): # self.remove_from_group(group) # return super(Team, self).delete() def save(self, *args, **kwargs): found_id = self.id super(Team, self).save(*args, **kwargs) if self.image and found_id is None and self.original_image_width and self.original_image_height: self.image = get_thumbnailer(self.image).get_thumbnail({ 'size': (self.original_image_width, self.original_image_height) }).name super(Team, self).save(*args, **kwargs) # all_emails = self.mailing_lists.all() # for email in all_emails: # self.add_to_group(email) return None class Meta: ordering = ('name', ) verbose_name_plural = u'Add COS Team Member' verbose_name = u'COS'
class Casehistory(models.Model): titolo = models.CharField(max_length=100) titolo_uk = models.CharField(max_length=250, null=True, blank=True) sottotitolo = models.CharField(max_length=250, null=True, blank=True) sottotitolo_uk = models.CharField(max_length=250, null=True, blank=True) azienda = models.CharField(max_length=250, null=True, blank=True, verbose_name="Azienda") link = models.CharField(max_length=250, null=True, blank=True) provincia = models.ForeignKey(Province, null=True, blank=True) location = models.CharField(max_length=250, null=True, blank=True) body = models.TextField(null=True, blank=True, verbose_name="Descrizione") body_uk = models.TextField(null=True, blank=True, verbose_name="Descrizione Inglese") image = models.ImageField(blank=True, null=True, upload_to='casehistory') cropping = ImageRatioField('image', '500x281', verbose_name="500x281") slidepage = ImageRatioField('image', '870x480', verbose_name="870x480") croppingthumb = ImageRatioField('image', '595x335', verbose_name="595x335") croppingslide = ImageRatioField('image', '1140x487', verbose_name="1140x487") croppingcarousel = ImageRatioField('image', '198x132', verbose_name="198x132") croppingrender = ImageRatioField('image', '1199x674', verbose_name="1199x674") designthumb = ImageRatioField('image', '500x469', verbose_name="Design Miniatura") designbig = ImageRatioField('image', '1200x800', verbose_name="Design HD", free_crop=True) designnews = ImageRatioField('image', '1200x1125', verbose_name="News") album = FilerFolderField(null=True, blank=True) planimetria = models.ImageField(blank=True, null=True, upload_to='planimetria') planimetria_crop = ImageRatioField('planimetria', '1200x800', verbose_name="Design HD", free_crop=True) attiva_slider = models.BooleanField('attiva in slider', default=False) active = models.BooleanField('attiva', default=False) tags = TaggableManager(verbose_name="Parole chiave", blank=True) def image_img(self): if self.image: return u'<img src="%s" style="width:300px"/>' % self.image.url else: return '(Sin imagen)' image_img.short_description = 'Thumb' image_img.allow_tags = True def __unicode__(self): return self.titolo class Meta: verbose_name_plural = "Case History"
class Sample(models.Model): """A Sample refers to the resulting compound of a specific experiment """ sample_number = models.CharField(max_length=10, db_index=True) name = models.CharField(max_length=200, db_index=True) formula = models.CharField(max_length=50, db_index=True, blank=True) stripped_formula = models.CharField(max_length=50, db_index=True, blank=True) AVAILABLE_MEDIUMS = [ ('Ballmill', 'Ballmill'), ('Tube: Borosilicate', 'Tube: Borosilicate'), ('Tube: Quartz', 'Tube: Quartz'), ('Tube: Alumina', 'Tube: Alumina'), ] AVAILABLE_ATMOSPHERES = [ ('Argon', 'Argon'), ('5%H2:95%N2', '5%H2:95%N2'), ('Oxygen', 'Oxygen'), ('Nitrogen', 'Nitrogen'), ('Air', 'Air'), ] experiment_medium = models.CharField(max_length=50, choices=AVAILABLE_MEDIUMS) experiment_atmosphere = models.CharField(max_length=50, choices=AVAILABLE_ATMOSPHERES) experiment_variable = models.FloatField(null=True, blank=True) experiment_time = models.FloatField(blank=True, null=True) experiment_equation = models.TextField(blank=True) variable_units = models.CharField(max_length=5, blank=True) file_photo = ImageCropField(blank=True, null=True, upload_to=root_file_storage + 'Photo') cropping = ImageRatioField('file_photo', '300x300') file_XRD = models.FileField(upload_to=root_file_storage + 'XRD', null=True, blank=True, validators=[validate_file_extension]) file_EC = models.FileField(upload_to=root_file_storage + 'EC', null=True, blank=True, validators=[validate_file_extension]) file_TEM = models.FileField(upload_to=root_file_storage + 'TEM', null=True, blank=True, validators=[validate_file_extension]) file_TGA = models.FileField(upload_to=root_file_storage + 'TGA', null=True, blank=True, validators=[validate_file_extension]) file_XAS = models.FileField(upload_to=root_file_storage + 'XAS', null=True, blank=True, validators=[validate_file_extension]) start_date = models.DateField(null=True, default=datetime.date.today) end_date = models.DateField(null=True, default=datetime.date.today) associated_project = models.ManyToManyField('Project') user = models.ForeignKey(User, blank=True, null=True) comment = models.TextField(blank=True) class Meta: ordering = ['sample_number'] def __str__(self): return "{sample_number} ({formula})".format( sample_number=self.sample_number, formula=self.stripped_formula) #Order By Meta data def detail_url(self): """Return the url for the detailed view of the sample""" url = reverse('sample_detail', kwargs={'id': self.id}) return url def edit_url(self): """Return the url for the edit view opf the sample""" url = reverse('edit_sample', kwargs={'id': self.id}) return url def edit_photo_url(self): """Return the url for the photo edit view of the sample""" url = reverse('edit_sample_photo', kwargs={'id': self.id}) return url def get_absolute_url(self): return reverse('sample_detail', kwargs={'id': self.id}) @property def is_archived(self): projects = Project.objects.all().filter(is_archived=True).values_list( 'id', flat=True) if Sample.objects.all().filter(associated_project__in=projects, id=self.id): return True else: return False
class Customer(models.Model): """ A model for a base customer. Contents everything, related to CRM via properties: * payments: payment history: :model:`history.PaymentEvent` * classes: all purchased classes: :model:`market.Class` * subscriptions: all purchased subscriptions: :model:`market.Subscription` The model automatically assigned to a current user, so you can access all CRM properties via `request.user.crm`. """ LEVELS = [(a + str(i), a + str(i)) for i in range(1, 4) for a in ('A', 'B', 'C')] GREETINGS = ( ('empty', 'A user without a single class, even the trial one'), ('trial', "User has a single trial class and didn't schedule it yet"), ('trial-scheduled', 'User has scheduled his trial class'), ('trial-started', 'Users trial class has started'), ('out-of-classes', 'User has no classes (completed his trial, or purchased some other lessons without a subscription'), ('classes-without-subscription', "User has come classes, but hasn't purchase a subscription"), ('subscription-active', "User is in process of active subscription"), ('subscription-finished', "user's subscription has finished, but he has some non-subscription-lessons"), ) user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='crm') curator = models.ForeignKey('teachers.Teacher', on_delete=models.SET_NULL, null=True, blank=True, related_name='patronized_customers') company = models.ForeignKey(Company, on_delete=models.SET_NULL, null=True, blank=True, related_name='customers') source = models.CharField(max_length=140, default='internal') customer_first_name = models.CharField('First name', max_length=140, blank=True) customer_last_name = models.CharField('Last name', max_length=140, blank=True) customer_email = models.EmailField('Email', blank=True) date_arrived = models.DateTimeField(auto_now_add=True) birthday = models.DateField(null=True, blank=True) timezone = TimeZoneField(default='Europe/Moscow') ref = models.CharField('Referal code', max_length=140, blank=True) cancellation_streak = models.SmallIntegerField('Cancelled lesson streak', default=0) max_cancellation_count = models.SmallIntegerField('Maximum allowed lessons to cancel', default=7) profile_photo = models.ImageField(upload_to='profiles/', null=True, blank=True) profile_photo_cropping = ImageRatioField('profile_photo', '80x80') profession = models.CharField(max_length=140, null=True, blank=True) country = CountryField() native_language = models.CharField(max_length=140, null=True, blank=True) languages = models.ManyToManyField('lessons.Language', blank=True) starting_level = models.CharField(max_length=2, choices=LEVELS, blank=True, null=True) current_level = models.CharField(max_length=2, choices=LEVELS, blank=True, null=True) phone = models.CharField('Phone number', max_length=15, blank=True) skype = models.CharField('Skype login', max_length=140, blank=True) facebook = models.CharField('Facebook profile id', max_length=140, blank=True) twitter = models.CharField('Twitter username', max_length=140, blank=True) instagram = models.CharField('Instagram username', max_length=140, blank=True) linkedin = models.CharField('Linkedin username', max_length=140, blank=True) def get_absolute_url(self): return resolve_url('admin:crm_customer_change', self.pk) @property def full_name(self): return '%s %s' % (self.first_name, self.last_name) @property def email(self): return self.user.email @property def first_name(self): return self.user.first_name @property def last_name(self): return self.user.last_name @classmethod def clean_greeting(cls, status): """ Check if greeting status is allowed, raise ValueError otherwise """ allowed_greetings = OrderedDict(cls.GREETINGS) if allowed_greetings.get(status) is not None: return status else: raise ValueError('Trying to set unexistant greeting') def get_greeting_type(self): # NOQA:C901 """ Get greeting type. For available greeting types see GREETINGS defined in this class """ classes = self.classes.all() if not classes.count(): return self.clean_greeting('empty') if self.is_trial_user(): if self.trial_lesson_is_scheduled(): if self.trial_lesson_has_started(): return self.clean_greeting('trial-started') return self.clean_greeting('trial-scheduled') return self.clean_greeting('trial') if self.can_schedule_classes(): if self.subscriptions.count(): if self.subscriptions.filter(is_fully_used=False): return self.clean_greeting('subscription-active') else: return self.clean_greeting('subscription-finished') else: return self.clean_greeting('classes-without-subscription') return self.clean_greeting('out-of-classes') def get_profile_photo(self): """ Get, if exists, profile photo link """ if self.profile_photo: return cropped_thumbnail(context={}, instance=self, ratiofieldname='profile_photo_cropping') return '' def add_trial_lesson(self): """ Add a free trial lesson to the customer """ TrialLesson = apps.get_model('lessons.TrialLesson') self.classes.create( lesson_type=TrialLesson.get_contenttype() ) trial_lesson_added.send(sender=self) def profile_needs_updating(self): """ Check if we should advise a customer to change his profile """ if len(self.skype) == 0: return True return False def is_trial_user(self): """ Returns true if the only lesson off this user is trial and it is not used. Will return True when the trial lesson is just finished, because it will be marked as finished after an hour. Let it be so. """ if self.classes.count() == 1: TrialLesson = apps.get_model('lessons.TrialLesson') if self.classes.first().lesson_type == TrialLesson.get_contenttype(): if not self.classes.first().is_fully_used: return True return False def trial_lesson_is_scheduled(self): """ Check if trial customer has scheduled his lesson """ if not self.is_trial_user(): return False c = self.classes.first() return c.is_scheduled def trial_lesson_has_started(self): """ Check if trial lesson has started """ if not self.is_trial_user(): return False c = self.classes.first() return c.has_started() def __str__(self): return self.full_name def can_cancel_classes(self): """ Determine, if user can cancel a particular class. Class here is for future purposes. """ if self.cancellation_streak < self.max_cancellation_count: return True return False def can_schedule_classes(self): """ Determine, if user has purchased classes """ if self.classes.filter(is_fully_used=False).exclude(is_scheduled=True).count(): return True return False class Meta: verbose_name = 'Profile'
class Competition(models.Model): title = models.CharField(max_length=100) subtitle = models.CharField(max_length=100, blank=True, null=True) # basic info hold_time = models.DateTimeField() holder = models.CharField(max_length=100) state = models.CharField(max_length=100) # admin info adminUser = models.CharField(max_length=50, blank=True) # text intro = models.TextField(blank=True, null=True) content = models.TextField(blank=True, null=True) method = models.TextField(blank=True, null=True) award = models.TextField(blank=True, null=True) # image image = models.ImageField(upload_to='./Competition/images/', null=True, blank=True) thumb = models.ImageField(upload_to='./Competition/thumbs', blank=True) havethumb = models.BooleanField(default=False) cropping = ImageRatioField('image', '640x480') tag = models.ManyToManyField(Tag, blank=True) likes = models.IntegerField(default=0) views = models.IntegerField(default=0) result = models.FileField(upload_to='./Competition/result/', null=True, blank=True) date_time = models.DateTimeField(auto_now_add=True) adminUser = models.CharField(max_length=30) '''def save(self): super(Competition, self).save() if self.havethumb: return self.havethumb = True # base, ext = os.path.splitext(os.path.basename(self.image.path)) thumb_path = os.path.join( './media/Competition/thumbs/', os.path.basename(self.image.path)) make_thumb(self.image.path, thumb_path) # thumb_path = os.path.join(MEDIA_ROOT, relate_thumb_path) thumb_path = os.path.join( './Competition/thumbs/', os.path.basename(self.image.path)) self.thumb = ImageFieldFile(self, self.thumb, thumb_path) super(Competition, self).save()''' '''def update(self): super(Competition, self).update() # base, ext = os.path.splitext(os.path.basename(self.image.path)) thumb_path = os.path.join( './media/Competition/thumbs/', os.path.basename(self.image.path)) make_thumb(self.image.path, thumb_path) # thumb_path = os.path.join(MEDIA_ROOT, relate_thumb_path) thumb_path = os.path.join( './Competition/thumbs/', os.path.basename(self.image.path)) self.thumb = ImageFieldFile(self, self.thumb, thumb_path) super(Competition, self).save()''' def __str__(self): return self.title class Meta: ordering = ['-hold_time']
class Event(models.Model): objects = EventManager() created_at = models.DateTimeField(_('Created At'), auto_now_add=True) updated_at = models.DateTimeField(_('Updated At'), auto_now=True) name = models.CharField(_('Event Name'), max_length=50) abstract = models.TextField(_('Abstract'), max_length=250, help_text=_('Short idea of the event (One or two sentences)')) limit_proposal_date = models.DateField(_('Limit Proposals Date'), help_text=_('Limit date to submit talk proposals')) slug = models.CharField(_('URL'), max_length=20, help_text=_('For example: flisol-caba'), validators=[validate_url]) cname = models.CharField(_('CNAME'), max_length=50, blank=True, null=True, help_text=_('For example: flisol-caba'), validators=[validate_url]) uid = models.UUIDField( default=uuid4, editable=False, unique=True, verbose_name=_('UID'), help_text=_('Unique identifier for the event'), ) registration_code = models.UUIDField( default=uuid4, editable=False, unique=True, verbose_name=_('code'), help_text=_('Code validator for in-place event self-registration'), ) external_url = models.URLField(_('External URL'), blank=True, null=True, default=None, help_text=_('http://www.my-awesome-event.com')) email = models.EmailField(verbose_name=_('Email')) event_information = RichTextField(verbose_name=_('Event Information'), help_text=_('Event Information HTML'), blank=True, null=True) schedule_confirmed = models.BooleanField(_('Schedule Confirmed'), default=False) use_installations = models.BooleanField(_('Use Installations'), default=True) use_installers = models.BooleanField(_('Use Installers'), default=True) use_collaborators = models.BooleanField(_('Use Collaborators'), default=True) use_proposals = models.BooleanField(_('Use Proposals'), default=True) is_flisol = models.BooleanField(_('Is FLISoL'), default=False) use_schedule = models.BooleanField(_('Use Schedule'), default=True) place = models.TextField(_('Place')) image = ImageCropField(upload_to='images_thumbnails', verbose_name=_('Image'), blank=True, null=True) cropping = ImageRatioField('image', '700x450', size_warning=True, verbose_name=_('Cropping'), free_crop=True, help_text=_('The image must be 700x450 px. You can crop it here.')) @property def location(self): try: place = json.loads(self.place) components = place['address_components'] components = filter( lambda componet: 'political' in componet['types'], components ) components = map( lambda componet: componet['long_name'], components ) return components except json.JSONDecodeError as error: logger.error(error) return [] @property def report(self): event_user = EventUser.objects.get_counts_by_event(self) collaborator = Collaborator.objects.get_counts_by_event(self) organizer = Organizer.objects.get_counts_by_event(self) attendee = Attendee.objects.get_counts_by_event(self) installer = Installer.objects.get_counts_by_event(self) activity = Activity.objects.get_counts_by_event(self) installation = Installation.objects.get_counts_by_event(self) speakers = [] for talk in Activity.objects.filter(event=self, status='2'): speakers.append(talk.speakers_names.split(',')) speakers_count = len(set(itertools.chain.from_iterable(speakers))) return { 'event_user': event_user, 'collaborator': collaborator, 'organizer': organizer, 'attendee': attendee, 'installer': installer, 'activity': activity, 'installation': installation, 'speakers': speakers_count } def get_absolute_url(self): if self.external_url: return self.external_url return '/event/{}/{}/'.format(self.slug, self.uid) def __str__(self): return self.name class Meta(object): ordering = ['name']
class Colaborador(Permalinkable, ComEndereco, models.Model): is_ativo = models.BooleanField(_('Ativo'), default=True) nome = models.CharField('nome', max_length=128) email = models.EmailField('e-mail', max_length=128, default='') fone = models.CharField('fone', max_length=32, default='') fone2 = models.CharField('fone 2', max_length=32, blank=True) fone3 = models.CharField('fone 3', max_length=32, blank=True) fone_detalhe = models.CharField('Operadora', max_length=32, blank=True, default='') fone2_detalhe = models.CharField('Operadora', max_length=32, blank=True, default='') fone3_detalhe = models.CharField('Operadora', max_length=32, blank=True, default='') whatsapp = models.CharField('WhatsApp', max_length=32, blank=True, default='') foto = models.ImageField(_('foto'), default='', upload_to='corretor_foto/%Y/%m/%d', blank=True) foto_cropping = ImageRatioField('foto', '296x324') cpf = models.CharField('CPF', max_length=16, default='', blank=True) rg = models.CharField('RG', max_length=16, default='', blank=True) data_nascimento = models.DateField(blank=True, null=True) data_admissao = models.DateField(blank=True, null=True) data_rescisao = models.DateField(blank=True, null=True) banco_ag_cc = models.CharField('Banco, Ag e CC', max_length=128, default='', blank=True) email_particular = models.EmailField('e-mail particular', max_length=128, default='', blank=True) fone_particular = models.CharField('fone particular', max_length=32, default='', blank=True) pode_alterar_imovel = models.BooleanField(default=True) creci = models.CharField('CRECI', max_length=16, default='') comprar_contador = models.BigIntegerField('comprar cont.', default=1) alugar_contador = models.BigIntegerField('alugar cont.', default=1) pausado = models.BooleanField(_('Pausado para atendimento'), default=False) objects = ColaboradorManager() class Meta: ordering = [ '-is_ativo', 'nome', ] verbose_name = 'colaborador' verbose_name_plural = 'colaboradores' def __str__(self): return self.nome def save(self, *args, **kwargs): if not self.id: self.slug = slugify(self.nome) profile = self.userprofile_set.all() if profile: update_roles(profile[0].user, self.pode_alterar_imovel) super(Colaborador, self).save(*args, **kwargs) def get_absolute_url(self): return reverse('core.paineladm.corretor', kwargs={ 'pk': self.id, 'slug': self.slug }) @property def foto_ok(self): return path.exists(self.foto.path) @property def foto_text64(self): return base64.b64encode(self.foto.read())
class Accessory(models.Model): name = models.CharField(max_length=100, verbose_name="Titolo:") code = models.CharField('Codice', max_length=250, null=True, blank=True) category = models.ManyToManyField(Category, null=True, blank=True, verbose_name="Seleziona Categorie") manufacturer = models.ForeignKey(Manufacturer, null=True, blank=True, verbose_name="Marca") designer = models.CharField(max_length=250, null=True, blank=True) ##PRICE price = models.DecimalField('Prezzo', max_digits=10, decimal_places=2, blank=True, null=True) discount = models.IntegerField(blank=True, null=True, verbose_name="sconto percentuale") price_offer = models.DecimalField('Prezzo Scontato', max_digits=10, decimal_places=2, blank=True, null=True) ##MULTIMEDIA image = models.ImageField(blank=True, null=True, upload_to='accessory', verbose_name="Immagine") slider = ImageRatioField('image', '1170x600', verbose_name="Slider") thumb = ImageRatioField('image', '800x578', verbose_name="Miniatura") thumbdue = ImageRatioField('image', '745x558', verbose_name="Miniatura pagina dettaglio") croplibero = ImageRatioField('image', '595x335', free_crop=True, verbose_name="Ritaglio Libero") album = FilerFolderField(null=True, blank=True) ## Composition color = models.ManyToManyField(Color, null=True, blank=True, verbose_name="Seleziona Colori") material = models.ManyToManyField(Material, null=True, blank=True, verbose_name="Seleziona Materiali") ## Data quantity = models.IntegerField(blank=True, null=True, verbose_name="Quantita") size = models.CharField('Misure', max_length=250, null=True, blank=True) width = models.IntegerField(blank=True, null=True, verbose_name="larghezza") lenght = models.IntegerField(blank=True, null=True, verbose_name="lunghezza") depth = models.IntegerField(blank=True, null=True, verbose_name="Profondita") height = models.IntegerField(blank=True, null=True, verbose_name="altezza") volume = models.DecimalField('Volume', max_digits=10, decimal_places=2, blank=True, null=True) models.IntegerField(blank=True, null=True, verbose_name="sconto percentuale") descrizione = models.TextField(null=True, blank=True, verbose_name="Descrizione") ## Delivery prompt_delivery = models.BooleanField('Pronta Consegna', default=False) delivery = models.BooleanField('Consegna 40gg', default=False) tags = TaggableManager(verbose_name="Parole chiave", blank=True) pub_date = models.DateTimeField('date published') active = models.BooleanField('attiva', default=False) slide = models.BooleanField('Mostra in Slide', default=False) promo = models.BooleanField('Mostra in Promo', default=False) def image_img(self): if self.image: return u'<img src="%s" style="width:300px"/>' % self.image.url else: return '(Sin imagen)' image_img.short_description = 'Thumb' image_img.allow_tags = True def __unicode__(self): return self.name class Meta: verbose_name_plural = "Accessori" ordering = ['id']
class ResourceImage(ModifiableModel): TYPES = ( ('main', _('Main photo')), ('ground_plan', _('Ground plan')), ('map', _('Map')), ('other', _('Other')), ) resource = models.ForeignKey('Resource', verbose_name=_('Resource'), db_index=True, related_name='images', on_delete=models.CASCADE) type = models.CharField(max_length=20, verbose_name=_('Type'), choices=TYPES) caption = models.CharField(max_length=100, verbose_name=_('Caption'), null=True, blank=True) # FIXME: name images based on resource, type, and sort_order image = models.ImageField(verbose_name=_('Image'), upload_to='resource_images') image_format = models.CharField(max_length=10) cropping = ImageRatioField('image', '800x800', verbose_name=_('Cropping')) sort_order = models.PositiveSmallIntegerField(verbose_name=_('Sort order')) def save(self, *args, **kwargs): self._process_image() if self.sort_order is None: other_images = self.resource.images.order_by('-sort_order') if not other_images: self.sort_order = 0 else: self.sort_order = other_images[0].sort_order + 1 if self.type == "main": other_main_images = self.resource.images.filter(type="main") if other_main_images.exists(): # Demote other main images to "other". # The other solution would be to raise an error, but that would # lead to a more awkward API experience (having to first patch other # images for the resource, then fix the last one). other_main_images.update(type="other") return super(ResourceImage, self).save(*args, **kwargs) def full_clean(self, exclude=(), validate_unique=True): if "image" not in exclude: self._process_image() return super(ResourceImage, self).full_clean(exclude, validate_unique) def _process_image(self): """ Preprocess the uploaded image file, if required. This may transcode the image to a JPEG or PNG if it's not either to begin with. :raises InvalidImage: Exception raised if the uploaded file is not valid. """ if not self.image: # No image set - we can't do this right now return if self.image_format: # Assume that if image_format is set, no further processing is required return try: img = Image.open(self.image) img.load() except Exception as exc: raise InvalidImage("Image %s not valid (%s)" % (self.image, exc)) from exc if img.format not in ("JPEG", "PNG"): # Needs transcoding. if self.type in ("map", "ground_plan"): target_format = "PNG" save_kwargs = {} else: target_format = "JPEG" save_kwargs = {"quality": 75, "progressive": True} image_bio = BytesIO() img.save(image_bio, format=target_format, **save_kwargs) self.image = ContentFile( image_bio.getvalue(), name=os.path.splitext(self.image.name)[0] + ".%s" % target_format.lower()) self.image_format = target_format else: # All good -- keep the file as-is. self.image_format = img.format def get_full_url(self): base_url = getattr(settings, 'RESPA_IMAGE_BASE_URL', None) if not base_url: return None return base_url.rstrip('/') + reverse('resource-image-view', args=[str(self.id)]) def __str__(self): return "%s image for %s" % (self.get_type_display(), str( self.resource)) class Meta: verbose_name = _('resource image') verbose_name_plural = _('resource images') unique_together = (('resource', 'sort_order'), )
class Composition(models.Model): product = models.ForeignKey(Product, null=True, blank=True, verbose_name="Prodotto") name = models.CharField(max_length=100, verbose_name="Titolo:", null=True, editable=False) name_uk = models.CharField(max_length=100, verbose_name="Titolo Inglese:", null=True, editable=False) name_fr = models.CharField(max_length=100, verbose_name="Titolo Francese:", null=True, editable=False) code = models.CharField('Codice', max_length=250, null=True, blank=True, editable=False) price = models.DecimalField('Prezzo', max_digits=10, decimal_places=2, blank=True, null=True, default=0, help_text="maggiorazione di prezzo") image = models.ImageField(blank=True, null=True, upload_to='product', verbose_name="Immagine") slider = ImageRatioField('image', '1170x600', verbose_name="Slider") thumb = ImageRatioField('image', '800x578', verbose_name="Miniatura") thumbdue = ImageRatioField('image', '745x558', verbose_name="Miniatura pagina dettaglio") croplibero = ImageRatioField('image', '595x335', free_crop=True, verbose_name="Ritaglio Libero") color = models.ForeignKey(Color, null=True, blank=True, verbose_name="Colori") material = models.ForeignKey(Material, null=True, blank=True, verbose_name="Metallo", editable=False) scarpemisura = models.ForeignKey(TagliaScarpe, null=True, blank=True, verbose_name="Taglia Scarpe", help_text="lascia vuoto se non e scarpa") cintureLunghezza = models.ForeignKey( CintureLunghezza, null=True, blank=True, verbose_name="Lunghezza Cinture", help_text="lascia vuoto se non e cintura") ## Data quantity = models.IntegerField(blank=True, null=True, verbose_name="quantita") pub_date = models.DateTimeField('date published', editable=False) active = models.BooleanField('attiva', default=False) def image_img(self): if self.image: return u'<img src="%s" style="width:300px"/>' % self.image.url else: return '(Sin imagen)' image_img.short_description = 'Thumb' image_img.allow_tags = True def save(self, *args, **kwargs): self.name = self.product.name + " - " + self.color.name self.name_uk = self.product.name_uk + " - " + self.color.name_uk self.name_fr = self.product.name_fr + " - " + self.color.name_fr self.code = self.product.id + self.color.id self.pub_date = datetime.now() super(Composition, self).save(*args, **kwargs) # Call the "real" save() method. def __unicode__(self): return self.name class Meta: verbose_name_plural = "Composizioni" ordering = ['id']
class News(NameSlugMixin, SEOTagsMixin, models.Model): audio_converted = models.BooleanField(verbose_name=_(u'аудио?'), default=False) create = models.DateField(verbose_name=u'дата создания', auto_now_add=True) name = models.CharField(verbose_name=_(u'заголовок'), max_length=150) publication = models.CharField(verbose_name=_(u'Название журнала'), max_length=150, default=False) issue = models.ForeignKey(Issue, verbose_name=_(u'печатное издание'), blank=True, default=False, null=True, on_delete=models.CASCADE) short_text = models.TextField(verbose_name=_(u'короткое описание'), blank=True, null=True) text = models.TextField(verbose_name=_(u'начало статьи')) text_continue = models.TextField(verbose_name=_(u'продолжение'), blank=True, null=True) image = models.ImageField(verbose_name=_(u'изображение ландшафт'), upload_to='news/cover/%Y/%m/%d/') image_portret = models.ImageField(verbose_name=_(u'изображение портрет'), upload_to='news/cover/%Y/%m/%d/') url = models.URLField(verbose_name=u'ссылка на ридер') cropping = ImageRatioField('image', '480x270') cropping_portret = ImageRatioField('image_portret', '205x282') cropping_square = ImageRatioField('image_portret', '80x80') is_publish = models.BooleanField(verbose_name=_(u'Опубликован?'), default=False) author = models.CharField(verbose_name=_(u'Автор'), max_length=250, blank=True, null=True) # rating = Ratings() tags = TaggableManager(blank=True) sorting = models.IntegerField(verbose_name=_(u'Сортировка'), default=0) @property def publication_name(self): #return self.issue.journal+' '+_('выпуск')+' '+self.issue return self.issue.journal.name_ru + u' № ' + self.issue.name def get_absolute_url(self): #return '/top10/detail/%s-%s' % (self.name_slug,self.id) return reverse("text-reader-announce", kwargs={ "issue_id": self.issue.pk, "article_id": self.pk }) def __unicode__(self): return self.name @property def image_url(self): try: return f'{settings.BACKEND_URL}{self.image.url}' except Exception as e: print(e) return 'None' @property def thumbnailsmall_url_square(self): try: return get_thumbnailer(self.image_portret).get_thumbnail({ 'size': (80, 80), 'box': self.cropping_square, 'crop': True, 'detail': True, }).url except: return '' @property def thumbnailsmall_url_portrait(self): try: return get_thumbnailer(self.image_portret).get_thumbnail({ 'size': (205, 282), 'box': self.cropping_portret, 'crop': True, 'detail': True, }).url except: return '' @property def thumbnailsmall_url(self): try: return get_thumbnailer(self.image).get_thumbnail({ 'size': (200, 100), 'box': self.cropping, 'crop': True, 'detail': True, }).url except: return '' @property def thumbnailmiddle_url(self): try: return get_thumbnailer(self.image).get_thumbnail({ 'size': (480, 270), 'box': self.cropping, 'crop': True, 'detail': True, }).url except: return '' def thumbnailsmall(self): return mark_safe( u'<img align="left" style="padding-right: 10px" src="%s" title="%s"/>' % (self.thumbnailsmall_url, self.name)) def thumbnail(self): try: thumbnail_url = get_thumbnailer(self.image).get_thumbnail({ 'size': (480, 270), 'box': self.cropping, 'crop': True, 'detail': True, }).url return mark_safe(u'<img src="%s" title="%s"/>' % (thumbnail_url, self.name)) except: return '' def thumbnailbig(self): try: thumbnail_url = get_thumbnailer(self.image).get_thumbnail({ 'size': (480, 270), 'box': self.cropping, 'crop': True, 'detail': True, }).url return mark_safe( u'<img align="right" style="padding: 0 0 0 15px" src="%s" title="%s"/>' % (thumbnail_url, self.name)) except: return '' class Meta: verbose_name = _(u'обзор') verbose_name_plural = _(u'Обзор прессы')
class CasaLegislativa(models.Model): """ Modelo para representar uma Casa Legislativa """ INCLUSAO_DIGITAL_CHOICES = ( ('NAO PESQUISADO', u'Não pesquisado'), ('NAO POSSUI PORTAL', u'Não possui portal'), ('PORTAL MODELO', u'Possui Portal Modelo'), ('OUTRO PORTAL', u'Possui outro portal'), ) nome = models.CharField( max_length=60, help_text='Exemplo: <em>Câmara Municipal de Pains</em>.') # Guarda um campo para ser usado em buscas em caixa baixa e sem acento search_text = SearchField(field_names=['nome']) # search_text.projeto_filter = True tipo = models.ForeignKey(TipoCasaLegislativa, verbose_name="Tipo") cnpj = models.CharField('CNPJ', max_length=32, blank=True) observacoes = models.TextField(u'observações', blank=True) # num_parlamentares = models.PositiveIntegerField('Número de parlamentares') codigo_interlegis = models.CharField('Código Interlegis', max_length=3, blank=True) # codigo_interlegis.ts_filter = True gerente_contas = models.ForeignKey(Servidor, verbose_name="Gerente de contas", null=True, blank=True, related_name='casas_que_gerencia') # Informações de contato logradouro = models.CharField( max_length=100, help_text='Avenida, rua, praça, jardim, parque...') bairro = models.CharField(max_length=100, blank=True) municipio = models.ForeignKey('contatos.Municipio', verbose_name='município') # municipio.uf_filter = True cep = models.CharField(max_length=32) email = models.EmailField('e-mail', max_length=128, blank=True) pagina_web = models.URLField( u'página web', help_text='Exemplo: <em>http://www.camarapains.mg.gov.br</em>.', blank=True, ) inclusao_digital = models.CharField(max_length=30, choices=INCLUSAO_DIGITAL_CHOICES, default=INCLUSAO_DIGITAL_CHOICES[0][0]) data_levantamento = models.DateTimeField(u"Data/hora da pesquisa", null=True, blank=True) pesquisador = models.ForeignKey(Servidor, verbose_name=u"Pesquisador", null=True, blank=True) obs_pesquisa = models.TextField(u"Observações do pesquisador", blank=True) ult_alt_endereco = models.DateTimeField(u'Última alteração do endereço', null=True, blank=True, editable=True) telefones = generic.GenericRelation('contatos.Telefone') foto = models.ImageField(upload_to='imagens/casas', width_field='foto_largura', height_field='foto_altura', blank=True) recorte = ImageRatioField( 'foto', '400x300', verbose_name="Recorte", ) foto_largura = models.SmallIntegerField(editable=False, null=True) foto_altura = models.SmallIntegerField(editable=False, null=True) data_instalacao = models.DateField( u'Data de instalação da Casa Legislativa', null=True, blank=True) class Meta: ordering = ('nome', ) unique_together = ('municipio', 'tipo') verbose_name = 'Casa Legislativa' verbose_name_plural = 'Casas Legislativas' @property def num_parlamentares(self): if not self.legislatura_set.exists(): return 0 return self.legislatura_set.latest('data_inicio').total_parlamentares @property def telefone(self): """ Link para acessar diretamente o primeiro telefone cadastrado da casa Util para relatorios antigos """ telefones = self.telefones.all() if telefones: return telefones[0] return None @property def presidente(self): """ Link para acessar diretamente o contato do presidente da casa Util para relatorios antigos """ try: if self.funcionario_set.filter(setor='presidente').count() > 1: return self.funcionario_set.filter(setor='presidente')[0] else: return self.funcionario_set.get(setor='presidente') except Funcionario.DoesNotExist: return None @property def total_parlamentares(self): """ Calcula o total de parlamentares atual da Casa: - O total de parlamentares da legislatura mais recente, ou - num_parlamentares ou - 0 se não tiver nenhuma das informações """ if self.legislatura_set.exists(): return self.legislatura_set.all()[0].total_parlamentares if self.num_parlamentares is not None: return self.num_parlamentares return 0 def gerarCodigoInterlegis(self): codigo = self.codigo_interlegis if codigo == '': if self.tipo.sigla == 'AL': # Assembléias são tratadas a parte codigo = 'A' + self.municipio.uf.sigla if CasaLegislativa.objects.filter( codigo_interlegis=codigo).count() <= 0: # Só grava o código se ele for inédito self.codigo_interlegis = codigo self.save() return codigo # Se já existe, então trata a Assembleia como uma Casa qualquer. cityName = normalize('NFKD', unicode(self.municipio.nome)).encode( 'ascii', 'ignore') cityName = cityName.upper().strip() cityName = cityName.replace(' DA ', ' ') cityName = cityName.replace(' DE ', ' ') cityName = cityName.replace(' DO ', ' ') cityName = filter(lambda x: x in ascii_uppercase + ' ', cityName) # estratégia 1 - Pegar as 1ª letra de cada nome da cidade codigo = ''.join([x[0] for x in cityName.split(' ')[:3]]) # Se o código ficou com menos que três letras, pegar as 2 primeiras if len(codigo) < 3: codigo = ''.join([x[0:2] for x in cityName.split(' ')[:3]])[:3] # Se ainda ficou com menos de três letras, então o nome da cidade só # tem uma palavra. Pegue as três primeiras letras da palavra if len(codigo) < 3: codigo = cityName[:3] # Se o código já existir, substituir a última letra do código pela # última letra do nome da cidade, e ir recuando, letra a letra, # até achar um novo código. cityName = cityName.replace(' ', '') ultima = len(cityName) while CasaLegislativa.objects.filter(codigo_interlegis=codigo). \ count() > 0 and ultima > 0: codigo = codigo[:2] + cityName[ultima - 1:ultima] ultima -= 1 # Se usou todas as letras do nome na última posição e ainda assim # não gerou um código único, então vamos compor o nome usando as # três primeiras consoantes. if CasaLegislativa.objects.filter( codigo_interlegis=codigo).count() > 0: codigo_cons = cityName.replace('A', '').replace('E', '').\ replace('I', '').replace('O', '').replace('U', '')[:3] if len(codigo_cons) == 3 and \ CasaLegislativa.objects.filter(codigo_interlegis=codigo).count() > 0: codigo = codigo_cons # Se ainda não gerou um nome único, vamos colocar dígitos no # último caractere, de A a Z i = 'A' while CasaLegislativa.objects.filter(codigo_interlegis=codigo). \ count() > 0 and i <= 'Z': codigo = codigo[:2] + str(i) i = chr(ord(i) + 1) # Se não encontrou, comece a gerar strings com 3 letras aleatórias # tiradas do nome da cidade, até gerar uma que não existe. Tentar # 100 vezes apenas i = 0 while CasaLegislativa.objects.filter(codigo_interlegis=codigo). \ count() > 0 and i < 100: codigo = random.choice(cityName) + random.choice(cityName) + \ random.choice(cityName) i += 1 # Caramba! Só resta então gerar o código com 3 letras aleatórias # quaisquer do alfabeto! i = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' while CasaLegislativa.objects.filter(codigo_interlegis=codigo). \ count() > 0: codigo = random.choice(i) + random.choice(i) + \ random.choice(i) self.codigo_interlegis = codigo self.save() return codigo def __unicode__(self): return self.nome def save(self, *args, **kwargs): address_changed = False if self.pk is not None: original = CasaLegislativa.objects.get(pk=self.pk) if (self.logradouro != original.logradouro or self.bairro != original.bairro or self.municipio != original.municipio or self.cep != original.cep): address_changed = True else: address_changed = True if address_changed: self.ult_alt_endereco = datetime.now() return super(CasaLegislativa, self).save(*args, **kwargs)
class AboutUs(models.Model): text1 = models.TextField('First text', max_length=2000, null=True, blank=True) text2 = models.TextField('Second text', max_length=2000, null=True, blank=True) image = models.ImageField('Image', upload_to='media/', null=True, blank=True) cropping = ImageRatioField('image', '669x300')