首页 > 解决方案 > 如何使 char 字段的行为类似于 django 中的 URLField

问题描述

我正在使用 Django,我想要一个 URL 字段我知道 Django 中有一个 URLField 但我希望该字段是一个字符字段,并且我不希望用户在该字符字段中提交除 URL 之外的任何内容

看看我的models.py:

 class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    email = models.EmailField(max_length=500, blank=True, null=True)
    social_github = models.CharField(max_length=200, blank=True, null=True)
    social_twitter = models.CharField(max_length=200, blank=True, null=True)
    social_linkedin = models.CharField(max_length=200, blank=True, null=True)
    social_youtube = models.CharField(max_length=200, blank=True, null=True)
    social_website = models.CharField(max_length=200, blank=True, null=True)
    created = models.DateTimeField(auto_now_add=True)
    id = models.UUIDField(
        default=uuid.uuid4, unique=True, primary_key=True, editable=False)

    def __str__(self):
        return str(self.username)

请回答如何使 char 字段的行为类似于 URL 字段

标签: django

解决方案


AnURLField本质上只是CharField带有一些验证(以及默认名称(默认为 URL 的翻译)和最大长度为 200 的默认名称。事实上,如果我们查看源代码 [GitHub],我们会看到:

class URLField(CharField):
    default_validators = [validators.URLValidator()]
    description = _("URL")

    def __init__(self, verbose_name=None, name=None, **kwargs):
        kwargs.setdefault('max_length', 200)
        super().__init__(verbose_name, name, **kwargs)

    def deconstruct(self):
        name, path, args, kwargs = super().deconstruct()
        if kwargs.get("max_length") == 200:
            del kwargs['max_length']
        return name, path, args, kwargs

    def formfield(self, **kwargs):
        # As with CharField, this will cause URL validation to be performed
        # twice.
        return super().formfield(**{
            'form_class': forms.URLField,
            **kwargs,
        })

它还使用不同的表单域:URLFieldis [implemented [GitHub] as):

class URLField(CharField):
    widget = URLInput
    # …

因此它将使用一个URLInput小部件,但没有什么可以阻止您使用另一个小部件。事实上,我们可以通过以下方式实现模型:

class Profile(models.Model):
    # …
    social_github = models.URLField(blank=True, null=True)
    social_twitter = models.URLField(blank=True, null=True)
    social_linkedin = models.URLField(blank=True, null=True)
    social_youtube = models.URLField(blank=True, null=True)
    social_website = models.URLField(blank=True, null=True)
    # …

如果您想更改小部件,例如在 a 中ModelForm,您可以使用:

class MyProfileForm(forms.ModelForm):
    # …
    class Meta:
        # …
        widgets = {
            'social_github': forms.TextInput,
            'social_twitter': forms.TextInput,
            'social_linkedin': forms.TextInput,
            'social_youtube': forms.TextInput,
            'social_website': forms.TextInput
        }

推荐阅读