0

Каждая запись временного диапазона TimeClass зависит друг от друга.зависимая проверка нескольких объектов в django admin

Они не могут пересекаться и start_time < end_time.

models.py

class Xyz(models.Model): 
    ... 

class TimeRangeClass(models.Model) 
    start_time = models.TimeField() 
    end_time = models.TimeField() 
    xyz = models.ForeignKey(Xyz) 
    # other fields here 

    def clean(self): 
     # Here I loop through TimeRangeClass.objects.all() and 
     # check for conflicts through my custom "my_validator_method". 
     # If there is a conflict I throw an error 
     #(I've since modified it to just be one single query as per Titusz advice)    
     for each in TimeRangeClass.objects.filter(xyz=self.xyz).exclude(id=self.id): 
      my_validator_method(start_time1=self.start_time, 
           end_time1=self.end_time, 
           start_time2=each.start_time, 
           end_time2=each.end_time) 

admin.py

from .models import TimeRangeClass, Xyz 
class TimeRangeClassInLine(admin.TabularInline): 
    model = TimeRangeClass 
    extra = 3 

@admin.register(Xyz) 
class Xyz(admin.ModelAdmin): 
    exclude = [] 
    inlines = [TimeRangeClassInLine] 

Проблема: Я могу редактировать/добавить несколько TimeRangeClass с полуслова через администратора. Но, учитывая, что модели. Метод очистки модели только оценивает 1 изменение за раз, я не могу проверять несколько изменений друг против друга.

Пример:

  1. сохранить entry1 & entry2 без конфликта

  2. Изменение entry2 для получения ошибки проверки

  3. Adjust entry1 (вместо # 2), чтобы они не перекрывали друг друга

  4. Это не регистрируется, потому что ни одно изменение не записано на th e db.

Я ищу обходное решение.

+0

Вы должны дать более конкретное объяснение проблемы. Где/Как вы меняете запись №2? Из интерфейса администратора, из вида или формы? – Titusz

ответ

1

Некоторые советы по проблеме:

Вы не должны перебрать всю таблицу при проверке перекрывающихся строк. Просто фильтр для проблемных строк ... что-то вроде:

overlaps = TimeRangeClass.objects.filter(
    Q(start_time__gte=self.start_time, start_time__lt=self.end_time) | 
    Q(end_time__gt=self.start_time, end_time__lte=self.end_time) 
) 

overlaps теперь QuerySet, который оценивает, когда вы итерацию над ней, и возвращает только конфликтующие объекты.

Если вы используете Django с postgres, вы должны зарегистрироваться https://docs.djangoproject.com/es/1.9/ref/contrib/postgres/fields/#datetimerangefield.

Как только у вас возникнут конфликтующие объекты, вы сможете изменить время начала и окончания функции и сохранить изменения. Model.save() не будет автоматически вызывать метод model.clean(). Но имейте в виду, что если вы сохраните объект из администратора Django, то будет вызвать метод model.clean() перед сохранением.

Так что-то вроде этого:

def clean(): 
    overlaps = TimeRangeClass.overlaps.for_trc(self) 
    for trc_object in overlaps: 
     fixed_object = fix_start_end(trc_object, self) 
     fixed_object.save() 

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

def clean(): 
    with transaction.atomic(): 
     # do your multi object magic here ... 

Update на осветленной вопрос:

Если вы хотите, чтобы подтвердить или данные предварительного/процесса, который происходит от администратора инлайн вы должны подключить в соответствующем ModelAdmin метода (ов).Есть несколько способов приблизиться к этому. Я думаю, проще всего было бы переопределить ModelAdmin.save_fromset. Здесь у вас есть доступ ко всем встроенным формам, прежде чем они будут сохранены.

+0

Благодарим вас за рекомендацию использовать Q() вместо того, чтобы перебирать запрос. Я не уверен, почему я решил зациклиться в этом случае, поскольку в других случаях я использую аналогичный запрос. – Maxim

+0

Я кратко рассмотрел документацию для transaction.atomic(). Позволит ли я сравнить еще не сохраненные переменные для чистого метода? – Maxim

+0

Что вы подразумеваете под еще не сохраненными переменными? Откуда бы ваши * еще не сохраненные переменные? Вы сравниваете новый, в конечном итоге, несохраненный экземпляр TimeRangeClass с существующими инстанциями, которые вы загрузили в память через ваш запрос. – Titusz

Смежные вопросы