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.