Example #1
0
class GeneLocus(Model):
    """
    Basically a gene as defined by a standard reference, it's location,
    length and other details which are optional.
    """
    STRANDS = (
        (None, 'Undefined'),
        ('+', '+'),
        ('-', '-'),
        ('.', '.'),
    )
    GENE_TYPES = (
        ('P', 'Promoter'),
        ('C', 'Coding'),
        ('I', 'Intergenic'),
        ('R', 'RNA'),
    )

    genome = ForeignKey(Genome,
                        related_name='gene_locuses',
                        null=True,
                        blank=True)
    name = CharField(max_length=255, db_index=True)
    previous_id = CharField(max_length=64,
                            db_index=True,
                            null=True,
                            blank=True)

    start = IntegerField(blank=True, null=True)
    stop = IntegerField(blank=True, null=True)
    length = IntegerField(blank=True, null=True)
    strand = CharField(max_length=5, choices=STRANDS, blank=True, null=True)

    gene_type = CharField(max_length=1,
                          choices=GENE_TYPES,
                          blank=True,
                          null=True,
                          help_text="Basic coding type for the locus.")
    gene_symbol = CharField(max_length=32,
                            blank=True,
                            null=True,
                            help_text="Short identifier used in names")
    description = CharField(max_length=255,
                            blank=True,
                            null=True,
                            help_text="Basic description about the gene.")

    gene_ontology = CharField(
        max_length=255,
        blank=True,
        null=True,
        help_text="Gene ontology or GO-Terms are annotations in the GO format"
        " that describe the gene product in a predictable way.")
    enzyme_commission = CharField(
        max_length=255,
        blank=True,
        null=True,
        help_text="The Enzyme Commission numbers for this gene.")
    pathway_kegg = CharField(max_length=255,
                             blank=True,
                             null=True,
                             help_text="The KEGG based pathways")
    pathway_cyc = CharField(
        max_length=255,
        blank=True,
        null=True,
        help_text="The PWY numbers usually linking to MetaCyc")
    pathway_cog = CharField(
        max_length=255,
        blank=True,
        null=True,
        help_text="Clusters of Orthologous Groups of protein list")
    protein_families = CharField(max_length=255,
                                 blank=True,
                                 null=True,
                                 help_text="Protein families from PFAM")

    objects = GeneLocusManager()

    class Meta:
        ordering = ('name', )
        unique_together = ('genome', 'name')

    def natural_key(self):
        """The genome's short code is a useful key to lookup this table"""
        return (self.genome.code, self.name)

    def __str__(self):
        return self.name
Example #2
0
class CompositionEDTF(Model):
    composition = ParentalKey('CompositionPage',
                              on_delete=CASCADE,
                              unique=True,
                              related_name='date')
    nat_lang_edtf_string = CharField(
        verbose_name='Natural Language Date',
        help_text=('The EDTF date in natural language. This field is help '
                   'users who aren\'t familiar with the EDTF. It does not '
                   'change how the date is represented.'),
        max_length=256)
    edtf_string = CharField(
        verbose_name='EDTF Date',
        help_text=mark_safe(
            'A date in the <a href="https://www.loc.gov/standards/datetime/" '
            'target="_blank"><strong>Extended Date Time Format</strong></a>'),
        max_length=256)
    lower_fuzzy = DateField(editable=False)
    upper_fuzzy = DateField(editable=False)
    lower_strict = DateField(editable=False)
    upper_strict = DateField(editable=False)
    nat_lang_year = CharField(editable=False, max_length=9)

    panels = [FieldPanel('edtf_string'), FieldPanel('nat_lang_edtf_string')]

    def __str__(self):
        return self.edtf_string

    def clean(self):
        try:
            e = parse_edtf(self.edtf_string)
        except EDTFParseException:
            raise ValidationError({
                'edtf_string':
                '{} is not a valid EDTF string'.format(self.edtf_string)
            })

        self.lower_fuzzy = struct_time_to_date(e.lower_fuzzy())
        self.upper_fuzzy = struct_time_to_date(e.upper_fuzzy())
        self.lower_strict = struct_time_to_date(e.lower_strict())
        self.upper_strict = struct_time_to_date(e.upper_strict())

        if self.lower_strict.year != self.upper_strict.year:
            self.nat_lang_year = '{}-{}'.format(self.lower_strict.year,
                                                self.upper_strict.year)
        else:
            self.nat_lang_year = str(self.lower_strict.year)

    def save(self, *args, **kwargs):
        try:
            e = parse_edtf(self.edtf_string)
        except EDTFParseException:
            raise ValidationError('{} is not a valid EDTF string'.format(
                self.edtf_string))

        self.lower_fuzzy = struct_time_to_date(e.lower_fuzzy())
        self.upper_fuzzy = struct_time_to_date(e.upper_fuzzy())
        self.lower_strict = struct_time_to_date(e.lower_strict())
        self.upper_strict = struct_time_to_date(e.upper_strict())

        if self.lower_strict.year != self.upper_strict.year:
            self.nat_lang_year = '{}-{}'.format(self.lower_strict.year,
                                                self.upper_strict.year)
        else:
            self.nat_lang_year = str(self.lower_strict.year)

        super().save(*args, **kwargs)
Example #3
0
class Instrument(Model):
    instrument = CharField(max_length=256)

    def __str__(self):
        return self.instrument
class Topic(BasePage):
    resource_type = "topic"
    parent_page_types = ["Topics"]
    subpage_types = ["Topic"]
    template = "topic.html"

    # Content fields
    description = RichTextField(
        blank=True,
        default="",
        features=RICH_TEXT_FEATURES_SIMPLE,
        help_text="Optional short text description, max. 400 characters",
        max_length=400,
    )
    featured = StreamField(
        StreamBlock(
            [
                (
                    "post",
                    PageChooserBlock(target_model=(
                        "articles.Article",
                        "externalcontent.ExternalArticle",
                    )),
                ),
                ("external_page", FeaturedExternalBlock()),
            ],
            max_num=4,
            required=False,
        ),
        null=True,
        blank=True,
        help_text="Optional space for featured posts, max. 4",
    )
    tabbed_panels = StreamField(
        StreamBlock([("panel", TabbedPanelBlock())], max_num=3,
                    required=False),
        null=True,
        blank=True,
        help_text=
        "Optional tabbed panels for linking out to other resources, max. 3",
        verbose_name="Tabbed panels",
    )
    latest_articles_count = IntegerField(
        choices=RESOURCE_COUNT_CHOICES,
        default=3,
        help_text="The number of posts to display for this topic.",
    )

    # Card fields
    card_title = CharField("Title", max_length=140, blank=True, default="")
    card_description = TextField("Description",
                                 max_length=400,
                                 blank=True,
                                 default="")
    card_image = ForeignKey(
        "mozimages.MozImage",
        null=True,
        blank=True,
        on_delete=SET_NULL,
        related_name="+",
        verbose_name="Image",
    )

    # Meta
    icon = FileField(
        upload_to="topics/icons",
        blank=True,
        default="",
        help_text=("MUST be a black-on-transparent SVG icon ONLY, "
                   "with no bitmap embedded in it."),
        validators=[check_for_svg_file],
    )
    color = CharField(max_length=14, choices=COLOR_CHOICES, default="blue-40")
    keywords = ClusterTaggableManager(through=TopicTag, blank=True)

    # Content panels
    content_panels = BasePage.content_panels + [
        FieldPanel("description"),
        StreamFieldPanel("featured"),
        StreamFieldPanel("tabbed_panels"),
        FieldPanel("latest_articles_count"),
        MultiFieldPanel(
            [InlinePanel("people")],
            heading="People",
            help_text=
            "Optional list of people associated with this topic as experts",
        ),
    ]

    # Card panels
    card_panels = [
        FieldPanel("card_title"),
        FieldPanel("card_description"),
        ImageChooserPanel("card_image"),
    ]

    # Meta panels
    meta_panels = [
        MultiFieldPanel(
            [
                InlinePanel("parent_topics", label="Parent topic(s)"),
                InlinePanel("child_topics", label="Child topic(s)"),
            ],
            heading="Parent/child topic(s)",
            classname="collapsible collapsed",
            help_text=("Topics with no parent (i.e. top-level topics) will be "
                       "listed on the home page. Child topics are listed "
                       "on the parent topic’s page."),
        ),
        MultiFieldPanel(
            [FieldPanel("icon"), FieldPanel("color")],
            heading="Theme",
            help_text=(
                "Theme settings used on topic page and any tagged content. "
                "For example, a post tagged with this topic "
                "will use the color specified here as its accent color."),
        ),
        MultiFieldPanel(
            [
                FieldPanel("seo_title"),
                FieldPanel("search_description"),
                ImageChooserPanel("social_image"),
                FieldPanel("keywords"),
            ],
            heading="SEO",
            help_text=("Optional fields to override the default "
                       "title and description for SEO purposes"),
        ),
    ]

    # Settings panels
    settings_panels = [FieldPanel("slug"), FieldPanel("show_in_menus")]

    # Tabs
    edit_handler = TabbedInterface([
        ObjectList(content_panels, heading="Content"),
        ObjectList(card_panels, heading="Card"),
        ObjectList(meta_panels, heading="Meta"),
        ObjectList(settings_panels, heading="Settings", classname="settings"),
    ])

    @property
    def articles(self):
        return get_combined_articles(self, topics__topic__pk=self.pk)

    @property
    def events(self):
        """Return upcoming events for this topic,
        ignoring events in the past, ordered by start date"""
        return get_combined_events(self,
                                   topics__topic__pk=self.pk,
                                   start_date__gte=datetime.datetime.now())

    @property
    def experts(self):
        """Return Person instances for topic experts"""
        return [person.person for person in self.people.all()]

    @property
    def videos(self):
        """Return the latest videos and external videos for this topic. """
        return get_combined_videos(self, topics__topic__pk=self.pk)

    @property
    def color_value(self):
        return dict(COLOR_VALUES)[self.color]

    @property
    def subtopics(self):
        return [topic.child for topic in self.child_topics.all()]
Example #5
0
class Dog(ExportModelOperationsMixin('dog'), Model):
    name = CharField(max_length=100, unique=True)
    breed = CharField(max_length=100, blank=True, null=True)
    age = PositiveIntegerField(blank=True, null=True)
Example #6
0
class BigCharSetModel(Model):
    field = SetTextField(base_field=CharField(max_length=8), max_length=32)
Example #7
0
 def filter_full_name(self, queryset, field_name, value):
     if value:
         queryset = queryset.annotate(fullname=Concat(F('group__slug'), V('/'), F('slug'),
                                      output_field=CharField())).filter(fullname__startswith=value)
     return queryset
Example #8
0
class SharableLink(Model):
    PERMISSIONS_CHOICES = (('read', 'read'), ('read+write', 'read+write'))
    code = CharField(max_length=32, unique=True)
    permissions = CharField(max_length=10, choices=PERMISSIONS_CHOICES)
    expiry_date = DateTimeField()
    note = ForeignKey(Note, on_delete=CASCADE)
Example #9
0
class Book(Model):
    title = CharField(max_length=32, db_index=True)
    author = ForeignKey(Author, on_delete=CASCADE, related_name="books")
Example #10
0
class Request(models.Model):
    id = CharField(max_length=36, default=uuid4, primary_key=True)
    path = CharField(max_length=190, db_index=True)
    query_params = TextField(blank=True, default='')
    raw_body = TextField(blank=True, default='')
    body = TextField(blank=True, default='')
    method = CharField(max_length=10)
    start_time = DateTimeField(default=timezone.now, db_index=True)
    view_name = CharField(max_length=190,
                          db_index=True,
                          blank=True,
                          default='',
                          null=True)
    end_time = DateTimeField(null=True, blank=True)
    time_taken = FloatField(blank=True, null=True)
    encoded_headers = TextField(blank=True, default='')  # stores json
    meta_time = FloatField(null=True, blank=True)
    meta_num_queries = IntegerField(null=True, blank=True)
    meta_time_spent_queries = FloatField(null=True, blank=True)
    pyprofile = TextField(blank=True, default='')
    prof_file = FileField(max_length=300,
                          blank=True,
                          storage=silk_storage,
                          null=True)

    # Useful method to create shortened copies of strings without losing start and end context
    # Used to ensure path and view_name don't exceed 190 characters
    def _shorten(self, string):
        return '%s...%s' % (string[:94], string[len(string) - 93:])

    @property
    def total_meta_time(self):
        return (self.meta_time or 0) + (self.meta_time_spent_queries or 0)

    @property
    def profile_table(self):
        for n, columns in enumerate(parse_profile(self.pyprofile)):
            location = columns[-1]
            if n and '{' not in location and '<' not in location:
                r = re.compile('(?P<src>.*\.py)\:(?P<num>[0-9]+).*')
                m = r.search(location)
                group = m.groupdict()
                src = group['src']
                num = group['num']
                name = 'c%d' % n
                fmt = '<a name={name} href="?pos={n}&file_path={src}&line_num={num}#{name}">{location}</a>'
                rep = fmt.format(**dict(group, **locals()))
                yield columns[:-1] + [mark_safe(rep)]
            else:
                yield columns

    # defined in atomic transaction within SQLQuery save()/delete() as well
    # as in bulk_create of SQLQueryManager
    # TODO: This is probably a bad way to do this, .count() will prob do?
    num_sql_queries = IntegerField(default=0)  # TODO replace with count()

    @property
    def time_spent_on_sql_queries(self):
        """
        TODO: Perhaps there is a nicer way to do this with Django aggregates?
        My initial thought was to perform:
        SQLQuery.objects.filter.aggregate(Sum(F('end_time')) - Sum(F('start_time')))
        However this feature isnt available yet, however there has been talk
        for use of F objects within aggregates for four years
        here: https://code.djangoproject.com/ticket/14030. It looks
        like this will go in soon at which point this should be changed.
        """
        return sum(x.time_taken for x in SQLQuery.objects.filter(request=self))

    @property
    def headers(self):
        if self.encoded_headers:
            raw = json.loads(self.encoded_headers)
        else:
            raw = {}

        return CaseInsensitiveDictionary(raw)

    @property
    def content_type(self):
        return self.headers.get('content-type', None)

    @classmethod
    def garbage_collect(cls, force=False):
        """ Remove Request/Responses when we are at the SILKY_MAX_RECORDED_REQUESTS limit
        Note that multiple in-flight requests may call this at once causing a
        double collection """
        check_percent = SilkyConfig().SILKY_MAX_RECORDED_REQUESTS_CHECK_PERCENT
        check_percent /= 100.0
        if check_percent < random.random() and not force:
            return
        target_count = SilkyConfig().SILKY_MAX_RECORDED_REQUESTS

        # Since garbage collection is probabilistic, the target count should
        # be lowered to account for requests before the next garbage collection
        if check_percent != 0:
            target_count -= int(1 / check_percent)

        # Make sure we can delete everything if needed by settings
        if target_count <= 0:
            cls.objects.all().delete()
            return
        requests = cls.objects.order_by('-start_time')
        if not requests or len(requests) - 1 < target_count:
            return
        time_cutoff = requests[target_count].start_time
        cls.objects.filter(start_time__lte=time_cutoff).delete()

    def save(self, *args, **kwargs):
        # sometimes django requests return the body as 'None'
        if self.raw_body is None:
            self.raw_body = ''

        if self.body is None:
            self.body = ''

        if self.end_time and self.start_time:
            interval = self.end_time - self.start_time
            self.time_taken = interval.total_seconds() * 1000

        # We can't save if either path or view_name exceed 190 characters
        if self.path and len(self.path) > 190:
            self.path = self._shorten(self.path)

        if self.view_name and len(self.view_name) > 190:
            self.view_name = self._shorten(self.view_name)

        super(Request, self).save(*args, **kwargs)
        Request.garbage_collect(force=False)
Example #11
0
class Event(BasePage):
    resource_type = "event"
    parent_page_types = ["events.Events"]
    subpage_types = []
    template = "event.html"

    # Content fields
    description = RichTextField(
        blank=True,
        default="",
        features=RICH_TEXT_FEATURES_SIMPLE,
        help_text="Optional short text description, max. 400 characters",
        max_length=400,
    )
    image = ForeignKey(
        "mozimages.MozImage",
        null=True,
        blank=True,
        on_delete=SET_NULL,
        related_name="+",
    )
    start_date = DateField(default=datetime.date.today)
    end_date = DateField(blank=True, null=True)
    latitude = FloatField(blank=True, null=True)
    longitude = FloatField(blank=True, null=True)
    register_url = URLField("Register URL", blank=True, null=True)
    body = CustomStreamField(
        blank=True,
        null=True,
        help_text=(
            "Optional body content. Supports rich text, images, embed via URL, "
            "embed via HTML, and inline code snippets"
        ),
    )
    venue_name = CharField(max_length=100, blank=True, default="")
    venue_url = URLField("Venue URL", max_length=100, blank=True, default="")
    address_line_1 = CharField(max_length=100, blank=True, default="")
    address_line_2 = CharField(max_length=100, blank=True, default="")
    address_line_3 = CharField(max_length=100, blank=True, default="")
    city = CharField(max_length=100, blank=True, default="")
    state = CharField("State/Province/Region", max_length=100, blank=True, default="")
    zip_code = CharField("Zip/Postal code", max_length=100, blank=True, default="")
    country = CountryField(blank=True, default="")
    agenda = StreamField(
        StreamBlock([("agenda_item", AgendaItemBlock())], required=False),
        blank=True,
        null=True,
        help_text="Optional list of agenda items for this event",
    )
    speakers = StreamField(
        StreamBlock(
            [
                ("speaker", PageChooserBlock(target_model="people.Person")),
                ("external_speaker", ExternalSpeakerBlock()),
            ],
            required=False,
        ),
        blank=True,
        null=True,
        help_text="Optional list of speakers for this event",
    )

    # Card fields
    card_title = CharField("Title", max_length=140, blank=True, default="")
    card_description = TextField("Description", max_length=400, blank=True, default="")
    card_image = ForeignKey(
        "mozimages.MozImage",
        null=True,
        blank=True,
        on_delete=SET_NULL,
        related_name="+",
        verbose_name="Image",
    )

    # Meta fields
    keywords = ClusterTaggableManager(through=EventTag, blank=True)

    # Content panels
    content_panels = BasePage.content_panels + [
        FieldPanel("description"),
        MultiFieldPanel(
            [ImageChooserPanel("image")],
            heading="Image",
            help_text=(
                "Optional header image. If not specified a fallback will be used. "
                "This image is also shown when sharing this page via social media"
            ),
        ),
        MultiFieldPanel(
            [
                FieldPanel("start_date"),
                FieldPanel("end_date"),
                FieldPanel("latitude"),
                FieldPanel("longitude"),
                FieldPanel("register_url"),
            ],
            heading="Event details",
            classname="collapsible",
            help_text=mark_safe(
                "Optional time and location information for this event. Latitude and "
                "longitude are used to show a map of the event’s location. For more "
                "information on finding these values for a given location, "
                "'<a href='https://support.google.com/maps/answer/18539'>"
                "see this article</a>"
            ),
        ),
        StreamFieldPanel("body"),
        MultiFieldPanel(
            [
                FieldPanel("venue_name"),
                FieldPanel("venue_url"),
                FieldPanel("address_line_1"),
                FieldPanel("address_line_2"),
                FieldPanel("address_line_3"),
                FieldPanel("city"),
                FieldPanel("state"),
                FieldPanel("zip_code"),
                FieldPanel("country"),
            ],
            heading="Event address",
            classname="collapsible",
            help_text=(
                "Optional address fields. The city and country are also shown "
                "on event cards"
            ),
        ),
        StreamFieldPanel("agenda"),
        StreamFieldPanel("speakers"),
    ]

    # Card panels
    card_panels = [
        FieldPanel("card_title"),
        FieldPanel("card_description"),
        ImageChooserPanel("card_image"),
    ]

    # Meta panels
    meta_panels = [
        MultiFieldPanel(
            [InlinePanel("topics")],
            heading="Topics",
            help_text=(
                "These are the topic pages the event will appear on. The first topic "
                "in the list will be treated as the primary topic and will be shown "
                "in the page’s related content."
            ),
        ),
        MultiFieldPanel(
            [
                FieldPanel("seo_title"),
                FieldPanel("search_description"),
                ImageChooserPanel("social_image"),
                FieldPanel("keywords"),
            ],
            heading="SEO",
            help_text=(
                "Optional fields to override the default title and description "
                "for SEO purposes"
            ),
        ),
    ]

    # Settings panels
    settings_panels = [FieldPanel("slug")]

    edit_handler = TabbedInterface(
        [
            ObjectList(content_panels, heading="Content"),
            ObjectList(card_panels, heading="Card"),
            ObjectList(meta_panels, heading="Meta"),
            ObjectList(settings_panels, heading="Settings", classname="settings"),
        ]
    )

    @property
    def is_upcoming(self):
        """Returns whether an event is in the future."""
        return self.start_date >= datetime.date.today()

    @property
    def primary_topic(self):
        """Return the first (primary) topic specified for the event."""
        article_topic = self.topics.first()
        return article_topic.topic if article_topic else None

    @property
    def month_group(self):
        return self.start_date.replace(day=1)

    @property
    def country_group(self):
        return (
            {"slug": self.country.code.lower(), "title": self.country.name}
            if self.country
            else {"slug": ""}
        )

    @property
    def event_dates(self):
        """Return a formatted string of the event start and end dates"""
        event_dates = self.start_date.strftime("%b %-d")
        if self.end_date and self.end_date != self.start_date:
            event_dates += " &ndash; "
            start_month = self.start_date.strftime("%m")
            if self.end_date.strftime("%m") == start_month:
                event_dates += self.end_date.strftime("%-d")
            else:
                event_dates += self.end_date.strftime("%b %-d")
        return event_dates

    @property
    def event_dates_full(self):
        """Return a formatted string of the event start and end dates,
        including the year"""
        return self.event_dates + self.start_date.strftime(", %Y")

    def has_speaker(self, person):
        for speaker in self.speakers:  # pylint: disable=not-an-iterable
            if speaker.block_type == "speaker" and str(speaker.value) == str(
                person.title
            ):
                return True
        return False
Example #12
0
    def get_redirect_path_with_status(self, path, full_path=None, language=None, version_slug=None):
        # add extra fields with the ``path`` and ``full_path`` to perform a
        # filter at db level instead with Python
        queryset = self.annotate(
            path=Value(
                path,
                output_field=CharField(),
            ),
            full_path=Value(
                full_path,
                output_field=CharField(),
            ),

            from_url_length=ExpressionWrapper(
                Length('from_url'),
                output_field=IntegerField(),
            ),

            # 1-indexed
            from_url_without_rest=Substr(
                'from_url',
                1,
                F('from_url_length') - 5,  # Strip "$rest"
                output_field=CharField(),
            ),

            # 1-indexed
            full_path_without_rest=Substr(
                'full_path',
                1,
                F('from_url_length') - 5,  # Strip "$rest"
                output_field=CharField(),
            ),
        )
        prefix = Q(
            redirect_type='prefix',
            path__startswith=F('from_url'),
        )
        page = Q(
            redirect_type='page',
            path__iexact=F('from_url'),
        )
        exact = (
            Q(
                redirect_type='exact',
                from_url__endswith='$rest',
                # This works around a bug in Django doing a substr and an endswith,
                # so instead we do 2 substrs and an exact
                # https://code.djangoproject.com/ticket/29155
                full_path_without_rest=F('from_url_without_rest'),
            ) | Q(
                redirect_type='exact',
                full_path__iexact=F('from_url'),
            )
        )
        sphinx_html = (
            Q(
                redirect_type='sphinx_html',
                path__endswith='/',
            ) | Q(
                redirect_type='sphinx_html',
                path__endswith='/index.html',
            )
        )
        sphinx_htmldir = Q(
            redirect_type='sphinx_htmldir',
            path__endswith='.html',
        )

        # There should be one and only one redirect returned by this query. I
        # can't think in a case where there can be more at this point. I'm
        # leaving the loop just in case for now
        queryset = queryset.filter(prefix | page | exact | sphinx_html | sphinx_htmldir)
        for redirect in queryset.select_related('project'):
            new_path = redirect.get_redirect_path(
                path=path,
                language=language,
                version_slug=version_slug,
            )
            if new_path:
                return new_path, redirect.http_status
        return (None, None)
Example #13
0
class StrainSource(Model):
    """
    A strain source contains all the meta-data relating to where a strain was collected
    from whom, by whom, and what ever else we can say about the strain.
    """
    name = CharField(max_length=128, db_index=True, unique=True)
    old_id = CharField(max_length=50, db_index=True, null=True, blank=True)
    cluster = CharField(max_length=15, null=True, blank=True)
    date = DateField(null=True, blank=True)

    country = ForeignKey(Country,
                         null=True,
                         blank=True,
                         related_name='sources')
    city = ForeignKey(Place, null=True, blank=True, related_name='sources')

    importer = ForeignKey(ImportSource,
                          verbose_name='Import Source',
                          null=True,
                          blank=True)
    source_lab = CharField(max_length=100,
                           verbose_name='Laboratory Source',
                           db_index=True,
                           null=True,
                           blank=True)
    source_paper = ForeignKey(Paper,
                              related_name="strains",
                              null=True,
                              blank=True)
    bioproject = ForeignKey(BioProject,
                            related_name="strains",
                            null=True,
                            blank=True)

    patient_id = CharField(max_length=16, db_index=True)
    patient_age = PositiveIntegerField(null=True, blank=True)
    patient_sex = CharField(max_length=3, choices=SEXES, null=True, blank=True)
    patient_hiv = CharField(max_length=10, choices=HIVS, null=True, blank=True)

    spoligotype_type = IntegerField(null=True, blank=True)
    spoligotype_family = CharField("Spoligotype Family Parent Strain",
                                   max_length=255,
                                   null=True,
                                   blank=True)
    spoligotype_octal = CharField(validators=[is_octal],
                                  max_length=15,
                                  null=True,
                                  blank=True)

    lineage = ForeignKey(Lineage,
                         related_name='strains',
                         null=True,
                         blank=True)
    rflp_type = CharField("Restriction fragment length polymorphism type",
                          max_length=10,
                          null=True,
                          blank=True)
    rflp_family = CharField("Restriction fragment length polymorphism family",
                            max_length=10,
                            null=True,
                            blank=True)
    insert_type = IntegerField("Insertion sequence 6110 type",
                               null=True,
                               blank=True)

    wgs_group = CharField("Whole Genome Sequence Group",
                          max_length=10,
                          null=True,
                          blank=True)
    principle_group = IntegerField("Principle Generic Group",
                                   null=True,
                                   blank=True)
    resistance_group = CharField(max_length=4,
                                 choices=RESISTANCE_GROUP,
                                 null=True,
                                 blank=True)
    targeting = ForeignKey(TargetSet, null=True, blank=True)

    notes = TextField(null=True, blank=True)

    objects = StrainSourceManager()

    def natural_key(self):
        """Natural key for strains based just on their name"""
        return (self.name, )

    def generate_resistance_group(self):
        """Generates the correct resistance_group based on drug information"""
        resistant_to = self.drugs.filter(resistance='r').values_list(
            'drug__code', flat=True)
        sensitive_to = self.drugs.filter(resistance='s').values_list(
            'drug__code', flat=True)
        group = None  # Unknown

        if 'INH' in resistant_to and 'RIF' in resistant_to:
            group = 'MDR'
            if ('MOXI' in resistant_to) or ('GATI' in resistant_to) or (
                    'LEVO' in resistant_to):
                if ('KAN' in resistant_to) or ('AMK' in resistant_to) or (
                        'CAP' in resistant_to):
                    group = 'XDR'
        elif resistant_to:
            group = 'ODR'
        elif 'INH' in sensitive_to or 'RIF' in sensitive_to:
            group = 's'

        self.resistance_group = group
        self.save()

    def __str__(self):
        return self.name or self.patient_id or ("Unnamed %d" % self.pk)
Example #14
0
class BioProject(Model):
    name = CharField(max_length=128, unique=True)

    def __str__(self):
        return self.name
Example #15
0
class CharSetModel(Model):
    field = SetCharField(base_field=CharField(max_length=8),
                         size=3,
                         max_length=32)
    field2 = SetCharField(base_field=CharField(max_length=8), max_length=255)
Example #16
0
class VanillaAuthor(VanillaModel):
    name = CharField(max_length=32)
Example #17
0
class CharListModel(Model):
    field = ListCharField(base_field=CharField(max_length=8),
                          size=3,
                          max_length=32)
Example #18
0
class NameAuthor(Model):
    name = CharField(max_length=32, primary_key=True)
Example #19
0
class BigCharListModel(Model):
    field = ListTextField(base_field=CharField(max_length=8))
Example #20
0
class AuthorMultiIndex(Model):
    class Meta:
        index_together = ("name", "country")

    name = CharField(max_length=32, db_index=True)
    country = CharField(max_length=32)
Example #21
0
class BaseSchema(Model):
    """
    Metadata for an attribute.
    """
    TYPE_TEXT = 'text'
    TYPE_FLOAT = 'float'
    TYPE_DATE = 'date'
    TYPE_BOOLEAN = 'bool'
    TYPE_ONE = 'one'
    TYPE_MANY = 'many'
    #TYPE_RANGE   = 'range'
    #TYPE_OBJECT   = 'object'

    DATATYPE_CHOICES = (
        (TYPE_TEXT, _('text')),
        (TYPE_FLOAT, _('number')),
        (TYPE_DATE, _('date')),
        (TYPE_BOOLEAN, _('boolean')),
        (TYPE_ONE, _('choice')),
        (TYPE_MANY, _('multiple choices')),
        #(TYPE_RANGE,   _('numeric range')),
        #(TYPE_OBJECT,   _('django model')),
    )

    title = CharField(_('title'),
                      max_length=250,
                      help_text=_('user-friendly attribute name'))
    name = AutoSlugField(_('name'),
                         max_length=250,
                         populate_from='title',
                         editable=True,
                         blank=True,
                         slugify=slugify_attr_name)
    help_text = CharField(_('help text'),
                          max_length=250,
                          blank=True,
                          help_text=_('short description for administrator'))
    datatype = CharField(_('data type'),
                         max_length=6,
                         choices=DATATYPE_CHOICES)

    required = BooleanField(_('required'))
    searched = BooleanField(
        _('include in search'))  # i.e. full-text search? mb for text only
    filtered = BooleanField(_('include in filters'))
    sortable = BooleanField(_('allow sorting'))

    class Meta:
        abstract = True
        verbose_name, verbose_name_plural = _('schema'), _('schemata')
        ordering = ['title']

    def __unicode__(self):
        return u'%s (%s)%s' % (self.title, self.get_datatype_display(),
                               u' %s' % _('required') if self.required else '')

    def get_choices(self):
        """
        Returns a queryset of choice objects bound to this schema.
        """
        return self.choices.all()

    def get_attrs(self, entity):
        """
        Returns available attributes for given entity instance.
        Handles many-to-one relations transparently.
        """
        return self.attrs.filter(**get_entity_lookups(entity))

    def save_attr(self, entity, value):
        """
        Saves given EAV attribute with given value for given entity.

        If schema is not a choice, the value is saved to the corresponding
        Attr instance (which is created or updated).

        If schema is an cvhoice (one-to-one or many-to-one), the value is
        processed thusly:

        * if value is iterable, all Attr instances for corresponding managed choice
          schemata are updated (those with names from the value list are set to
          True, others to False). If a list item is not in available choices,
          ValueError is raised;
        * if the value is None, all corresponding Attr instances are reset to False;
        * if the value is neither a list nor None, it is wrapped into a list and
          processed as above (i.e. "foo" --> ["foo"]).
        """

        if self.datatype in (self.TYPE_ONE, self.TYPE_MANY):
            self._save_choice_attr(entity, value)
        else:
            self._save_single_attr(entity, value)

    def _save_single_attr(self,
                          entity,
                          value=None,
                          schema=None,
                          create_nulls=False,
                          extra={}):
        """
        Creates or updates an EAV attribute for given entity with given value.

        :param schema: schema for attribute. Default it current schema instance.
        :param create_nulls: boolean: if True, even attributes with value=None
            are created (by default they are skipped).
        :param extra: dict: additional data for Attr instance (e.g. title).
        """
        # If schema is not many-to-one, the value is saved to the corresponding
        # Attr instance (which is created or updated).

        schema = schema or self
        lookups = dict(get_entity_lookups(entity), schema=schema, **extra)
        try:
            attr = self.attrs.get(**lookups)
        except self.attrs.model.DoesNotExist:
            attr = self.attrs.model(**lookups)
        if create_nulls or value != attr.value:
            attr.value = value
            for k, v in extra.items():
                setattr(attr, k, v)
            attr.save()

    def _save_choice_attr(self, entity, value):
        """
        Creates or updates BaseChoice(s) attribute(s) for given entity.
        """

        # value can be None to reset choices from schema
        if value == None:
            value = []

        if not hasattr(value, '__iter__'):
            value = [value]

        if self.datatype == self.TYPE_ONE and len(value) > 1:
            raise TypeError('Cannot assign multiple values "%s" to TYPE_ONE '
                            'must be only one BaseChoice instance.' % value)

        if not all(isinstance(x, BaseChoice) for x in value):
            raise TypeError('Cannot assign "%s": "Attr.choice" '
                            'must be a BaseChoice instance.' % value)

        # drop all attributes for this entity/schema pair
        self.get_attrs(entity).delete()

        # Attr instances for corresponding managed choice schemata are updated
        for choice in value:
            self._save_single_attr(entity,
                                   schema=self,
                                   create_nulls=True,
                                   extra={'choice': choice})
Example #22
0
class AuthorHugeName(Model):
    class Meta:
        db_table = "this_is_an_author_with_an_incredibly_long_table_name_" "you_know_it"

    name = CharField(max_length=32)
Example #23
0
class Lawn(ExportModelOperationsMixin('lawn'), Model):
    location = CharField(max_length=100)
Example #24
0
class Customer(Model):
    name = CharField(max_length=32)
Example #25
0
class Genre(Model):
    genre = CharField(max_length=256)

    def __str__(self):
        return self.genre
Example #26
0
class TitledAgedCustomer(AgedCustomer):
    class Meta:
        db_table = "titled aged customer"  # Test name quoting

    title = CharField(max_length=16)
Example #27
0
class CompositionPage(Page):
    composition_title = RichTextField(features=['bold', 'italic'])
    description = StreamField([('rich_text', RichTextBlock()),
                               ('image', ImageChooserBlock())],
                              blank=True)
    location = RichTextField(
        blank=True,
        features=['bold', 'italic', 'link', 'document-link'],
    )
    genre = ParentalManyToManyField(Genre,
                                    blank=True,
                                    related_name='compositions')
    instrumentation = ParentalManyToManyField(
        'Instrument',
        blank=True,
    )
    orchestration = RichTextField(
        blank=True,
        features=['bold', 'italic'],
        help_text=(
            'If the composition is for an ensemble, use this field to enter '
            'the orchestration of the work.'))
    duration = DurationField(null=True,
                             blank=True,
                             help_text='Expects data in the format "HH:MM:SS"')
    dedicatee = RichTextField(
        blank=True,
        features=['bold', 'italic', 'link', 'document-link'],
    )
    text_source = RichTextField(
        blank=True,
        features=['bold', 'italic', 'link', 'document-link'],
        help_text='The source of the text used in the compostition.')
    collaborator = RichTextField(
        blank=True,
        features=['bold', 'italic', 'link', 'document-link'],
        help_text='Others that Decruck collaborated with.')
    manuscript_status = RichTextField(
        blank=True,
        features=['bold', 'italic', 'link', 'document-link'],
        help_text='Notes about the location and condition of the manuscript.')
    recording = StreamField([('rich_text', RichTextBlock()),
                             ('image', ImageChooserBlock())],
                            blank=True)
    information_up_to_date = BooleanField(default=False)
    scanned = BooleanField(default=False)
    premiere = RichTextField(
        blank=True,
        features=['bold', 'italic', 'link', 'document-link'],
    )

    # For preview score
    preview_score = FileField(
        upload_to='composition_preview_scores/',
        blank=True,
        null=True,
        validators=[FileExtensionValidator(allowed_extensions=['pdf'])])
    preview_score_checksum = CharField(editable=False,
                                       max_length=256,
                                       blank=True)
    preview_score_checked = False
    preview_score_updated = False

    # Extended Date Time Format
    nat_lang_edtf_string = CharField(
        verbose_name='Natural Language Date',
        help_text=('The EDTF date in natural language. This field is help '
                   'users who aren\'t familiar with the EDTF. It does not '
                   'change how the date is represented.'),
        blank=True,
        max_length=256)
    edtf_string = CharField(
        verbose_name='EDTF Date',
        help_text=mark_safe(
            'A date in the <a href="https://www.loc.gov/standards/datetime/" '
            'target="_blank"><strong>Extended Date Time Format</strong></a>'),
        blank=True,
        max_length=256)
    lower_fuzzy = DateField(editable=False, null=True, blank=True)
    upper_fuzzy = DateField(editable=False, null=True, blank=True)
    lower_strict = DateField(editable=False, null=True, blank=True)
    upper_strict = DateField(editable=False, null=True, blank=True)
    nat_lang_year = CharField(editable=False, max_length=9, blank=True)

    def instrumentation_list(self):
        return ', '.join([str(i) for i in self.instrumentation.all()])

    class Meta:
        verbose_name = "Composition"

    def get_context(self, request, *args, **kwargs):
        ctx = super().get_context(request, *args, **kwargs)

        try:
            search_idx = request.session['comp_search_index']
            if search_idx:
                idx = search_idx.index(self.pk)
                prev_url = None
                next_url = None
                if idx > 0:
                    pk = search_idx[idx - 1]
                    prev_url = CompositionPage.objects.get(pk=pk).url

                if idx < len(search_idx) - 1:
                    pk = search_idx[idx + 1]
                    next_url = CompositionPage.objects.get(pk=pk).url

                ctx['prev_url'] = prev_url
                ctx['next_url'] = next_url
                ctx['comp_search_qs'] = request.\
                    session.get('comp_search_qs', '')
        except (KeyError, ValueError):
            pass

        return ctx

    def clean(self):
        super().clean()
        # Per Django docs: validate and modify values in Model.clean()
        # https://docs.djangoproject.com/en/3.1/ref/models/instances/#django.db.models.Model.clean

        # Check that nat_lang_edtf_string and edtf_string are either both set, or both unset
        if (self.nat_lang_edtf_string
                and not self.edtf_string) or (not self.nat_lang_edtf_string
                                              and self.edtf_string):
            raise ValidationError(
                'If setting a date on a composition, an EDTF string and a natural language EDTF string must be provided.'
            )

        # Validate edtf_string
        if self.edtf_string and self.nat_lang_edtf_string:
            try:
                e = parse_edtf(self.edtf_string)
            except EDTFParseException:
                raise ValidationError({
                    'edtf_string':
                    '{} is not a valid EDTF string'.format(self.edtf_string)
                })

            self.lower_fuzzy = struct_time_to_date(e.lower_fuzzy())
            self.upper_fuzzy = struct_time_to_date(e.upper_fuzzy())
            self.lower_strict = struct_time_to_date(e.lower_strict())
            self.upper_strict = struct_time_to_date(e.upper_strict())

            if self.lower_strict.year != self.upper_strict.year:
                self.nat_lang_year = '{}-{}'.format(self.lower_strict.year,
                                                    self.upper_strict.year)
            else:
                self.nat_lang_year = str(self.lower_strict.year)

    def save(self, *args, **kwargs):
        # If there's no preview score file, then just save the model
        if not self.preview_score:
            return super().save(*args, **kwargs)

        if self.preview_score_checked:
            # This was the cause of a subtle bug. Because this method can be
            # called multiple times during model creation, leaving this flag
            # set would cause the post save hook to fire multiple times.
            self.preview_score_updated = False
            return super().save(*args, **kwargs)

        h = hashlib.md5()
        for chunk in iter(lambda: self.preview_score.read(8192), b''):
            h.update(chunk)

        self.preview_score.seek(0)
        checksum = h.hexdigest()
        if not self.preview_score_checksum == checksum:
            self.preview_score_checksum = checksum
            self.preview_score_updated = True

        self.preview_score_checked = True
        return super().save(*args, **kwargs)

    content_panels = Page.content_panels + [
        FieldPanel('composition_title'),
        StreamFieldPanel('description'),
        MultiFieldPanel(
            [FieldPanel('edtf_string'),
             FieldPanel('nat_lang_edtf_string')],
            help_text='Enter a date in the LOC Extended Date Time Format',
            heading='Date'),
        FieldPanel('location'),
        FieldPanel('instrumentation'),
        FieldPanel('orchestration'),
        FieldPanel('duration'),
        FieldPanel('dedicatee'),
        FieldPanel('premiere'),
        FieldPanel('genre'),
        FieldPanel('text_source'),
        FieldPanel('collaborator'),
        FieldPanel('manuscript_status'),
        FieldPanel('information_up_to_date'),
        FieldPanel('scanned'),
        FieldPanel('preview_score'),
        StreamFieldPanel('recording'),
    ]

    search_fields = Page.search_fields + [
        index.SearchField('description', partial_match=True),
        index.SearchField('location', partial_match=True),
        index.SearchField('dedicatee', partial_match=True),
        index.SearchField('premiere', partial_match=True),
        index.SearchField('text_source', partial_match=True),
        index.SearchField('collaborator', partial_match=True),
        index.SearchField('manuscript_status', partial_match=True),
        index.SearchField('recording', partial_match=True),
        index.RelatedFields('genre', [
            index.SearchField('genre_en', partial_match=True),
            index.SearchField('genre_fr', partial_match=True),
        ]),
        index.RelatedFields('instrumentation', [
            index.SearchField('instrument_en', partial_match=True),
            index.SearchField('instrument_fr', partial_match=True),
        ]),
    ]

    parent_page_types = ['CompositionListingPage']
Example #28
0
class Poll(VanillaModel):
    question = CharField(max_length=200)
    answer = CharField(max_length=200)
    pub_date = DateTimeField("date published", default=expensive_calculation)
Example #29
0
class ScorePage(RoutablePageMixin, Page):
    cover_image = ForeignKey('wagtailimages.Image',
                             null=True,
                             blank=True,
                             on_delete=PROTECT,
                             related_name='cover_image')
    description = StreamField([('rich_text', RichTextBlock()),
                               ('image', ImageChooserBlock())])
    duration = DurationField(null=True,
                             blank=True,
                             help_text='Expects data in the format "HH:MM:SS"')
    file = FileField(
        upload_to='scores/',
        validators=[FileExtensionValidator(allowed_extensions=['pdf', 'zip'])])
    preview_score = FileField(
        upload_to='preview_scores/',
        validators=[FileExtensionValidator(allowed_extensions=['pdf'])])
    preview_score_checksum = CharField(editable=False,
                                       max_length=256,
                                       blank=True)
    preview_score_checked = False
    preview_score_updated = False
    genre = ParentalManyToManyField(Genre, blank=True, related_name='scores')
    date = CharField(max_length=256, blank=True)
    instrumentation = ParentalManyToManyField(
        'Instrument',
        blank=True,
        help_text='The instrumentation of the compostition.')
    price = DecimalField(max_digits=6, decimal_places=2)
    materials = RichTextField(
        blank=True,
        features=['bold', 'italic', 'link', 'document-link'],
        help_text='The materials sent in the PDF file.')

    def save(self, *args, **kwargs):
        if self.preview_score_checked:
            # This was the cause of a subtle bug. Because this method can be
            # called multiple times during model creation, leaving this flag
            # set would cause the post save hook to fire multiple times.
            self.preview_score_updated = False
            return super().save(*args, **kwargs)

        h = hashlib.md5()
        for chunk in iter(lambda: self.preview_score.read(8192), b''):
            h.update(chunk)

        self.preview_score.seek(0)
        checksum = h.hexdigest()
        if not self.preview_score_checksum == checksum:
            self.preview_score_checksum = checksum
            self.preview_score_updated = True

        self.preview_score_checked = True
        return super().save(*args, **kwargs)

    @route(r'^([\w-]+)/$')
    def get_score_file(self, request, score_link_slug):
        if request.method == 'GET':
            item_link = get_object_or_404(OrderItemLink, slug=score_link_slug)

            if item_link.is_expired():
                raise Http404()

            item_link.access_ip = request.META.get('REMOTE_ADDR', '0.0.0.0')
            item_link.save()

            return render(request, "main/score_page_download.html", {
                'self': self,
                'page': self,
            })
        else:
            raise Http404()

    @route(r'^$')
    def score(self, request):
        cart_page = ShoppingCartPage.objects.first()
        if request.method == 'POST':
            in_cart = toggle_score_in_cart(request, self.pk)
            return render(
                request, "main/score_page.html", {
                    'self': self,
                    'page': self,
                    'in_cart': in_cart,
                    'cart_page': cart_page
                })
        else:
            return render(
                request, "main/score_page.html", {
                    'self': self,
                    'page': self,
                    'in_cart': score_in_cart(request, self.pk),
                    'cart_page': cart_page
                })

    class Meta:
        verbose_name = "Score Page"

    content_panels = Page.content_panels + [
        FieldPanel('date'),
        FieldPanel('duration'),
        FieldPanel('genre'),
        FieldPanel('instrumentation'),
        FieldPanel('price'),
        StreamFieldPanel('description'),
        FieldPanel('materials'),
        FieldPanel('file'),
        FieldPanel('preview_score'),
        ImageChooserPanel('cover_image')
    ]
class User(AbstractUser):
    name = CharField(_("Name of User"), blank=True, null=True, max_length=255)

    def get_absolute_url(self):
        return reverse("users:detail", kwargs={"username": self.username})