Ejemplo n.º 1
0
    def _check_relation(self, obj, parent_model):
        # There's no FK, but we do need to confirm that the ct_field and ct_fk_field are valid,
        # and that they are part of a GenericForeignKey.

        gfks = [
            f for f in obj.model._meta.private_fields
            if isinstance(f, GenericForeignKey)
        ]
        if not gfks:
            return [
                checks.Error(
                    "'%s.%s' has no GenericForeignKey." %
                    (obj.model._meta.app_label, obj.model._meta.object_name),
                    obj=obj.__class__,
                    id='admin.E301')
            ]
        else:
            # Check that the ct_field and ct_fk_fields exist
            try:
                obj.model._meta.get_field(obj.ct_field)
            except FieldDoesNotExist:
                return [
                    checks.Error(
                        "'ct_field' references '%s', which is not a field on '%s.%s'."
                        % (obj.ct_field, obj.model._meta.app_label,
                           obj.model._meta.object_name),
                        obj=obj.__class__,
                        id='admin.E302')
                ]

            try:
                obj.model._meta.get_field(obj.ct_fk_field)
            except FieldDoesNotExist:
                return [
                    checks.Error(
                        "'ct_fk_field' references '%s', which is not a field on '%s.%s'."
                        % (obj.ct_fk_field, obj.model._meta.app_label,
                           obj.model._meta.object_name),
                        obj=obj.__class__,
                        id='admin.E303')
                ]

            # There's one or more GenericForeignKeys; make sure that one of them
            # uses the right ct_field and ct_fk_field.
            for gfk in gfks:
                if gfk.ct_field == obj.ct_field and gfk.fk_field == obj.ct_fk_field:
                    return []

            return [
                checks.Error(
                    "'%s.%s' has no GenericForeignKey using content type field '%s' and object ID field '%s'."
                    % (obj.model._meta.app_label, obj.model._meta.object_name,
                       obj.ct_field, obj.ct_fk_field),
                    obj=obj.__class__,
                    id='admin.E304')
            ]
Ejemplo n.º 2
0
    def check_field_type(self, field, field_type):
        """
        MySQL has the following field length restriction:
        No character (varchar) fields can have a length exceeding 255
        characters if they have a unique index on them.
        MySQL doesn't support a database index on some data types.
        """
        errors = []
        if (field_type.startswith('varchar') and field.unique
                and (field.max_length is None or int(field.max_length) > 255)):
            errors.append(
                checks.Error(
                    'MySQL does not allow unique CharFields to have a max_length > 255.',
                    obj=field,
                    id='mysql.E001',
                ))

        if field.db_index and field_type.lower(
        ) in self.connection._limited_data_types:
            errors.append(
                checks.Warning(
                    'MySQL does not support a database index on %s columns.' %
                    field_type,
                    hint=("An index won't be created. Silence this warning if "
                          "you don't care about it."),
                    obj=field,
                    id='fields.W162',
                ))
        return errors
Ejemplo n.º 3
0
    def test_pointing_to_swapped_model(self):
        class Replacement(models.Model):
            pass

        class SwappedModel(models.Model):
            content_type = models.ForeignKey(ContentType, models.CASCADE)
            object_id = models.PositiveIntegerField()
            content_object = GenericForeignKey()

            class Meta:
                swappable = 'TEST_SWAPPED_MODEL'

        class Model(models.Model):
            rel = GenericRelation('SwappedModel')

        self.assertEqual(Model.rel.field.check(), [
            checks.Error(
                "Field defines a relation with the model "
                "'contenttypes_tests.SwappedModel', "
                "which has been swapped out.",
                hint="Update the relation to point at 'settings.TEST_SWAPPED_MODEL'.",
                obj=Model.rel.field,
                id='fields.E301',
            )
        ])
Ejemplo n.º 4
0
 def _check_content_type_field(self):
     """
     Check if field named `field_name` in model `model` exists and is a
     valid content_type field (is a ForeignKey to ContentType).
     """
     try:
         field = self.model._meta.get_field(self.ct_field)
     except FieldDoesNotExist:
         return [
             checks.Error(
                 "The GenericForeignKey content type references the "
                 "nonexistent field '%s.%s'." %
                 (self.model._meta.object_name, self.ct_field),
                 obj=self,
                 id='contenttypes.E002',
             )
         ]
     else:
         if not isinstance(field, models.ForeignKey):
             return [
                 checks.Error(
                     "'%s.%s' is not a ForeignKey." %
                     (self.model._meta.object_name, self.ct_field),
                     hint=
                     ("GenericForeignKeys must use a ForeignKey to "
                      "'contenttypes.ContentType' as the 'content_type' field."
                      ),
                     obj=self,
                     id='contenttypes.E003',
                 )
             ]
         elif field.remote_field.model != ContentType:
             return [
                 checks.Error(
                     "'%s.%s' is not a ForeignKey to 'contenttypes.ContentType'."
                     % (self.model._meta.object_name, self.ct_field),
                     hint=
                     ("GenericForeignKeys must use a ForeignKey to "
                      "'contenttypes.ContentType' as the 'content_type' field."
                      ),
                     obj=self,
                     id='contenttypes.E004',
                 )
             ]
         else:
             return []
Ejemplo n.º 5
0
 def test_model_name_too_long(self):
     model = type('A' * 101, (models.Model,), {'__module__': self.__module__})
     self.assertEqual(check_model_name_lengths(self.apps.get_app_configs()), [
         checks.Error(
             'Model names must be at most 100 characters (got 101).',
             obj=model,
             id='contenttypes.E005',
         )
     ])
Ejemplo n.º 6
0
 def check(self, **kwargs):
     errors = super().check(**kwargs)
     if self.base_field.remote_field:
         errors.append(
             checks.Error('Base field for array cannot be a related field.',
                          obj=self,
                          id='postgres.E002'))
     else:
         # Remove the field name checks as they are not needed here.
         base_errors = self.base_field.check()
         if base_errors:
             messages = '\n    '.join('%s (%s)' % (error.msg, error.id)
                                      for error in base_errors)
             errors.append(
                 checks.Error('Base field for array has errors:\n    %s' %
                              messages,
                              obj=self,
                              id='postgres.E001'))
     return errors
Ejemplo n.º 7
0
 def _check_primary_key(self):
     if self._primary_key_set_explicitly:
         return [
             checks.Error(
                 "'primary_key' is not a valid argument for a %s." % self.__class__.__name__,
                 obj=self,
                 id='fields.E201',
             )
         ]
     else:
         return []
Ejemplo n.º 8
0
 def _check_field_name(self):
     if self.name.endswith("_"):
         return [
             checks.Error(
                 'Field names must not end with an underscore.',
                 obj=self,
                 id='fields.E001',
             )
         ]
     else:
         return []
Ejemplo n.º 9
0
    def test_pointing_to_missing_model(self):
        class Model(models.Model):
            rel = GenericRelation('MissingModel')

        self.assertEqual(Model.rel.field.check(), [
            checks.Error(
                "Field defines a relation with model 'MissingModel', "
                "which is either not installed, or is abstract.",
                obj=Model.rel.field,
                id='fields.E300',
            )
        ])
Ejemplo n.º 10
0
 def _check_upload_to(self):
     if isinstance(self.upload_to, str) and self.upload_to.startswith('/'):
         return [
             checks.Error(
                 "%s's 'upload_to' argument must be a relative path, not an "
                 "absolute path." % self.__class__.__name__,
                 obj=self,
                 id='fields.E202',
                 hint='Remove the leading slash.',
             )
         ]
     else:
         return []
Ejemplo n.º 11
0
    def test_field_name_ending_with_underscore(self):
        class Model(models.Model):
            content_type = models.ForeignKey(ContentType, models.CASCADE)
            object_id = models.PositiveIntegerField()
            content_object_ = GenericForeignKey('content_type', 'object_id')

        self.assertEqual(Model.content_object_.check(), [
            checks.Error(
                'Field names must not end with an underscore.',
                obj=Model.content_object_,
                id='fields.E001',
            )
        ])
Ejemplo n.º 12
0
 def _check_object_id_field(self):
     try:
         self.model._meta.get_field(self.fk_field)
     except FieldDoesNotExist:
         return [
             checks.Error(
                 "The GenericForeignKey object ID references the "
                 "nonexistent field '%s'." % self.fk_field,
                 obj=self,
                 id='contenttypes.E001',
             )
         ]
     else:
         return []
Ejemplo n.º 13
0
    def test_invalid_name(self):
        class InvalidArticle(models.Model):
            on_site = CurrentSiteManager("places_this_article_should_appear")

        errors = InvalidArticle.check()
        expected = [
            checks.Error(
                "CurrentSiteManager could not find a field named "
                "'places_this_article_should_appear'.",
                obj=InvalidArticle.on_site,
                id='sites.E001',
            )
        ]
        self.assertEqual(errors, expected)
Ejemplo n.º 14
0
    def test_missing_object_id_field(self):
        class TaggedItem(models.Model):
            content_type = models.ForeignKey(ContentType, models.CASCADE)
            # missing object_id field
            content_object = GenericForeignKey()

        self.assertEqual(TaggedItem.content_object.check(), [
            checks.Error(
                "The GenericForeignKey object ID references the nonexistent "
                "field 'object_id'.",
                obj=TaggedItem.content_object,
                id='contenttypes.E001',
            )
        ])
Ejemplo n.º 15
0
    def test_CommaSeparatedIntegerField_deprecated(self):
        class CommaSeparatedIntegerModel(models.Model):
            csi = models.CommaSeparatedIntegerField(max_length=64)

        model = CommaSeparatedIntegerModel()
        self.assertEqual(
            model.check(),
            [checks.Error(
                'CommaSeparatedIntegerField is removed except for support in '
                'historical migrations.',
                hint='Use CharField(validators=[validate_comma_separated_integer_list]) instead.',
                obj=CommaSeparatedIntegerModel._meta.get_field('csi'),
                id='fields.E901',
            )],
        )
Ejemplo n.º 16
0
    def test_IPAddressField_deprecated(self):
        class IPAddressModel(models.Model):
            ip = models.IPAddressField()

        model = IPAddressModel()
        self.assertEqual(
            model.check(),
            [checks.Error(
                'IPAddressField has been removed except for support in '
                'historical migrations.',
                hint='Use GenericIPAddressField instead.',
                obj=IPAddressModel._meta.get_field('ip'),
                id='fields.E900',
            )],
        )
Ejemplo n.º 17
0
 def _check_image_library_installed(self):
     try:
         from PIL import Image  # NOQA
     except ImportError:
         return [
             checks.Error(
                 'Cannot use ImageField because Pillow is not installed.',
                 hint=('Get Pillow at https://pypi.org/project/Pillow/ '
                       'or run command "pip install Pillow".'),
                 obj=self,
                 id='fields.E210',
             )
         ]
     else:
         return []
Ejemplo n.º 18
0
    def test_new_fields(self):
        class NoNewFields(Person):
            newfield = models.BooleanField()

            class Meta:
                proxy = True

        errors = NoNewFields.check()
        expected = [
            checks.Error(
                "Proxy model 'NoNewFields' contains model fields.",
                id='models.E017',
            )
        ]
        self.assertEqual(errors, expected)
Ejemplo n.º 19
0
    def test_missing_content_type_field(self):
        class TaggedItem(models.Model):
            # no content_type field
            object_id = models.PositiveIntegerField()
            content_object = GenericForeignKey()

        expected = [
            checks.Error(
                "The GenericForeignKey content type references the nonexistent "
                "field 'TaggedItem.content_type'.",
                obj=TaggedItem.content_object,
                id='contenttypes.E002',
            )
        ]
        self.assertEqual(TaggedItem.content_object.check(), expected)
Ejemplo n.º 20
0
    def test_default_details(self):
        class MyField(models.Field):
            system_check_removed_details = {}

        class Model(models.Model):
            name = MyField()

        model = Model()
        self.assertEqual(model.check(), [
            checks.Error(
                msg=
                'MyField has been removed except for support in historical migrations.',
                obj=Model._meta.get_field('name'),
                id='fields.EXXX',
            )
        ])
Ejemplo n.º 21
0
    def test_field_name_ending_with_underscore(self):
        class TaggedItem(models.Model):
            content_type = models.ForeignKey(ContentType, models.CASCADE)
            object_id = models.PositiveIntegerField()
            content_object = GenericForeignKey()

        class InvalidBookmark(models.Model):
            tags_ = GenericRelation('TaggedItem')

        self.assertEqual(InvalidBookmark.tags_.field.check(), [
            checks.Error(
                'Field names must not end with an underscore.',
                obj=InvalidBookmark.tags_.field,
                id='fields.E001',
            )
        ])
Ejemplo n.º 22
0
    def test_invalid_field_type(self):

        class ConfusedArticle(models.Model):
            site = models.IntegerField()
            on_site = CurrentSiteManager()

        errors = ConfusedArticle.check()
        expected = [
            checks.Error(
                "CurrentSiteManager cannot use 'ConfusedArticle.site' as it is "
                "not a foreign key or a many-to-many field.",
                obj=ConfusedArticle.on_site,
                id='sites.E002',
            )
        ]
        self.assertEqual(errors, expected)
Ejemplo n.º 23
0
    def test_content_type_field_pointing_to_wrong_model(self):
        class Model(models.Model):
            content_type = models.ForeignKey('self', models.CASCADE)  # should point to ContentType
            object_id = models.PositiveIntegerField()
            content_object = GenericForeignKey('content_type', 'object_id')

        self.assertEqual(Model.content_object.check(), [
            checks.Error(
                "'Model.content_type' is not a ForeignKey to 'contenttypes.ContentType'.",
                hint=(
                    "GenericForeignKeys must use a ForeignKey to "
                    "'contenttypes.ContentType' as the 'content_type' field."
                ),
                obj=Model.content_object,
                id='contenttypes.E004',
            )
        ])
Ejemplo n.º 24
0
    def test_invalid_content_type_field(self):
        class Model(models.Model):
            content_type = models.IntegerField()  # should be ForeignKey
            object_id = models.PositiveIntegerField()
            content_object = GenericForeignKey('content_type', 'object_id')

        self.assertEqual(Model.content_object.check(), [
            checks.Error(
                "'Model.content_type' is not a ForeignKey.",
                hint=(
                    "GenericForeignKeys must use a ForeignKey to "
                    "'contenttypes.ContentType' as the 'content_type' field."
                ),
                obj=Model.content_object,
                id='contenttypes.E003',
            )
        ])
Ejemplo n.º 25
0
    def test_missing_generic_foreign_key(self):
        class TaggedItem(models.Model):
            content_type = models.ForeignKey(ContentType, models.CASCADE)
            object_id = models.PositiveIntegerField()

        class Bookmark(models.Model):
            tags = GenericRelation('TaggedItem')

        self.assertEqual(Bookmark.tags.field.check(), [
            checks.Error(
                "The GenericRelation defines a relation with the model "
                "'contenttypes_tests.TaggedItem', but that model does not have a "
                "GenericForeignKey.",
                obj=Bookmark.tags.field,
                id='contenttypes.E004',
            )
        ])
Ejemplo n.º 26
0
    def test_user_specified_details(self):
        class MyField(models.Field):
            system_check_removed_details = {
                'msg': 'Support for this field is gone.',
                'hint': 'Use something else.',
                'id': 'fields.E999',
            }

        class Model(models.Model):
            name = MyField()

        model = Model()
        self.assertEqual(model.check(), [
            checks.Error(
                msg='Support for this field is gone.',
                hint='Use something else.',
                obj=Model._meta.get_field('name'),
                id='fields.E999',
            )
        ])
Ejemplo n.º 27
0
 def _check_generic_foreign_key_existence(self):
     target = self.remote_field.model
     if isinstance(target, ModelBase):
         fields = target._meta.private_fields
         if any(
                 self._is_matching_generic_foreign_key(field)
                 for field in fields):
             return []
         else:
             return [
                 checks.Error(
                     "The GenericRelation defines a relation with the model "
                     "'%s.%s', but that model does not have a GenericForeignKey."
                     % (target._meta.app_label, target._meta.object_name),
                     obj=self,
                     id='contenttypes.E004',
                 )
             ]
     else:
         return []