Модель django добавляет схему в поле url, если она не представлена

В моем проекте Django есть модель с полем URL. Я хочу обеспечить добавление схемы (например, https://) к URL, если она не существует.

from django.db import models
class MyModel(models.Model):
    url = models.URLField()

Я пробовал использовать методы clean, save, clean_fields, но ни один из них, похоже, не работает. Мне кажется, что должен существовать простой способ решения этой задачи, но я не могу его найти.

Любые предложения или лучшие практики будут высоко оценены.

Спасибо!

для решения этой проблемы я настоятельно рекомендую сделать функцию custome save для вашей модели, чтобы проверить, нет ли в ней https:// или http:// создать ее для нее


from django.db import models

class MyModel(models.Model):
    url = models.URLField()
    def save(self, *args, **kwargs):
       if not self.url.startswith("http://")):
            self.url = "http://" + self.url
       super().save(*args, **kwargs)

Одним из распространенных подходов является обработка данных на уровне формы или сериализатора, где вы можете предварительно обработать вводимые данные, прежде чем они пройдут проверку. Этот метод особенно полезен при работе с данными из форм или конечных точек API.

Пример форм

Пример сериализаторов

Если вы используете Django REST Framework:

from rest_framework import serializers
from .models import MyModel

class MyModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyModel
        fields = ['url']

    def validate_url(self, value):
        if not value.startswith(('http://', 'https://')):
            value = f'https://{value}'
        return value

Переопределение проверки модели

Другой подход заключается в непосредственном изменении механизма валидации модели путем переопределения метода clean, что позволяет манипулировать данными до запуска валидаторов поля.

from django.core.exceptions import ValidationError
from django.core.validators import URLValidator
from django.db import models

class MyModel(models.Model):
    url = models.URLField()

    def clean(self):
        if self.url and not self.url.startswith(('http://', 'https://')):
            self.url = f'https://{self.url}'
        
        # Manually validate the URL after modification
        validator = URLValidator()
        try:
            validator(self.url)
        except ValidationError:
            raise ValidationError({'url': 'Enter a valid URL.'})

Используйте метод сохранения модели

Хотя это не рекомендуется для целей проверки, в крайнем случае можно изменить данные в методе сохранения, особенно если URL не является критичным для немедленного использования (например, не используется в том же цикле запросов).

class MyModel(models.Model):
    url = models.URLField()

    def save(self, *args, **kwargs):
        if not self.url.startswith(('http://', 'https://')):
            self.url = f'https://{self.url}'
        super(MyModel, self).save(*args, **kwargs)

Однако помните, что использование сохранения для таких целей не соответствует лучшим практикам, поскольку в идеале проверка должна происходить до попадания в базу данных.

Я нашел решение своего вопроса, которое переопределяет to_internal_value метод URLField в сериализаторе, я понял, что я должен изменить данные в моем сериализаторе, а не в модели.

class CustomURLField(serializers.URLField):
    def to_internal_value(self, value):
        value = super().to_internal_value(value)
        if value and not (value.startswith('http://') or 
 value.startswith('https://')):
            value = 'https://' + value
        return value

class MyModelSerializer(serializers.ModelSerializer):
    url = CustomURLField()

    class Meta:
        model = MyModel
    fields = '__all__'

Если бы я не использовал Django REST Framework, я полагаю, что мне пришлось бы переопределить метод to_python в поле модели.

Вернуться на верх