Правильный способ проверки объектов модели Django?

Я все еще пытаюсь понять, как правильно проверить объект модели Django, используя специальный валидатор на уровне модели. Я знаю, что проверка обычно выполняется в форме или модели. Тем не менее, я хочу обеспечить целостность моих данных на уровне модели, если яЯ взаимодействую с ним через ORM в оболочке Python. Вот'Мой текущий подход:

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


def validate_gender(value):
    """ Custom validator """
    if not value in ('m', 'f', 'M', 'F'):
        raise ValidationError(u'%s is not a valid value for gender.' % value)


class Person(models.Model):
    name = models.CharField(max_length=128)
    age = models.IntegerField()
    gender = models.CharField(maxlength=1, validators=[validate_gender])

    def save(self, *args, **kwargs):
        """ Override Person's save """
        self.full_clean(exclude=None)
        super(Person, self).save(*args, **kwargs)

Вот мои вопросы:

Должен ли я создать пользовательскую функцию проверки, назначить ее в качестве валидатора, а затем переопределить Person 's сохранить () функцию как яВы сделали выше? (Кстати, я знаю, что мог бы подтвердить свой гендерный выбор, используявыбор вариант поля, но я создалvalidate_gender» с целью иллюстрации).

Если ядействительно Хотите обеспечить целостность своих данных, должен ли я писать не только модульные тесты Django для тестирования на уровне модели, но также эквивалентные модульные тесты уровня базы данных с использованием Python / Psycopg? Я'мы заметили, что модульные тесты Django, которые вызывают ValidationErrors, только тестируют модель 'понимание схемы базы данных с использованием копии базы данных. Даже если бы я использовал Юг для миграций, любые ограничения на уровне базы данных ограничиваются тем, что Django может понять и преобразовать в ограничение Postgres. Если мне нужно пользовательское ограничение, которое Джанго может 'Я могу ввести данные в свою базу данных, которые нарушают это ограничение, если яm взаимодействует с базой данных напрямую через терминал psql.

Спасибо! Я

 Alasdair23 окт. 2012 г., 22:30
Я не уверен, насколько вопрос 1 отличается от ваших предыдущих вопросов по этой теме. Обратите внимание, что это все еще неПредотвратить вставку неверных данных с помощью ORM. Рассматривать .Person.objects.update(gender='a')
 Jim25 окт. 2012 г., 00:12
Вы правы, за исключением того, что в моем предыдущем вопросе я неЯ включил пользовательскую функцию проверки, как я сделал здесь. Что касается вашего другого наблюдения по поводу .update, я думаю, что теперь у меня есть дополнительная проблема, которая добавляет мне путаницу. Я'я действительно борюсь с пониманием того, чтоэто правильный способ сделать это. Хотя документы по Django довольно хорошие, ИМХО, онидолго на фрагментах и "ручной размахивая» но коротко о полных примерах, которые могли бы помочь "Newb» Как и я, я понимаю, как правильно решить эту проблему. К сожалению, я работаю один и неу меня есть более опытные разработчики, чтобы обсудить это.

Ответы на вопрос(1)

Решение Вопроса

1) Нет, нет поставитьself.full_clean() Внутриsave, Или

А) использоватьModelForm (что приведет к тому, что произойдет все та же проверка - примечание:ModelForm.is_valid() победил'т звонокModel.full_clean явно, но будет выполнять те же проверки, что иModel.full_clean). Пример:

class PersonForm(forms.ModelForm):
    class Meta:
        model = Person

def add_person(request):
    if request.method == 'POST':
        form = PersonForm(request.POST, request.FILES)
        if form.is_valid():  # Performs your validation, including ``validate_gender``
            person = form.save()
            return redirect('some-other-view')
    else:
        form = PersonForm()
        # ... return response with ``form`` in the context for rendering in a template

Также обратите внимание, формы не 'для использования только в представлениях, которые отображают их в шаблонах - ониотлично подходит для любого использования, в том числе API и т. д. После запускаform.is_valid() и получать ошибки, выбудет иметьform.errors это словарь, содержащий все ошибки в форме, включая ключ'__all__' который будет содержать неполевые ошибки.

Б) Просто используйтеmodel_instance.full_clean() с вашей точки зрения (или другого уровня логического приложения), вместо использования формы, но формы - хорошая абстракция для этого.

2) я неу меня действительно есть решение, но яЯ никогда не сталкивался с такой проблемой, даже в больших проектах (текущий проект, в котором я работаю с моей компанией, имеет 146 таблиц), и я нене подозреваю этоВ вашем случае это тоже будет проблемой.

 rgenito23 июл. 2016 г., 05:40
Вы сказали либо А) сделать это, и что такое вариант Б?
 orokusaki29 окт. 2012 г., 02:30
@RobertF. - тот'правильно.ModelForm class - достойная абстракция для проверки модели, будь то обновление или создание экземпляров, даже если вы нене предназначены для отображения формы в шаблоне.
 chefarov10 июл. 2018 г., 22:24
Б) Вы имеете в виду, например,?model_instance = Person('Natalie'); model_instance.full_clean(); model_instance.save();
 orokusaki10 июл. 2018 г., 22:26
@chefarov да, кроме точки с запятой (неиспользовать их в Python), а также вам понадобится, например,Person(name=‘Natalie’) (против простой передачи имени в качестве упорядоченного аргумента).
 Jim25 окт. 2012 г., 00:14
Вы говорите, что мне следует использовать форму или форму модели для проверки моих моделей данных, даже если яя не представляю объект модели в фактической форме шаблона пользователю? Благодарю.

Ваш ответ на вопрос