Модель 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 в поле модели.