Запрос к модели Django и сравнение ее полей на предмет сходства или близких дубликатов
У меня есть модель, которая записывает изменения других моделей в моей базе данных.
Я хотел бы запросить изменения, которые добавляют только символ новой строки -- \n.
Моя модель изменений выглядит следующим образом:
class Change(models.Model):
object_type = models.ForeignKey(
ContentType,
related_name="object_change_set",
on_delete=models.CASCADE,
)
object_id = models.CharField(max_length=255, db_index=True)
object = GenericForeignKey("object_type", "object_id")
old_fields = models.JSONField(encoder=JSONEncoder, null=True, blank=True)
new_fields = models.JSONField(encoder=JSONEncoder, null=True, blank=True)
По сути, я хочу найти случаи Change, где разница между значением ключа в old_fields и new_fields составляет \n.
Вот как выглядят new_fields:
{
"body": "Had a great time on Wednesday.",
"created": "2022-06-15T19:49:06.784Z",
}
И аналогично, old_fields:
{
"body": "Had a great time on Wednesday.\n",
"created": "2022-06-15T19:49:06.784Z",
}
Обратите внимание, что new_fields и old_fields оба являются JSONFields.
В конечном итоге, я хочу удалить экземпляры Change, которые только добавляют \n к body.
Я понимаю, что могу сделать это путем итерации по набору запросов и поиска этих расхождений, но мне интересно, есть ли более элегантное решение.
Вы можете использовать фильтры __startswith (вместе с выражением F()) и __endswith, чтобы проверить, начинается ли тело old_fields с тела new_fields и заканчивается ли оно :
from django.db.models import F
queryset = Change.objects.filter(
old_fields__body__startswith=F("new_fields__body"), old_fields__body__endswith="\n"
)
Однако это все равно будет соответствовать, если тело old_fields будет содержать любую строку между концом тела new_fields и завершающим переводом строки (например, "Had a great time on Wednesday.aaaaaaaaaaaaaaaaaa\n"). Чтобы исправить это, вы можете аннотировать набор запросов функцией Length и проверить, равна ли длина тела old_fields тела Length("new_fields__body") + 1:
from django.db.models import F
from django.db.models.functions import Length
queryset = Change.objects.annotate(old_body_len=Length("old_fields__body")).filter(
old_fields__body__startswith=F("new_fields__body"),
old_fields__body__endswith="\n",
old_body_len=Length("new_fields__body") + 1,
)
Это должно сработать!