Home > database >  ValueError: Could not find function validator when calling makemigrations in Django 4.0
ValueError: Could not find function validator when calling makemigrations in Django 4.0

Time:04-02

Using the solution here to validate URLField, I am getting ValueError when I run python manage.py makemigrations and I'm not sure why. What am I doing wrong?

from django.contrib.auth.models import User
from django.db import models
from django.core.exceptions import ValidationError

from urllib.parse import urlparse


def validate_hostname(*hostnames):
    hostnames = set(hostnames)
    def validator(value):
        try:
            result = urlparse(value)
            if result.hostname not in hostnames:
                raise ValidationError(f'The hostname {result.hostname} is not allowed.')
        except ValueError:
            raise ValidationError('Invalid URL')
    return validator

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.SET_NULL, null=True)
    twitter = models.URLField(
        blank=True,
        null=True,
        validators=[validate_hostname('twitter.com', 'www.twitter.com')]
    )

Traceback

$ python manage.py makemigrations

Migrations for 'userprofiles':
  userprofiles/migrations/0002_userprofile_twitter.py
    - Add field twitter to userprofile
Traceback (most recent call last):
  File "/home/master/github/mywebsite/src/manage.py", line 22, in <module>
    main()
  File "/home/master/github/mywebsite/src/manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "/home/master/.cache/pypoetry/virtualenvs/mywebsite-WMQVlvmt-py3.10/lib/python3.10/site-packages/django/core/management/__init__.py", line 446, in execute_from_command_line
    utility.execute()
  File "/home/master/.cache/pypoetry/virtualenvs/mywebsite-WMQVlvmt-py3.10/lib/python3.10/site-packages/django/core/management/__init__.py", line 440, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/master/.cache/pypoetry/virtualenvs/mywebsite-WMQVlvmt-py3.10/lib/python3.10/site-packages/django/core/management/base.py", line 414, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/home/master/.cache/pypoetry/virtualenvs/mywebsite-WMQVlvmt-py3.10/lib/python3.10/site-packages/django/core/management/base.py", line 460, in execute
    output = self.handle(*args, **options)
  File "/home/master/.cache/pypoetry/virtualenvs/mywebsite-WMQVlvmt-py3.10/lib/python3.10/site-packages/django/core/management/base.py", line 98, in wrapped
    res = handle_func(*args, **kwargs)
  File "/home/master/.cache/pypoetry/virtualenvs/mywebsite-WMQVlvmt-py3.10/lib/python3.10/site-packages/django/core/management/commands/makemigrations.py", line 214, in handle
    self.write_migration_files(changes)
  File "/home/master/.cache/pypoetry/virtualenvs/mywebsite-WMQVlvmt-py3.10/lib/python3.10/site-packages/django/core/management/commands/makemigrations.py", line 255, in write_migration_files
    migration_string = writer.as_string()
  File "/home/master/.cache/pypoetry/virtualenvs/mywebsite-WMQVlvmt-py3.10/lib/python3.10/site-packages/django/db/migrations/writer.py", line 141, in as_string
    operation_string, operation_imports = OperationWriter(operation).serialize()
  File "/home/master/.cache/pypoetry/virtualenvs/mywebsite-WMQVlvmt-py3.10/lib/python3.10/site-packages/django/db/migrations/writer.py", line 99, in serialize
    _write(arg_name, arg_value)
  File "/home/master/.cache/pypoetry/virtualenvs/mywebsite-WMQVlvmt-py3.10/lib/python3.10/site-packages/django/db/migrations/writer.py", line 63, in _write
    arg_string, arg_imports = MigrationWriter.serialize(_arg_value)
  File "/home/master/.cache/pypoetry/virtualenvs/mywebsite-WMQVlvmt-py3.10/lib/python3.10/site-packages/django/db/migrations/writer.py", line 282, in serialize
    return serializer_factory(value).serialize()
  File "/home/master/.cache/pypoetry/virtualenvs/mywebsite-WMQVlvmt-py3.10/lib/python3.10/site-packages/django/db/migrations/serializer.py", line 216, in serialize
    return self.serialize_deconstructed(path, args, kwargs)
  File "/home/master/.cache/pypoetry/virtualenvs/mywebsite-WMQVlvmt-py3.10/lib/python3.10/site-packages/django/db/migrations/serializer.py", line 94, in serialize_deconstructed
    arg_string, arg_imports = serializer_factory(arg).serialize()
  File "/home/master/.cache/pypoetry/virtualenvs/mywebsite-WMQVlvmt-py3.10/lib/python3.10/site-packages/django/db/migrations/serializer.py", line 43, in serialize
    item_string, item_imports = serializer_factory(item).serialize()
  File "/home/master/.cache/pypoetry/virtualenvs/mywebsite-WMQVlvmt-py3.10/lib/python3.10/site-packages/django/db/migrations/serializer.py", line 172, in serialize
    raise ValueError(
ValueError: Could not find function validator in userprofiles.models.

CodePudding user response:

If you look at your validate_hostname function it has an inner function called validator which you are trying to return. hence this error: ValueError: Could not find function validator in userprofiles.models.

This code snippet should work:

from django.contrib.auth.models import User
from django.db import models
from django.core.exceptions import ValidationError



HOST_NAMES = ['twitter.com', 'www.twitter.com']
def validate_hostname(entered_hostname):
    if entered_hostname in HOST_NAMES:
        return entered_hostname
    else:
        raise ValidationError(f'The hostname {entered_hostname} is not allowed.')
   

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.SET_NULL, null=True)
    twitter = models.URLField(
        blank=True,
        null=True,
        validators=[validate_hostname]
    )

You can modify this by using urlparse in validate_hostname function

CodePudding user response:

You are doing return validator however validator is a function. Try return validator(hostnames) perhaps, or whatever argument you need to give to your function.

  • Related