Пример #1
0
class Category(TranslatableModel):
    slug = models.SlugField(_('slug'), max_length=100, unique=True)

    image = ImageField(_("image"),
                       max_length=255,
                       blank=True,
                       null=True,
                       upload_to='categories/',
                       help_text=_("Category image"))
    video = models.FileField(
        _("video"),
        max_length=255,
        blank=True,
        null=True,
        validators=[
            validate_video_file_size,
            FileMimetypeValidator(
                allowed_mimetypes=settings.VIDEO_FILE_ALLOWED_MIME_TYPES)
        ],
        help_text=_('This video will autoplay at the background. '
                    'Allowed types are mp4, ogg, 3gp, avi, mov and webm. '
                    'File should be smaller then 10MB.'),
        upload_to='banner_slides/')
    image_logo = ImageField(_("logo"),
                            max_length=255,
                            blank=True,
                            null=True,
                            upload_to='categories/logos/',
                            help_text=_("Category Logo image"))

    translations = TranslatedFields(title=models.CharField(_("name"),
                                                           max_length=255),
                                    description=models.TextField(
                                        _("description")))

    class Meta(object):
        verbose_name = _("category")
        verbose_name_plural = _("categories")
        # ordering = ['title']
        permissions = (('api_read_category',
                        'Can view categories through API'), )

    def __str__(self):
        return self.title

    def save(self, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)

        super(Category, self).save(**kwargs)

    def get_absolute_url(self):
        return 'https://{}/projects/?category={}'.format(
            properties.tenant.domain_url, self.slug)
Пример #2
0
class PictureItem(ContentItem):
    """
    Picture content item
    """
    class PictureAlignment(DjangoChoices):
        float_left = ChoiceItem('float-left', label=_("Float left"))
        center = ChoiceItem('center', label=_("Center"))
        float_right = ChoiceItem('float-right', label=_("Float right"))

    image = ImageField(
        _("Picture"),
        upload_to='content_images',
        validators=[
            FileMimetypeValidator(
                allowed_mimetypes=settings.IMAGE_ALLOWED_MIME_TYPES, ),
            validate_file_infection
        ])
    align = models.CharField(_("Align"),
                             max_length=50,
                             choices=PictureAlignment.choices)

    class Meta(object):
        verbose_name = _("Picture")
        verbose_name_plural = _("Pictures")

    def __str__(self):
        return self.image.name if self.image else u'(no image)'
Пример #3
0
class Slide(SortableMixin, models.Model):
    block = models.ForeignKey('cms.SlidesContent', related_name='slides')
    tab_text = models.CharField(
        _("Tab text"), max_length=100,
        help_text=_("This is shown on tabs beneath the banner.")
    )
    title = models.CharField(_("Title"), max_length=100, blank=True)
    body = models.TextField(_("Body text"), blank=True)
    image = ImageField(
        _("Image"), max_length=255, blank=True, null=True,
        upload_to='banner_slides/',

        validators=[
            FileMimetypeValidator(
                allowed_mimetypes=settings.IMAGE_ALLOWED_MIME_TYPES,
            ),
            validate_file_infection
        ]
    )
    background_image = ImageField(
        _("Background image"), max_length=255, blank=True,
        null=True, upload_to='banner_slides/',

        validators=[
            FileMimetypeValidator(
                allowed_mimetypes=settings.IMAGE_ALLOWED_MIME_TYPES,
            ),
            validate_file_infection
        ]
    )
    video_url = models.URLField(
        _("Video url"), max_length=100, blank=True, default=''
    )
    link_text = models.CharField(
        _("Link text"), max_length=400,
        help_text=_("This is the text on the button inside the banner."),
        blank=True
    )
    link_url = models.CharField(
        _("Link url"), max_length=400,
        help_text=_("This is the link for the button inside the banner."),
        blank=True
    )
    sequence = models.PositiveIntegerField(default=0, editable=False, db_index=True)

    class Meta:
        ordering = ['sequence']
Пример #4
0
class Quote(models.Model):
    block = models.ForeignKey('cms.QuotesContent', related_name='quotes')
    name = models.CharField(max_length=60)
    quote = models.TextField()
    image = ImageField(_("Image"),
                       max_length=255,
                       blank=True,
                       null=True,
                       upload_to='quote_images/')
Пример #5
0
class Category(models.Model):
    title = models.CharField(_("name"), max_length=255, unique=True)
    slug = models.SlugField(_('slug'), max_length=100, unique=True)
    description = models.TextField(_("description"))
    image = ImageField(_("image"),
                       max_length=255,
                       blank=True,
                       null=True,
                       upload_to='categories/',
                       help_text=_("Category image"))
    image_logo = ImageField(_("logo"),
                            max_length=255,
                            blank=True,
                            null=True,
                            upload_to='categories/logos/',
                            help_text=_("Category Logo image"))

    class Meta:
        ordering = ('title', )
        verbose_name = _("category")
        verbose_name_plural = _("categories")
        ordering = ['title']

    def __unicode__(self):
        return self.title

    def save(self, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)

        super(Category, self).save(**kwargs)

    def get_absolute_url(self):
        return 'https://{}/projects/?category={}'.format(
            properties.tenant.domain_url, self.slug)

    @property
    def projects(self):
        return self.project_set\
            .order_by('-favorite', '-popularity')\
            .filter(status__slug__in=['campaign', 'done-complete', 'done-incomplete', 'voting', 'voting-done'])
Пример #6
0
class BaseFundraiser(models.Model):
    owner = models.ForeignKey('members.Member',
                              verbose_name=_("initiator"),
                              help_text=_("Project owner"))
    project = models.ForeignKey('projects.Project', verbose_name=_("project"))

    title = models.CharField(_("title"), max_length=255)
    description = models.TextField(_("description"), blank=True)
    image = ImageField(_("picture"),
                       max_length=255,
                       blank=True,
                       null=True,
                       upload_to='fundraiser_images/',
                       help_text=_("Minimal of 800px wide"))
    video_url = models.URLField(max_length=100, blank=True, default='')

    amount = MoneyField(_("amount"))
    deadline = models.DateTimeField(null=True)

    created = CreationDateTimeField(
        _("created"), help_text=_("When this fundraiser was created."))
    updated = ModificationDateTimeField(_('updated'))
    deleted = models.DateTimeField(_('deleted'), blank=True, null=True)

    location = models.ForeignKey('geo.Location', null=True, blank=True)

    wallposts = GenericRelation(Wallpost,
                                related_query_name='fundraiser_wallposts')

    def __unicode__(self):
        return self.title

    @property
    def amount_donated(self):
        donations = self.donation_set.filter(order__status__in=[
            StatusDefinition.SUCCESS, StatusDefinition.PENDING,
            StatusDefinition.PLEDGED
        ])

        totals = [
            Money(data['amount__sum'], data['amount_currency'])
            for data in donations.values('amount_currency').annotate(
                Sum('amount')).order_by()
        ]

        totals = [convert(amount, self.amount.currency) for amount in totals]

        return sum(totals) or Money(0, self.amount.currency)

    class Meta():
        abstract = True
        verbose_name = _('fundraiser')
        verbose_name_plural = _('fundraisers')
Пример #7
0
class NewsItem(AnonymizationMixin, PublishableModel):

    title = models.CharField(_("Title"), max_length=200)
    slug = models.SlugField(_("Slug"))

    # Contents
    main_image = ImageField(
        _("Main image"),
        help_text=_("Shows at the top of your post."),
        upload_to='blogs',
        blank=True,
        validators=[
            FileMimetypeValidator(
                allowed_mimetypes=settings.IMAGE_ALLOWED_MIME_TYPES, ),
            validate_file_infection
        ])
    language = models.CharField(_("language"),
                                max_length=5,
                                choices=lazy(get_languages, tuple)())
    contents = PlaceholderField("blog_contents",
                                plugins=[
                                    'TextPlugin', 'ImageTextPlugin',
                                    'OEmbedPlugin', 'RawHtmlPlugin',
                                    'PicturePlugin'
                                ])
    # This should not be necessary, but fixes deletion of some news items
    # See https://github.com/edoburu/django-fluent-contents/issues/19
    contentitem_set = ContentItemRelation()

    allow_comments = models.BooleanField(_("Allow comments"), default=True)

    def __str__(self):
        return self.title

    def get_meta_description(self, **kwargs):
        request = kwargs.get('request')
        s = MLStripper()
        s.feed(mark_safe(render_placeholder(request, self.contents).html))
        return truncatechars(s.get_data(), 250)

    class Meta(object):
        verbose_name = _("news item")
        verbose_name_plural = _("news items")

        permissions = (
            ('api_read_newsitem', 'Can view news items through the API'),
            ('api_add_newsitem', 'Can add news items through the API'),
            ('api_change_newsitem', 'Can change news items through the API'),
            ('api_delete_newsitem', 'Can delete news items through the API'),
        )
Пример #8
0
class Logo(SortableMixin, models.Model):
    block = models.ForeignKey('cms.LogosContent', related_name='logos')
    image = ImageField(_("Image"),
                       max_length=255,
                       blank=True,
                       null=True,
                       upload_to='logo_images/')
    link = models.CharField(max_length=100, blank=True, null=True)
    sequence = models.PositiveIntegerField(default=0,
                                           editable=False,
                                           db_index=True)

    class Meta:
        ordering = ['sequence']
Пример #9
0
class Quote(models.Model):
    block = models.ForeignKey('cms.QuotesContent', related_name='quotes')
    name = models.CharField(max_length=60)
    quote = models.TextField()
    image = ImageField(
        _("Image"), max_length=255, blank=True, null=True,
        upload_to='quote_images/',

        validators=[
            FileMimetypeValidator(
                allowed_mimetypes=settings.IMAGE_ALLOWED_MIME_TYPES,
            ),
            validate_file_infection
        ]
    )
Пример #10
0
class Step(SortableMixin, models.Model):
    block = models.ForeignKey('cms.StepsContent', related_name='steps')
    image = ImageField(_("Image"),
                       max_length=255,
                       blank=True,
                       null=True,
                       upload_to='step_images/')
    header = models.CharField(_("Header"), max_length=100)
    text = models.CharField(_("Text"), max_length=400, null=True, blank=True)
    sequence = models.PositiveIntegerField(default=0,
                                           editable=False,
                                           db_index=True)

    class Meta:
        ordering = ['sequence']
Пример #11
0
class CategoryContent(SortableMixin, TranslatableModel):
    category = models.ForeignKey(Category, related_name='contents')

    translations = TranslatedFields(
        title=models.CharField(_('title'),
                               max_length=60,
                               help_text=_("Max: %(chars)s characters.") %
                               {'chars': 60}),
        description=models.TextField(
            _('description'),
            max_length=190,
            blank=True,
            default='',
            help_text=_("Max: %(chars)s characters.") % {'chars': 190}),
        link_text=models.CharField(
            _("link name"),
            max_length=60,
            blank=True,
            default=_("Read more"),
            help_text=_(
                "The link will only be displayed if an URL is provided. "
                "Max: %(chars)s characters.") % {'chars': 60}),
        link_url=models.CharField(_("link url"), max_length=300, blank=True))

    image = ImageField(_('image'),
                       max_length=255,
                       blank=True,
                       null=True,
                       upload_to='categories/content/',
                       help_text=_("Accepted file format: .jpg, .jpeg & .png"))
    video_url = models.URLField(
        max_length=100,
        blank=True,
        default='',
        help_text=
        _("Setting a video url will replace the image. Only YouTube or Vimeo videos "
          "are accepted. Max: %(chars)s characters.") % {'chars': 100})
    sequence = models.PositiveIntegerField(default=0,
                                           editable=False,
                                           db_index=True)

    class Meta(object):
        verbose_name = _("content block")
        verbose_name_plural = _("content blocks")
        ordering = ['sequence']

    def __str__(self):
        return self.title
Пример #12
0
class Logo(SortableMixin, models.Model):
    block = models.ForeignKey('cms.LogosContent', related_name='logos')
    image = ImageField(
        _("Image"), max_length=255, blank=True, null=True,
        upload_to='logo_images/',

        validators=[
            FileMimetypeValidator(
                allowed_mimetypes=settings.IMAGE_ALLOWED_MIME_TYPES,
            ),
            validate_file_infection
        ]
    )
    link = models.CharField(max_length=100, blank=True, null=True)
    sequence = models.PositiveIntegerField(default=0, editable=False, db_index=True)

    class Meta:
        ordering = ['sequence']
Пример #13
0
class Organization(ValidatedModelMixin, AnonymizationMixin, models.Model):
    """
    Organizations can run Projects. An organization has one or more members.
    """
    name = models.CharField(_('name'), max_length=255)
    slug = models.SlugField(_('slug'), max_length=100)
    description = models.TextField(_('description'), default='', blank=True)

    created = CreationDateTimeField(_('created'))
    updated = ModificationDateTimeField(_('updated'))

    owner = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_('owner'), null=True)

    website = models.URLField(_('website'), blank=True)
    logo = ImageField(
        _('logo'),
        blank=True,
        help_text=_('Partner Organization Logo'),
        max_length=255,
        null=True,
        upload_to='partner_organization_logos/',

        validators=[
            FileMimetypeValidator(
                allowed_mimetypes=settings.IMAGE_ALLOWED_MIME_TYPES,
            ),
            validate_file_infection
        ]
    )

    required_fields = ['name', 'website']

    def __str__(self):
        return self.name

    def save(self, *args, **kwargs):
        self.slug = slugify(self.name)

        super(Organization, self).save(*args, **kwargs)

    class Meta(object):
        ordering = ['name']
        verbose_name = _("partner organization")
        verbose_name_plural = _("partner organizations")
Пример #14
0
class PictureItem(ContentItem):
    """
    Picture content item
    """
    class PictureAlignment(DjangoChoices):
        float_left = ChoiceItem('float-left', label=_("Float left"))
        center = ChoiceItem('center', label=_("Center"))
        float_right = ChoiceItem('float-right', label=_("Float right"))

    image = ImageField(_("Picture"), upload_to='content_images')
    align = models.CharField(_("Align"),
                             max_length=50,
                             choices=PictureAlignment.choices)

    class Meta:
        verbose_name = _("Picture")
        verbose_name_plural = _("Pictures")

    def __unicode__(self):
        return self.image.name if self.image else u'(no image)'
Пример #15
0
class BlueBottleBaseUser(AbstractBaseUser, PermissionsMixin):
    """
    Custom user model for BlueBottle.

    When extending the user model, the serializer should extend too.
    We provide a default base serializer in sync with the base user model
    The Django Meta attribute seems the best place for this configuration, so we
    have to add this.
    """
    class Gender(DjangoChoices):
        male = ChoiceItem('male', label=_('Male'))
        female = ChoiceItem('female', label=_('Female'))

    class UserType(DjangoChoices):
        person = ChoiceItem('person', label=_('Person'))
        company = ChoiceItem('company', label=_('Company'))
        foundation = ChoiceItem('foundation', label=_('Foundation'))
        school = ChoiceItem('school', label=_('School'))
        group = ChoiceItem('group', label=_('Club / association'))

    email = models.EmailField(_('email address'), db_index=True, max_length=254, unique=True)
    username = models.CharField(_('username'), max_length=254, unique=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=False,
                                    help_text=_('Designates whether this user should be treated as active. Unselect '
                                                'this instead of deleting accounts.'))
    disable_token = models.CharField(blank=True, max_length=32, null=True)

    date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
    updated = ModificationDateTimeField()
    last_seen = models.DateTimeField(_('Last Seen'), blank=True, null=True)
    deleted = models.DateTimeField(_('deleted'), blank=True, null=True)

    user_type = models.CharField(_('Member Type'), choices=UserType.choices, default=UserType.person, max_length=25)

    first_name = models.CharField(_('first name'), blank=True, max_length=100)
    last_name = models.CharField(_('last name'), blank=True, max_length=100)
    place = models.CharField(_('Location your at now'), blank=True, max_length=100)
    location = models.ForeignKey('geo.Location', blank=True, help_text=_('Location'),
                                 null=True, on_delete=models.SET_NULL)
    favourite_themes = models.ManyToManyField(ProjectTheme, blank=True)
    skills = models.ManyToManyField('tasks.Skill', blank=True)
    phone_number = models.CharField(_('phone number'), blank=True, max_length=50)
    gender = models.CharField(_('gender'), blank=True, choices=Gender.choices, max_length=6)
    birthdate = models.DateField(_('birthdate'), blank=True, null=True)
    about_me = models.TextField(_('about me'), blank=True, max_length=265)
    # TODO Use generate_picture_filename (or something) for upload_to
    picture = ImageField(_('picture'), blank=True, upload_to='profiles')

    is_co_financer = models.BooleanField(_('Co-financer'),
                                         default=False,
                                         help_text=_('Donations by co-financers are shown in a separate list on the '
                                                     'project page. These donation will always be visible.'))
    can_pledge = models.BooleanField(_('Can pledge'), default=False, help_text=_('User can create a pledge donation.'))

    # Use lazy for the choices and default, so that tenant properties
    # will be correctly loaded
    primary_language = models.CharField(_('primary language'),
                                        choices=lazy(get_language_choices, tuple)(),
                                        default=lazy(get_default_language, str)(),
                                        help_text=_('Language used for website and emails.'),
                                        max_length=5)
    share_time_knowledge = models.BooleanField(_('share time and knowledge'), default=False)
    share_money = models.BooleanField(_('share money'), default=False)
    newsletter = models.BooleanField(_('newsletter'), default=True, help_text=_('Subscribe to newsletter.'))
    campaign_notifications = models.BooleanField(_('Project Notifications'), default=True)

    website = models.URLField(_('website'), blank=True)
    facebook = models.CharField(_('facebook profile'), blank=True, max_length=50)
    twitter = models.CharField(_('twitter profile'), blank=True, max_length=15)
    skypename = models.CharField(_('skype profile'), blank=True, max_length=32)

    partner_organization = models.ForeignKey(
        'organizations.Organization',
        blank=True, null=True,
        help_text=_('Users that are connected to a partner organisation '
                    'will skip the organisation step in initiative create.'),
        related_name='partner_organization_members',
        verbose_name=_('Partner organisation'))

    is_anonymized = models.BooleanField(_('Is anonymized'), default=False)
    welcome_email_is_sent = models.BooleanField(_('Welcome email is sent'), default=False)

    USERNAME_FIELD = 'email'

    slug_field = 'username'

    objects = BlueBottleUserManager()

    class Meta(object):
        abstract = True
        verbose_name = _('member')
        verbose_name_plural = _('members')

        permissions = (
            ('api_read_member', 'Can view members through the API'),
            ('api_read_full_member', 'Can view full members through the API'),
            ('api_add_member', 'Can add members through the API'),
            ('api_change_member', 'Can change members through the API'),
            ('api_delete_member', 'Can delete members through the API'),

            ('api_read_own_member', 'Can view own members through the API'),
            ('api_change_own_member', 'Can change own members through the API'),
            ('api_delete_own_member', 'Can delete own members through the API'),
        )

    def update_deleted_timestamp(self):
        """ Automatically set or unset the deleted timestamp."""
        if not self.is_active and self.deleted is None:
            self.deleted = timezone.now()
        elif self.is_active and self.deleted is not None:
            self.deleted = None

    def generate_username(self):
        """ Generate and set a username if it hasn't already been set. """
        if not self.username:
            username = self.email
            original_username = username
            queryset = self.__class__.objects.all()
            if self.pk:
                queryset = queryset.exclude(pk=self.pk)

            # Increase the number while searching for the next valid slug
            # depending on the given slug, clean-up
            next_num = 2
            while queryset.filter(username=username):
                username = original_username
                end = str(next_num)
                username = '******'.format(username, end)
                next_num += 1

            # Finally set the generated username.
            self.username = username

    def clean(self):
        self.update_deleted_timestamp()
        self.generate_username()

    def get_full_name(self):
        """
        Returns the first_name plus the last_name, with a space in between.
        """
        full_name = u'{0} {1}'.format(self.first_name, self.last_name)
        return full_name.strip()

    def anonymize(self):
        self.is_active = False
        self.is_anonymized = True
        self.email = '{}[email protected]'.format(self.pk)  # disabled emails need to be unique too
        self.username = '******'.format(self.pk)  # disabled emails need to be unique too
        self.remote_id = '{}[email protected]'.format(self.pk)  # disabled emails need to be unique too
        self.set_unusable_password()
        self.first_name = 'Deactivated'
        self.last_name = 'Member'
        self.user_name = ''
        self.picture = ''
        self.avatar = ''
        self.about_me = ''
        self.gender = ''
        self.birthdate = '1000-01-01'
        self.location = None
        self.website = ''
        self.facebook = ''
        self.twitter = ''
        self.skypename = ''
        self.partner_organization = None

        self.save()

    @property
    def full_name(self):
        return self.get_full_name()

    def get_short_name(self):
        """
        The user is identified by their email address.
        """
        return self.first_name

    def email_user(self, subject, message, from_email=None):
        """
        Sends an email to this User with content type HTML.
        """
        # It's possible to send multi-part text / HTML email by following these
        # instructions: https://docs.djangoproject.com/en/1.5/topics/email
        # /#sending-alternative-content-types
        msg = EmailMessage(subject, message, from_email, [self.email])
        msg.content_subtype = 'html'  # Main content is now text/html
        msg.send()

    def get_jwt_token(self):
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER

        payload = jwt_payload_handler(self)
        token = jwt_encode_handler(payload)
        return token

    def get_login_token(self):
        return login_token_generator.make_token(self)

    @property
    def short_name(self):
        return self.get_short_name()

    @cached_property
    def is_initiator(self):
        return bool(self.own_initiatives.count())

    @cached_property
    def is_supporter(self):
        from bluebottle.funding.states import DonationStateMachine
        from bluebottle.funding.models import Donation
        return bool(self.contribution_set.instance_of(Donation).
                    filter(status=DonationStateMachine.succeeded.value).count())

    @cached_property
    def is_volunteer(self):
        from bluebottle.assignments.models import Applicant
        from bluebottle.events.models import Participant
        from bluebottle.activities.states import ActivityStateMachine
        return bool(self.contribution_set.instance_of(Applicant, Participant).
                    filter(status=ActivityStateMachine.succeeded.value).count())

    @cached_property
    def amount_donated(self):
        from bluebottle.funding.states import DonationStateMachine
        from bluebottle.funding.models import Donation
        from bluebottle.funding.utils import calculate_total
        donations = self.contribution_set.instance_of(Donation).filter(
            status=DonationStateMachine.succeeded.value
        )
        return calculate_total(donations)

    @cached_property
    def time_spent(self):
        from bluebottle.assignments.models import Applicant
        from bluebottle.events.models import Participant
        from bluebottle.activities.states import ActivityStateMachine
        contributions = self.contribution_set.instance_of(Applicant, Participant).\
            filter(status=ActivityStateMachine.succeeded.value).all()
        return sum([c.time_spent for c in contributions])

    @cached_property
    def subscribed(self):
        return self.campaign_notifications

    def reset_disable_token(self):
        # Generates a random UUID and converts it to a 32-character
        # hexidecimal string
        token = uuid.uuid4().hex
        self.disable_token = token
        self.save()

    def get_disable_token(self):
        if not self.disable_token:
            self.reset_disable_token()
        return self.disable_token

    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):
        self.generate_username()

        super(BlueBottleBaseUser, self).save(force_insert, force_update, using,
                                             update_fields)

    def __getattr__(self, name):
        # Magically get extra fields
        if name.startswith('extra_'):
            name = name.replace('extra_', '')
            return self.extra.get(field__name=name).value
        return super(BlueBottleBaseUser, self).__getattribute__(name)
Пример #16
0
class Organization(models.Model):
    """
    Organizations can run Projects. An organization has one or more members.
    """
    name = models.CharField(_('name'), max_length=255)
    slug = models.SlugField(_('slug'), max_length=100, unique=True)
    description = models.TextField(_('description'), default='', blank=True)

    created = CreationDateTimeField(_('created'))
    updated = ModificationDateTimeField(_('updated'))
    deleted = models.DateTimeField(_('deleted'), blank=True, null=True)

    partner_organizations = models.TextField(_('partner organizations'),
                                             blank=True)

    # Address
    address_line1 = models.CharField(blank=True, max_length=100)
    address_line2 = models.CharField(blank=True, max_length=100)
    city = models.CharField(blank=True, max_length=100)
    state = models.CharField(blank=True, max_length=100)
    country = models.ForeignKey('geo.Country',
                                blank=True,
                                null=True,
                                related_name='country')
    postal_code = models.CharField(blank=True, max_length=20)

    # Contact
    phone_number = models.CharField(_('phone number'),
                                    blank=True,
                                    max_length=40)
    website = models.URLField(_('website'), blank=True)
    email = models.EmailField(blank=True)
    tags = TaggableManager(blank=True, verbose_name=_('tags'))
    registration = models.FileField(
        blank=True,
        null=True,
        storage=FileSystemStorage(location=settings.PRIVATE_MEDIA_ROOT),
        upload_to='organizations/registrations')

    logo = ImageField(_('logo'),
                      blank=True,
                      help_text=_('Partner Organization Logo'),
                      max_length=255,
                      null=True,
                      upload_to='partner_organization_logos/')

    def save(self, *args, **kwargs):
        if not self.slug:
            original_slug = slugify(self.name)
            slug = original_slug
            next_slug = 2
            while not slug or self.__class__.objects.filter(slug=slug):
                slug = '{0}-{1}'.format(original_slug, next_slug)
                next_slug += 1
            self.slug = slug

        super(Organization, self).save(*args, **kwargs)

    def merge(self, organizations):
        """ Merge `organizations` into the current organization.
        Makes sure that all foreign keys point to `this`.

        Deletes all organization models in `organization` after merging.
        """
        for organization in organizations:
            for member in organization.members.all():
                member.organization = self
                member.save()

            for project in organization.projects.all():
                project.organization = self
                project.save()

            organization.delete()

    def __unicode__(self):
        return self.name

    class Meta:
        ordering = ['name']
        verbose_name = _("partner organization")
        verbose_name_plural = _("partner organizations")
Пример #17
0
class Slide(PublishableModel):
    """
    Slides for homepage
    """
    class SlideStatus(DjangoChoices):
        published = ChoiceItem('published', label=_("Published"))
        draft = ChoiceItem('draft', label=_("Draft"))

    slug = models.SlugField(_("Slug"))
    language = models.CharField(_("language"),
                                max_length=5,
                                choices=lazy(get_languages, tuple)())
    tab_text = models.CharField(
        _("Tab text"),
        max_length=100,
        help_text=_("This is shown on tabs beneath the banner."))

    # Contents
    title = models.CharField(_("Title"), max_length=100, blank=True)
    body = models.TextField(_("Body text"), blank=True)
    image = ImageField(
        _("Image"),
        max_length=255,
        blank=True,
        null=True,
        upload_to='banner_slides/',
        validators=[
            FileMimetypeValidator(
                allowed_mimetypes=settings.IMAGE_ALLOWED_MIME_TYPES, ),
            validate_file_infection
        ])
    background_image = ImageField(
        _("Background image"),
        max_length=255,
        blank=True,
        null=True,
        upload_to='banner_slides/',
        validators=[
            FileMimetypeValidator(
                allowed_mimetypes=settings.IMAGE_ALLOWED_MIME_TYPES, ),
            validate_file_infection
        ])
    video = models.FileField(
        _("Video"),
        max_length=255,
        blank=True,
        null=True,
        validators=[
            validate_video_file_size,
            FileMimetypeValidator(
                allowed_mimetypes=settings.VIDEO_FILE_ALLOWED_MIME_TYPES)
        ],
        help_text=_('This video will autoplay at the background. '
                    'Allowed types are mp4, ogg, 3gp, avi, mov and webm. '
                    'File should be smaller then 10MB.'),
        upload_to='banner_slides/')
    video_url = models.URLField(_("Video url"),
                                max_length=100,
                                blank=True,
                                default='')
    link_text = models.CharField(
        _("Link text"),
        max_length=400,
        blank=True,
        help_text=_("This is the text on the button inside the banner."))
    link_url = models.CharField(
        _("Link url"),
        max_length=400,
        blank=True,
        help_text=_("This is the link for the button inside the banner."))
    style = models.CharField(_("Style"),
                             max_length=40,
                             help_text=_("Styling class name"),
                             default='default',
                             blank=True)

    # Metadata
    sequence = models.IntegerField()

    @property
    def background_image_full_path(self):
        return "{0}{1}".format(settings.MEDIA_URL, str(self.background_image))

    def __str__(self):
        return self.title

    class Meta(object):
        ordering = ('language', 'sequence')
Пример #18
0
class Slide(PublishableModel):
    """
    Slides for homepage
    """
    class SlideStatus(DjangoChoices):
        published = ChoiceItem('published', label=_("Published"))
        draft = ChoiceItem('draft', label=_("Draft"))

    slug = models.SlugField(_("Slug"))
    language = models.CharField(_("language"),
                                max_length=5,
                                choices=lazy(get_languages, tuple)())
    tab_text = models.CharField(
        _("Tab text"),
        max_length=100,
        help_text=_("This is shown on tabs beneath the banner."))

    # Contents
    title = models.CharField(_("Title"), max_length=100, blank=True)
    body = models.TextField(_("Body text"), blank=True)
    image = ImageField(_("Image"),
                       max_length=255,
                       blank=True,
                       null=True,
                       upload_to='banner_slides/')
    background_image = ImageField(_("Background image"),
                                  max_length=255,
                                  blank=True,
                                  null=True,
                                  upload_to='banner_slides/')
    video_url = models.URLField(_("Video url"),
                                max_length=100,
                                blank=True,
                                default='')

    link_text = models.CharField(
        _("Link text"),
        max_length=400,
        help_text=_("This is the text on the button inside the banner."),
        blank=True)
    link_url = models.CharField(
        _("Link url"),
        max_length=400,
        help_text=_("This is the link for the button inside the banner."),
        blank=True)
    style = models.CharField(_("Style"),
                             max_length=40,
                             help_text=_("Styling class name"),
                             default='default',
                             blank=True)

    # Metadata
    sequence = models.IntegerField()

    @property
    def background_image_full_path(self):
        return "{0}{1}".format(settings.MEDIA_URL, str(self.background_image))

    def __unicode__(self):
        return self.title

    class Meta:
        ordering = ('language', 'sequence')