-2

Are they typed in below same?

The first code which defines fields in class attribute section is recommended by django documents

class Musician(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    instrument = models.CharField(max_length=100)

The second code which I want to use defines fields in init function.

class Musician(models.Model):
    def __init__(self, *args, **kwargs):
        first_name = models.CharField(max_length=50)
        last_name = models.CharField(max_length=50)
        instrument = models.CharField(max_length=100)
        super().__init__(*args, **kwargs)

I want to use second codes when I define classmethod in Model to define functions validateing fields like below.

class HyperLinks(model.Model):
    def __init__(self, *args, **kwargs):
        self.links = models.JSONField(default=[], validators=[self.validate_links])
        super().__init__(*args, **kwargs)

    @staticmethod
    def validate_links(data):
        """
        example
        links = [("github", "https://github.com/yeop-sang"), ("homepage", "http://yeop.kr")]
        """
        if type(data) is not list:
            raise ValidationError(
                'links should be list'
            )
        for datum in data:
            if type(datum) is not tuple:
                raise ValidationError(
                    'links should be list contained tuple'
                )
            if len(datum) is not 2:
                raise ValidationError(
                    'link should be contain type and link'
                )
            if not (type(datum[0]) is str or type(datum[1]) is str):
                raise ValidationError(
                    'link and type should be string'
                )
yeop
  • 29
  • 7
  • 2
    No, follow the docs’ recommended structure and create your own validator https://docs.djangoproject.com/en/4.0/ref/validators/ – 0sVoid Aug 03 '22 at 08:44
  • I want to define my validator in related Model class. And I read the doc and it just was written how to write validation functions. Umm... I think I should write validate_links more detail. – yeop Aug 03 '22 at 09:02

1 Answers1

0

The Second code in my question won't work.

I found similar questions, Storing Variables in Python Class, Attributes initialization/declaration in Python class: where to place them?

According to above questions, class attributes cannot be shared by __dict__ function.

class A(object):
    foo = None
class B(object):
   def __init__(self):
       self.foo = None

A.__dict__
# result
# mappingproxy({'__module__': '__main__', 'foo': None, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None})
B.__dict__
# result
# mappingproxy({'__module__': '__main__', '__init__': <function B.__init__ at 0x110805790>, '__dict__': <attribute '__dict__' of 'B' objects>, '__weakref__': <attribute '__weakref__' of 'B' objects>, '__doc__': None})

There is differences which django library call models. Therefore, when we define models, we must avoid define attributes in __init__ functions. That makes unexpected errors.

Especially, in django Migration Section, the django cannot recognize fields, then it won't create columns or delete your columns. And in objects.create(), the column names.

Then, how about declare the function in front of assigning field attributes like below?

class HyperLinks(models.Model):
    @staticmethod
    def validate_links(data):
        """
        example
        links = [("github", "https://github.com/yeop-sang"), ("homepage", "http://yeop.kr")]
        """
        if type(data) is not list:
            raise ValidationError(
                'links should be list'
            )
        for datum in data:
            if type(datum) is not tuple:
                raise ValidationError(
                    'links should be list contained tuple'
                )
            if len(datum) is not 2:
                raise ValidationError(
                    'link should be contain type and link'
                )
            if not (type(datum[0]) is str and type(datum[1]) is str):
                raise ValidationError(
                    'link and type should be string'
                )

    links = models.JSONField(default=[], validators=[validate_links])

There is an Exception TypeError: 'staticmethod' object is not callable. (Related link).

To fix it, I can change last line like links = models.JSONField(default=[], validators=[validate_links.__get__(object)])

Eventually, to validate fields, the best way is create the functions separated from Model class which recommended by django docs and @0sVoid.

yeop
  • 29
  • 7