Example #1
0
class ISModel(models.Model):
    related_things = RelatedSetField(ISOther)
    related_list = RelatedListField(ISOther, related_name="ismodel_list")
    limted_related = RelatedSetField(RelationWithoutReverse, limit_choices_to={'name': 'banana'}, related_name="+")
    children = RelatedSetField("self", related_name="+")

    class Meta:
        app_label = "djangae"
Example #2
0
class ISStringReferenceModel(models.Model):
    related_things = RelatedSetField('ISOther')
    related_list = RelatedListField('ISOther', related_name="ismodel_list_string")
    limted_related = RelatedSetField('RelationWithoutReverse', limit_choices_to={'name': 'banana'}, related_name="+")
    children = RelatedSetField("self", related_name="+")

    class Meta:
        app_label = "djangae"
Example #3
0
class User(BaseModel
           ):  # TODO: subclass Django/Djangae user base model, or something
    """ A public user who is registered on the site. """

    constituency = CharField(choices=CONSTITUENCIES.choices)
    # The MP can be calculated from constituency, but shortcut field for speed and convenience:
    mp = models.ForeignKey(MP, related_name="constituents")
    follows_mps = RelatedSetField(
        MP,
        help_text=
        "MPs which this user wants to get/see info/updates/notifications about",
        blank=True,
        related_name="followers",
    )
    follows_keywords = SetField(
        CharField(),
        help_text=
        "Keywords which this user wants to know about when an MP says them",
        blank=True,
    )

    def save(self, *args, **kwargs):
        # Make the user follow their own MP.  # TODO: maybe don't be so forceful!
        self.follows_mps_ids.add(self.mp_id)
        return super(User, self).save(*args, **kwargs)
Example #4
0
class Video(ThumbnailAbstract):
    """A video"""
    subscription = models.ForeignKey(Subscription)
    user = models.ForeignKey(settings.AUTH_USER_MODEL)
    viewed = models.BooleanField(default=False)
    buckets = RelatedSetField(Bucket)

    # from video endpoint
    youtube_id = models.CharField(max_length=200)  # id
    published_at = models.DateTimeField()

    # calculate id based on user ID + video ID so we can get by keys later
    id = ComputedCharField(
        lambda self: create_composite_key(str(self.user_id), self.youtube_id),
        primary_key=True,
        max_length=200)
    ordering_key = ComputedCharField(lambda self: create_composite_key(
        self.published_at.isoformat(" "), self.youtube_id),
                                     max_length=200)

    objects = VideoQuerySet.as_manager()

    class Meta:
        ordering = ["ordering_key"]

    @property
    def html_snippet(self):
        tmpl = get_template("subscribae/includes/videos.html")
        return tmpl.render({"video": self})

    def add_titles(self):
        """Fetches titles and descriptions for Video"""
        from subscribae.utils import video_add_titles
        return list(video_add_titles([self]))[0]
Example #5
0
class UniqueAction(models.Model):
    action_type = models.CharField(choices=ACTION_TYPES, max_length=100)
    model = models.CharField(max_length=100)
    status = models.CharField(choices=ACTION_STATUSES,
                              default=ACTION_STATUSES[0][0],
                              editable=False,
                              max_length=100)
    logs = RelatedSetField(ActionLog, editable=False)
Example #6
0
class Ticket(TimeStampedModel):
    title = models.CharField(max_length=200)
    description = models.TextField(blank=True)
    project = models.ForeignKey(Project, related_name="tickets")
    created_by = models.ForeignKey(settings.AUTH_USER_MODEL,
                                   null=True,
                                   related_name="created_tickets")
    assignees = RelatedSetField(settings.AUTH_USER_MODEL,
                                related_name="tickets")

    def __str__(self):
        return self.title
Example #7
0
class Bucket(UniquenessMixin, models.Model):
    """A "bucket" that a user can put a subscription in

    A subscription can be in more than one bucket
    """
    subs = RelatedSetField(Subscription)
    user = models.ForeignKey(settings.AUTH_USER_MODEL)
    title = models.CharField(max_length=100)
    last_update = models.DateTimeField()
    last_viewed = models.DateTimeField(null=True, blank=True)
    last_watched_video = models.CharField(max_length=200)

    class Meta:
        unique_together = ["user", "title"]
        ordering = ["title"]

    @property
    def latest_videos(self):
        qs = self.video_set.all()
        if self.last_watched_video:
            qs = qs.filter(ordering_key__gt=self.last_watched_video)

        return qs
Example #8
0
class Ticket(TimeStampedModel):
    SHORT_DESCRIPTION_MAX_LENGTH = 200

    title = models.CharField(max_length=200)
    description = models.TextField(blank=True)
    project = models.ForeignKey(Project, related_name="tickets")
    created_by = models.ForeignKey(settings.AUTH_USER_MODEL,
                                   null=True,
                                   related_name="created_tickets")
    assignees = RelatedSetField(settings.AUTH_USER_MODEL,
                                related_name="tickets")

    def __str__(self):
        return self.title

    @property
    def short_description(self):
        """A shorterned version of description."""
        trunc = '...'
        real_max_length = self.SHORT_DESCRIPTION_MAX_LENGTH - len(trunc)
        if len(self.description) < real_max_length:
            return self.description

        return self.description[0:real_max_length] + trunc
Example #9
0
class PermissionsMixin(models.Model):
    """
    A mixin class that adds the fields and methods necessary to support
    Django's Group and Permission model using the ModelBackend.
    """
    is_superuser = models.BooleanField(
        _('superuser status'),
        default=False,
        help_text=_('Designates that this user has all permissions without '
                    'explicitly assigning them.'))

    groups = RelatedSetField(
        Group,
        verbose_name=_('groups'),
        blank=True,
        help_text=_('The groups this user belongs to. A user will '
                    'get all permissions granted to each of '
                    'his/her group.'))

    user_permissions = ListField(
        models.CharField(max_length=500),
        verbose_name=_('user permissions'),
        blank=True,
        help_text='Specific permissions for this user.')

    class Meta:
        abstract = True

    def __init__(self, *args, **kwargs):
        """We need to override this to make the choices lazy and prevent import madness"""
        super(PermissionsMixin, self).__init__(*args, **kwargs)
        self._meta.get_field('user_permissions')._choices = lazy(
            get_permission_choices, list)()

    def get_group_permissions(self, obj=None):
        """
        Returns a list of permission strings that this user has through his/her
        groups. This method queries all available auth backends. If an object
        is passed in, only permissions matching this object are returned.
        """
        permissions = set()
        for backend in auth.get_backends():
            if hasattr(backend, "get_group_permissions"):
                if obj is not None:
                    permissions.update(backend.get_group_permissions(
                        self, obj))
                else:
                    permissions.update(backend.get_group_permissions(self))
        return permissions

    def get_all_permissions(self, obj=None):
        return _user_get_all_permissions(self, obj)

    def has_perm(self, perm, obj=None):
        """
        Returns True if the user has the specified permission. This method
        queries all available auth backends, but returns immediately if any
        backend returns True. Thus, a user who has permission from a single
        auth backend is assumed to have permission in general. If an object is
        provided, permissions for this specific object are checked.
        """

        # Active superusers have all permissions.
        if self.is_active and self.is_superuser:
            return True

        # Otherwise we need to check the backends.
        return _user_has_perm(self, perm, obj)

    def has_perms(self, perm_list, obj=None):
        """
        Returns True if the user has each of the specified permissions. If
        object is passed, it checks if the user has all required perms for this
        object.
        """
        for perm in perm_list:
            if not self.has_perm(perm, obj):
                return False
        return True

    def has_module_perms(self, app_label):
        """
        Returns True if the user has any permissions in the given app label.
        Uses pretty much the same logic as has_perm, above.
        """
        # Active superusers have all permissions.
        if self.is_active and self.is_superuser:
            return True

        return _user_has_module_perms(self, app_label)
Example #10
0
class MasterTranslation(models.Model):
    id = models.CharField(max_length=64, primary_key=True)

    text = models.TextField()
    text_for_ordering = ComputedCharField(lambda instance: instance.text[:500], max_length=500)

    plural_text = models.TextField(blank=True)
    hint = models.CharField(max_length=500, default="", blank=True)

    language_code = models.CharField(
        max_length=8,
        choices=settings.LANGUAGES,
        default=settings.LANGUAGE_CODE
    )

    translations_by_language_code = JSONField()
    translations = RelatedSetField(Translation)
    translated_into_languages = SetField(models.CharField(max_length=8), editable=False)

    # Was this master translation updated or created by make messages?
    used_in_code_or_templates = models.BooleanField(default=False, blank=True, editable=False)

    # Were any groups specified in the trans tags?
    used_by_groups_in_code_or_templates = SetField(models.CharField(max_length=64), blank=True)

    # Record the ID of the last scan which updated this instance (if any)
    last_updated_by_scan_uuid = models.CharField(max_length=64, blank=True, default="")

    first_letter = models.CharField(max_length=1, editable=False)

    @property
    def is_plural(self):
        return bool(self.plural_text)

    def __unicode__(self):
        return u"{} ({}{})".format(self.text, self.language_code, ' plural' if self.is_plural else '')

    def __repr__(self):
        """
        Define an ASCII string safe representation of the master translation.
        """
        return str("{}".format(self.id))

    def get_display(self):
        from fluent.trans import _get_trans
        result = _get_trans(self.text, self.hint)
        return result

    def text_for_language_code(self, lang_code):
        new_code = find_closest_supported_language(lang_code)
        if new_code not in self.translations_by_language_code.keys():
            # we don't have a translation for this language
            return self.text

        translation_id = self.translations_by_language_code[new_code]
        translation = Translation.objects.get(id=translation_id)

        return translation.text

    @classmethod
    def find_by_groups(cls, groups):
        from .fields import find_installed_translatable_fields
        translatable_fields_by_model = find_installed_translatable_fields(with_groups=groups)

        # Go through all Translatable(Char|Text)Fields or TextFields marked with the specified group and get
        # all the master translation IDs which are set to them
        master_translation_ids = []
        for model, fields in translatable_fields_by_model.items():
            master_translation_ids.extend(chain(*model.objects.values_list(*[field.attname for field in fields])))
            master_translation_ids = list(set(master_translation_ids))

        # Now get all the master translations with a group specified in the templates
        master_translation_ids.extend(
            list(MasterTranslation.objects.filter(used_by_groups_in_code_or_templates__overlap=groups)
                 .values_list("pk", flat=True))
        )

        # Make sure master translation ids don't include None values or duplicates
        master_translation_ids = set(master_translation_ids)
        master_translation_ids = master_translation_ids - {None}
        # Return them all!
        return MasterTranslation.objects.filter(pk__in=master_translation_ids)

    @classmethod
    def find_by_group(cls, group_name):
        return cls.find_by_groups([group_name])

    @staticmethod
    def generate_key(text, hint, language_code):
        assert text
        assert hint is not None
        assert language_code

        result = md5()
        for x in (text.encode("utf-8"), hint.encode("utf-8"), language_code):
            result.update(x)
        return result.hexdigest()

    def save(self, *args, **kwargs):
        assert self.text
        assert self.language_code

        # Always store the first letter for querying
        self.first_letter = self.text.strip()[:1]

        # Generate the appropriate key on creation
        if self._state.adding:
            self.pk = MasterTranslation.generate_key(
                self.text, self.hint, self.language_code
            )

        # If we are adding for the first time, then create a counterpart
        # translation for the master language.

        # Note that this Translation will be complete and correct only for the languages that
        # only require 2 plural forms - for others this language needs to be explicitly translated
        # or updated later.
        if self._state.adding:
            with transaction.atomic(xg=True):

                singular_form = get_plural_index(self.language_code, 1)
                plural_form = get_plural_index(self.language_code, 2)

                plurals = {singular_form: self.text}
                if self.is_plural:
                    plurals[plural_form] = self.plural_text

                # if len(LANGUAGE_LOOKUPS[self.language_code].plurals_needed) > len(plurals):
                # FIXME: We can detect that we're dealing with a language that needs more plurals
                # What should we do? mark the translation as incomplete?
                # Don't create the translation object at all?
                new_trans = Translation.objects.create(
                    master_translation=self,
                    language_code=self.language_code,
                    plural_texts=plurals,
                    denorm_master_text=self.text,
                    denorm_master_hint=self.hint
                )
                self.translations_by_language_code[self.language_code] = new_trans.pk
                self.translations.add(new_trans)

                self.translated_into_languages = set(self.translations_by_language_code.keys())
                return super(MasterTranslation, self).save(*args, **kwargs)
        else:
            # Otherwise just do a normal save
            self.translated_into_languages = set(self.translations_by_language_code.keys())
            return super(MasterTranslation, self).save(*args, **kwargs)

    def create_or_update_translation(self, language_code, singular_text=None, plural_texts=None, validate=False):

        if language_code not in dict(settings.LANGUAGES).keys():
            return ["'{}' is not included as a language in your settings file".format(language_code)]

        with transaction.atomic(xg=True):
            trans = None
            if language_code in self.translations_by_language_code:
                # We already have a translation for this language, update it!
                try:
                    trans = Translation.objects.get(pk=self.translations_by_language_code[language_code])
                    created = False
                except Translation.DoesNotExist:
                    trans = None

            if not trans:
                # OK, create the translation object and add it to the respective fields
                trans = Translation(
                    master_translation_id=self.pk,
                    language_code=language_code,
                    denorm_master_hint=self.hint,
                    denorm_master_text=self.text
                )
                created = True

            if plural_texts:
                trans.plural_texts = plural_texts
            else:
                trans.text = singular_text

            if validate:
                errors = validate_translation_texts(trans, self)
                if errors:
                    return errors

            trans.master_translation = self
            trans.save()

            if created:
                self.refresh_from_db()
                self.translations_by_language_code[language_code] = trans.pk
                self.translations.add(trans)
                self.save()

    class Meta:
        app_label = "fluent"
Example #11
0
class Post(models.Model):
    content = models.TextField()
    tags = RelatedSetField('Tag', related_name='posts')
    ordered_tags = RelatedListField('Tag')
Example #12
0
class Post(BaseModel):
    class Meta:
        ordering = ("-created", )

    subtitle = models.CharField(
        verbose_name="Subtitle",
        max_length=100,
    )
    text = RichTextField()
    image = models.ImageField(
        upload_to="post_images",
        validators=[ImageSize(min_w=1900, max_w=1900, min_h=100, max_h=500)],
        help_text="Must be 1900px X 100-500px",
        blank=True)
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)
    tags = RelatedSetField(Tag, related_name="posts", blank=True)

    @models.permalink
    def get_absolute_url(self):
        return ("post", [
            self.slug,
        ])

    @models.permalink
    def get_edit_url(self):
        return ("post-edit", [
            self.slug,
        ])

    @models.permalink
    def get_delete_url(self):
        return ("post-delete", [
            self.slug,
        ])

    def index_text(self):
        """ Text indexed for fulltext search
        """
        elems = [
            self.title,
            self.subtitle,
            self.text,
        ]
        tags = [unicode(t.title) for t in self.tags.all()]
        elems.extend(tags)
        return unicode(" ".join(elems))

    def index_tags(self, sep="\t"):
        """ Returns a string representing all the post tsgs separated by
            the sep val.
            Needed to index the tags as listid in whoosh and have facets
        """
        return unicode(sep.join([t.slug for t in self.tags.all()]))

    def index(self):
        """ Returns a dictionary representing the whoosh entry for
            the current object in the index
        """
        return dict(
            pk=unicode(self.pk),
            text=self.index_text(),
            tags=self.index_tags(),
        )
Example #13
0
class IterableFieldsWithValidatorsModel(models.Model):
    set_field = SetField(models.CharField(max_length=100), min_length=2, max_length=3, blank=False)
    list_field = ListField(models.CharField(max_length=100), min_length=2, max_length=3, blank=False)
    related_set = RelatedSetField(ISOther, min_length=2, max_length=3, blank=False)
    related_list = RelatedListField(ISOther, related_name="iterable_list", min_length=2, max_length=3, blank=False)
Example #14
0
class PFAuthor(models.Model):
    name = models.CharField(max_length=32)
    awards = RelatedSetField('PFAwards')

    class Meta:
        app_label = "djangae"
Example #15
0
class PFPost(models.Model):
    content = models.TextField()
    authors = RelatedSetField('PFAuthor', related_name='posts')

    class Meta:
        app_label = "djangae"