Example #1
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)
    def test_max_length(self):
        field = SetCharField(
            models.CharField(max_length=32),
            size=3,
            max_length=32
        )

        field.clean({'a', 'b', 'c'}, None)

        with pytest.raises(exceptions.ValidationError) as excinfo:
            field.clean({'a', 'b', 'c', 'd'}, None)
        assert (
            excinfo.value.messages[0] ==
            'Set contains 4 items, it should contain no more than 3.'
        )
Example #3
0
class CharSetDefaultModel(Model):
    field = SetCharField(
        base_field=CharField(max_length=5),
        size=5,
        max_length=32,
        default=lambda: {"a", "d"},
    )
Example #4
0
class Migration(migrations.Migration):

    dependencies = []

    operations = [
        migrations.CreateModel(
            name="IntSetDefaultModel",
            fields=[
                (
                    "id",
                    models.AutoField(
                        verbose_name="ID",
                        serialize=False,
                        auto_created=True,
                        primary_key=True,
                    ),
                ),
                (
                    "field",
                    SetCharField(models.IntegerField(), size=None, max_length=32),
                ),
            ],
            options={},
            bases=(models.Model,),
        )
    ]
class Migration(migrations.Migration):

    dependencies = [("testapp", "0001_initial")]

    operations = [
        migrations.AddField(
            model_name="intsetdefaultmodel",
            name="field_2",
            field=SetCharField(
                models.IntegerField(), default=lambda: set(), size=None, max_length=32
            ),
        ),
        migrations.AddField(
            model_name="intsetdefaultmodel",
            name="field_3",
            field=SetCharField(
                models.IntegerField(), default=lambda: {1, 5}, size=None, max_length=32
            ),
        ),
    ]
Example #6
0
class CardToken(models.Model):

    COST_PATTERN = r"(({(h[wubrg]|\u221E|\u00BD|(([0-9]+|[WUBRGCXYZST])(\/[WUBRGP])?))})|\(.*\))"

    name = models.CharField(max_length=255)
    colors = SetCharField(base_field=models.CharField(max_length=50),
                          max_length=(5 * 51),
                          null=True)
    type = models.CharField(max_length=255)
    text = models.TextField(null=True)
    power = models.CharField(max_length=255, null=True)
    toughness = models.CharField(max_length=255, null=True)

    @property
    def html_text(self):
        return self.transform_tags(self.text)

    def transform_tags(self, string):
        if (string == None or string == ''):
            return ''
        complete = ''
        empty = ''
        regex = re.compile(self.COST_PATTERN)
        last_index = 0
        string = "<br />".join(string.split('\n'))
        for tag in regex.finditer(string):
            if (tag.group()[0] == '{'):
                raw = tag.group()[1:-1].lower()
                bool_split = raw.find('/') != -1 and raw.find('p') == -1
                split = ' ms-split' if bool_split else ''
                bool_half = raw[0] == 'h'
                if bool_half:  # Scott says this is bad, fairly certain it isn't
                    raw = raw[1:]
                raw = empty.join(raw.split('/'))
                if raw == 't':
                    raw += 'ap'
                elif raw == "\u221E":
                    raw = 'infinity'
                elif raw == "\u00BD":
                    raw = 'half'
                # The previous 6 lines might be able to be cleaned up
                html_tag = "<i class=\"ms ms-cost ms-shadow ms-%s%s\"></i>" % (
                    raw, split)
                if bool_half:
                    html_tag = '<span class="ms-half">' + html_tag + '</span>'
            else:
                html_tag = '<span class="reminder">%s</span>' % tag.group()
            complete += string[last_index:tag.start()] + html_tag
            last_index = tag.end()
        complete += string[last_index:]
        return complete
class Migration(migrations.Migration):

    dependencies = [
        ('testapp', '0001_initial'),
    ]

    operations = [
        migrations.AddField(
            model_name='intsetdefaultmodel',
            name='field_2',
            field=SetCharField(models.IntegerField(),
                               default=lambda: set(),
                               size=None,
                               max_length=32),
        ),
        migrations.AddField(
            model_name='intsetdefaultmodel',
            name='field_3',
            field=SetCharField(models.IntegerField(),
                               default=lambda: {1, 5},
                               size=None,
                               max_length=32),
        ),
    ]
    def test_makemigrations(self):
        field = SetCharField(models.CharField(max_length=5), max_length=32)
        statement, imports = MigrationWriter.serialize(field)

        # The order of the output max_length/size statements varies by
        # python version, hence a little regexp to match them
        assert re.compile(
            r"""^django_mysql\.models\.SetCharField\(
                models\.CharField\(max_length=5\),\ # space here
                (
                    max_length=32,\ size=None|
                    size=None,\ max_length=32
                )
                \)$
            """, re.VERBOSE).match(statement)
Example #9
0
    def test_max_length(self):
        field = SetCharField(models.CharField(max_length=32), size=3, max_length=32)

        field.clean({"a", "b", "c"}, None)

        with pytest.raises(exceptions.ValidationError) as excinfo:
            field.clean({"a", "b", "c", "d"}, None)
        assert (
            excinfo.value.messages[0]
            == "Set contains 4 items, it should contain no more than 3."
        )
Example #10
0
    def test_max_length(self):
        field = SetCharField(
            models.CharField(max_length=32),
            size=3,
            max_length=32,
        )

        field.clean({'a', 'b', 'c'}, None)

        with pytest.raises(exceptions.ValidationError) as excinfo:
            field.clean({'a', 'b', 'c', 'd'}, None)
        assert excinfo.value.messages[
            0] == 'Set contains 4 items, it should contain no more than 3.'
Example #11
0
 class InvalidSetCharFieldModel4(TemporaryModel):
     field = SetCharField(models.CharField(max_length=2), size=2)
Example #12
0
 def test_deconstruct(self):
     field = SetCharField(models.IntegerField(), max_length=32)
     name, path, args, kwargs = field.deconstruct()
     new = SetCharField(*args, **kwargs)
     assert new.base_field.__class__ == field.base_field.__class__
Example #13
0
 class InvalidSetCharFieldModel1(TemporaryModel):
     field = SetCharField(models.CharField(), max_length=32)
Example #14
0
 class InvalidSetCharFieldModel2(TemporaryModel):
     field = SetCharField(
         models.ForeignKey("testapp.Author", on_delete=models.CASCADE),
         max_length=32,
     )
Example #15
0
 def test_model_field_formfield(self):
     model_field = SetCharField(models.CharField(max_length=27))
     form_field = model_field.formfield()
     assert isinstance(form_field, SimpleSetField)
     assert isinstance(form_field.base_field, forms.CharField)
     assert form_field.base_field.max_length == 27
Example #16
0
 def test_deconstruct_args(self):
     field = SetCharField(models.CharField(max_length=5), max_length=32)
     name, path, args, kwargs = field.deconstruct()
     new = SetCharField(*args, **kwargs)
     assert new.base_field.max_length == field.base_field.max_length
Example #17
0
class Team(MySqlModel):
    """
    Attributes:
        
    :attr id: Unique team id, always equal to the team_number.
    :attr active_years {@set[int]}: A set of years that the team has been active (in commission, not participated)
    :attr website {@string}: URL for the team website
    :attr team_number: FRC assigned team number
    :attr name: Long FRC Team Name (note, this can be VERY long, short_name or nickname is recommended)
    :attr short_name: Short FRC Team Name (often the more wel
    :attr nickname: Team Nickname, e.g. Shaker Robotics or Cheesy Poofs
    :attr key: Most specific team name, simply frc#### where #### is the team number
    """

    active_years = SetCharField(base_field=models.IntegerField(),
                                max_length=255,
                                default=set())

    website = models.URLField(null=True)
    name = models.TextField(null=True)  # longer name

    locality = models.CharField(max_length=50, null=True)  # e.g. city
    region = models.CharField(max_length=50, null=True)  # e.g. state, province
    country_name = models.CharField(max_length=50, null=True)
    location = models.CharField(max_length=150,
                                null=True)  # full city + state + country

    team_number = models.PositiveSmallIntegerField(db_index=True)
    key = models.CharField(max_length=8)  # e.g. frc2791
    nickname = models.CharField(max_length=100, null=True)  # shorter name
    rookie_year = models.PositiveSmallIntegerField(null=True)
    motto = models.TextField(null=True)

    # TrueSkill distribution, which is a model of player skill which assumes a Gaussian distribution with
    # an initial estimate (mean mu, player is assumed to be of average skill) and confidence (standard deviation sigma).
    elo_mu = models.FloatField(default=settings.DEFAULT_MU)
    elo_sigma = models.FloatField(default=settings.DEFAULT_SIGMA)

    objects = BulkUpdateManager()

    # Stats that are too expensive to compute on the fly
    # see util.management.commands.update
    # Yes, it is trivially easy to get some of these through basic querysets. However, this allows us for a much
    # faster lookup at the expense of a very small amount of database space.
    active_event_winstreak = models.PositiveSmallIntegerField(default=0)
    longest_event_winstreak = models.PositiveSmallIntegerField(default=0)
    event_wins_count = models.PositiveSmallIntegerField(default=0)
    event_attended_count = models.PositiveSmallIntegerField(default=0)
    event_winrate = models.FloatField(default=0.0)

    match_wins_count = models.PositiveSmallIntegerField(default=0)
    match_losses_count = models.PositiveSmallIntegerField(default=0)
    match_ties_count = models.PositiveSmallIntegerField(default=0)
    match_winrate = models.FloatField(default=0.0)

    awards_count = models.PositiveSmallIntegerField(default=0)
    blue_banners_count = models.PositiveSmallIntegerField(default=0)

    def __str__(self):
        return "{0} ({1})".format(self.nickname, self.team_number)

    def get_matches(self, year=None) -> QuerySet:

        if year is None:
            return Match.objects.filter(
                alliances__teams__team_number=self.team_number)
        else:
            return Match.objects.filter(event__year=year).filter(
                alliances__teams__team_number=self.team_number)

    def get_wins(self, year=None) -> QuerySet:
        matches = Match.objects.prefetch_related('winner__teams')
        if year is None:
            return matches.filter(winner__teams__team_number=self.team_number)
        else:
            matches.select_related('event')
            return matches.filter(event__year=year).filter(
                winner__teams__team_number=self.team_number)

    def get_losses(self, year=None) -> QuerySet:
        matches = Match.objects.prefetch_related(
            'alliances__teams').select_related('winner')
        if year is None:
            return matches.filter(
                alliances__teams__team_number=self.team_number).exclude(
                    winner__teams__team_number=self.team_number).exclude(
                        winner__isnull=True)
        else:
            matches.select_related('event')
            return matches.filter(event__year=year).filter(
                alliances__teams__team_number=self.team_number).exclude(
                    winner__teams__team_number=self.team_number).exclude(
                        winner__isnull=True)

    def get_ties(self, year=None) -> QuerySet:
        matches = Match.objects.prefetch_related(
            'alliances__teams').select_related('winner')
        if year is None:
            return matches.filter(
                alliances__teams__team_number=self.team_number,
                winner__isnull=True)
        else:
            matches.select_related('event')
            return matches.filter(event__year=year) \
                .filter(alliances__teams__team_number=self.team_number, winner__isnull=True)

    def get_record(self) -> str:
        return "{0}-{1}-{2}".format(self.match_wins_count,
                                    self.match_losses_count,
                                    self.match_ties_count)

    def get_winrate(self) -> float:
        return self.match_winrate * 100.0

    def get_elo_standing(self) -> int:
        return Team.objects.filter(elo_mu__gte=self.elo_mu).count()

    def get_awards(self, year=None) -> QuerySet:
        if year is None:
            return Award.objects.filter(recipients=self)
        else:
            return Award.objects.filter(recipients=self, year=year)

    def count_awards_old(self) -> QuerySet:
        return Team.objects.filter(team_number=self.team_number).values_list('award__name'). \
            annotate(count=models.Count('award__award_type')).order_by('-count')

    def count_awards(self) -> Dict[str, List['Event']]:
        awards = {}
        award_types = set(
            self.award_set.values_list('award_type', flat=True).all())
        types_to_names = {t: Award.choice_to_display(t) for t in award_types}

        # get_events = lambda award_t: Event.objects.filter(award__award_type=award_t, award__recipients=self).values_list(flat=True)
        # This is great if the if statement in the below loop is not required...
        # awards = {types_to_names[t]: get_events(t) for t in award_types}

        for award_t in award_types:
            award = types_to_names[award_t]
            if award not in awards:
                awards[award] = Event.objects.filter(
                    award__award_type=award_t, award__recipients=self).all()

        awards = {k: v for k, v in awards.items() if len(v) > 0}
        return OrderedDict(
            sorted(awards.items(), key=lambda entry: -len(entry[1])))

    def get_max_opr(self) -> float:
        return self.rankingmodel_set.order_by('-tba_opr').first().tba_opr

    def to_dict(self) -> dict:
        return dict((name, getattr(self, name)) for name in self.__dict__
                    if not name.startswith('_'))
Example #18
0
 def test_char(self):
     field = SetCharField(models.CharField(max_length=5), max_length=32)
     assert field.description == "Set of String (up to %(max_length)s)"
Example #19
0
class Film(models.Model, ModelSerializationMixin):
    """
    CREATE TABLE film (
      film_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
      title VARCHAR(128) NOT NULL,
      description TEXT DEFAULT NULL,
      release_year YEAR DEFAULT NULL,
      language_id TINYINT UNSIGNED NOT NULL,
      original_language_id TINYINT UNSIGNED DEFAULT NULL,
      rental_duration TINYINT UNSIGNED NOT NULL DEFAULT 3,
      rental_rate DECIMAL(4,2) NOT NULL DEFAULT 4.99,
      length SMALLINT UNSIGNED DEFAULT NULL,
      replacement_cost DECIMAL(5,2) NOT NULL DEFAULT 19.99,
      rating ENUM('G','PG','PG-13','R','NC-17') DEFAULT 'G',
      special_features SET('Trailers','Commentaries','Deleted Scenes','Behind the Scenes') DEFAULT NULL,
      last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
      PRIMARY KEY  (film_id),
      KEY idx_title (title),
      KEY idx_fk_language_id (language_id),
      KEY idx_fk_original_language_id (original_language_id),
      CONSTRAINT fk_film_language FOREIGN KEY (language_id) REFERENCES language (language_id) ON DELETE RESTRICT ON UPDATE CASCADE,
      CONSTRAINT fk_film_language_original FOREIGN KEY (original_language_id) REFERENCES language (language_id) ON DELETE RESTRICT ON UPDATE CASCADE
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    # Django会自动为所有 models.ForeignKey 列创建索引
    """
    film_id = models.SmallAutoField(primary_key=True)
    title = models.CharField(max_length=128)
    description = models.TextField(null=True, default=None)

    YEAR_CHOICES = lambda : [(r, r) for r in range(1901, 2156)]
    release_year = models.PositiveSmallIntegerField(choices=YEAR_CHOICES() , null=True, default=None)
    language = models.ForeignKey(Language, on_delete=models.RESTRICT)
    original_language = models.ForeignKey(
        Language,
        on_delete=models.RESTRICT,
        related_name="original_film",
        null=True,
        default=None,
    )
    rental_duration = models.PositiveSmallIntegerField(default=3)
    rental_rate = models.DecimalField(max_digits=4, decimal_places=2, default='4.99')
    length = models.PositiveSmallIntegerField(null=True, default=None)
    replacement_cost = models.DecimalField(max_digits=5, decimal_places=2, default='19.99')
    class Rating(ChoiceEnum):
        G = 'G'
        R = 'R'
        PG = 'PG'
        PG_13 = 'PG-13'
        NC_17 = 'NC-17'
    rating = models.CharField(max_length=5, choices=Rating, default=Rating.G)

    class Special(ChoiceEnum):
        Trailers = 'Trailers'
        Commentaries = 'Commentaries'
        Deleted_Scenes = 'Deleted Scenes'
        Behind_the_Scenes = 'Behind the Scenes'

    """
    生成数据表后, 使用该语句修改字段类型即可符合表原型设计, 并且兼容SetCharField
        ALTER TABLE film
        MODIFY special_features 
        SET('Trailers','Commentaries','Deleted Scenes','Behind the Scenes') 
        DEFAULT NULL
        COLLATE utf8mb4_general_ci;
    设置字段的字符集排序的原因是
    Film.objects.filter(special_features__contains="trailers").update(
        special_features=SetF('special_features').add('Commentaries')
    )
    会触发以下报错:
    MySQLdb._exceptions.OperationalError: (1267, "Illegal mix of collations (utf8mb4_general_ci,IMPLICIT) and (utf8mb4_unicode_ci,IMPLICIT) for operation 'find_in_set'")
    因为字符集排序规则不一致导致.
    """
    special_features = SetCharField(
        base_field=models.CharField(max_length=20),
        size=4,
        max_length=83,  # 20*4+3个逗号, 这里是设置数据库该字段的最终长度
        choices=Special,  # 该设置在model层无效
        null=True,
        default=None,
        verbose_name="特殊功能"
    )
    actors = models.ManyToManyField(Actor, through='FilmActor', verbose_name='电影演员')
    last_update = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name = "电影表"
        verbose_name_plural = verbose_name
        db_table = "film"

        indexes = [models.Index(fields=['title'], name='idx_title')]
Example #20
0
 class InvalidSetCharFieldModel2(TemporaryModel):
     field = SetCharField(models.ForeignKey('testapp.Author'),
                          max_length=32)
Example #21
0
 def test_deconstruct(self):
     field = SetCharField(models.IntegerField(), max_length=32)
     name, path, args, kwargs = field.deconstruct()
     new = SetCharField(*args, **kwargs)
     assert new.base_field.__class__ == field.base_field.__class__
Example #22
0
 def test_model_field_formfield_size(self):
     model_field = SetCharField(models.IntegerField(), size=4)
     form_field = model_field.formfield()
     assert isinstance(form_field, SimpleSetField)
     assert form_field.max_length == 4
Example #23
0
 def test_model_field_formfield(self):
     model_field = SetCharField(models.CharField(max_length=27))
     form_field = model_field.formfield()
     assert isinstance(form_field, SimpleSetField)
     assert isinstance(form_field.base_field, forms.CharField)
     assert form_field.base_field.max_length == 27
Example #24
0
 def test_deconstruct_with_size(self):
     field = SetCharField(models.IntegerField(), size=3, max_length=32)
     name, path, args, kwargs = field.deconstruct()
     new = SetCharField(*args, **kwargs)
     assert new.size == field.size
Example #25
0
 class Invalid(models.Model):
     field = SetCharField(models.CharField(max_length=2), size=2)
Example #26
0
 def test_deconstruct_args(self):
     field = SetCharField(models.CharField(max_length=5), max_length=32)
     name, path, args, kwargs = field.deconstruct()
     new = SetCharField(*args, **kwargs)
     assert new.base_field.max_length == field.base_field.max_length
Example #27
0
class IntSetModel(Model):
    field = SetCharField(base_field=IntegerField(), size=5, max_length=32)
Example #28
0
 def test_int(self):
     field = SetCharField(models.IntegerField(), max_length=32)
     assert field.description == "Set of Integer"
Example #29
0
 class Invalid(models.Model):
     field = SetCharField(models.CharField(), max_length=32)
Example #30
0
 def test_model_field_formfield_size(self):
     model_field = SetCharField(models.IntegerField(), size=4)
     form_field = model_field.formfield()
     assert isinstance(form_field, SimpleSetField)
     assert form_field.max_length == 4
Example #31
0
 def test_deconstruct_with_size(self):
     field = SetCharField(models.IntegerField(), size=3, max_length=32)
     name, path, args, kwargs = field.deconstruct()
     new = SetCharField(*args, **kwargs)
     assert new.size == field.size