Лучший способ сделать несколько save () в одном представлении в Django - PullRequest
0 голосов
/ 16 сентября 2018

Я новичок в Django, и на самом деле веб-разработки.Некоторое время искал, но пока не получил ответа.

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

В настоящее время у меня есть две модели:

  1. Запрос

    class Request(models.Model):
        create_time = models.DateTimeField('create time', auto_now_add=True)
        user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET('unknown'))
        image_name = models.CharField(max_length=48)
        image = models.ForeignKey(Image, on_delete=models.SET('unknown'))
    
  2. Изображение

    class Image(models.Model):
        add_time = models.DateTimeField('add time', auto_now_add=True)
        image_source = models.CharField(max_length=48)
        image_size = models.CharField(max_length=48)
    

Просто хотел знать, как лучше всего сохранить () в моделях при отправке запроса.Подходы, о которых я думаю:

Вариант A:

  1. Когда запрос получен, сохраните () для запроса модели с базовой информацией - кроме «Идентификатор изображения» (этопока недоступно) и установите статус «Запущено»
  2. Выполните поиск и загрузите изображения, а затем сохраните () в модели изображений - теперь у меня есть «Идентификатор изображения»
  3. Обновите экземпляр запроса с информацией об «Идентификаторе изображения» и измените статус на «успех»

Опция B:

  1. Поиск и загрузка изображенийсразу после получения запроса и сохранения () в модель изображения - теперь у меня есть «Идентификатор изображения»

  2. Сохранить () в модель запроса с «Идентификатором изображения» -это новая операция вставки.

Какой лучший способ сделать это?Или есть другие лучшие способы сделать это?

Кроме того, есть ли какие-либо предложения использовать функцию «транзакции» в Django для такого сценария?Я не предпочитаю это для своего маленького проекта - просто не хочу усложнять его.

1 Ответ

0 голосов
/ 16 сентября 2018

Я бы выбрал вариант А, и я настоятельно рекомендую переименовать модель «Запрос» в нечто иное, например: «SearchRequest» Request является чем-то очень специфичным в мире django и если вы добавите в него новый контекст, вы скоро очень запутаетесь.

Когда срабатывает SearchRequest, вы можете сохранить время создания, статус в STARTED и затем выполнить исследование. Что-то может пойти не так во время исследования, поэтому лучше, если вы включите поиск изображений в попытке / за исключением. Затем вы можете сохранить статус с помощью FAILED и указать причину, если что-то пойдет не так. Это ответ на вопрос об атомарной транзакции, вам не нужно .

Еще одно предложение, переместите имя изображения в модель изображения, SearchRequest может получить имя изображения из связанных изображений.

Улучшение в SearchRequest состояло бы в том, чтобы сохранить статус как связанную модель, чтобы вы могли восстановить изменение статуса во время поиска.

class SearchRequestStatus(models.Model):
    create_time = models.DateTimeField('create time', auto_now_add=True)
    status = models.CharField(max_length=48)
    detail = models.CharField(max_length=256)
    search = models.ForeignKey(SearchRequest, on_delete=models.CASCADE, related_name='statuses')

Это решение может быть достигнуто двумя способами:

  1. Вы сохраняете явное изменение статуса в соответствующем поле создание вручную нового SearchRequestStatus или ..

  2. Вы сохраняете status и status_detail в SearchRequest и сигнал сохранения захватит изменения и автоматически создаст SearchRequestStatus с использованием приемника. (увидеть: https://docs.djangoproject.com/en/2.1/topics/signals/)

    @ получатель (сигналов.post_save, отправитель = SearchRequest, слабый = False, dispatch_uid = "_ update_search_request_status_history") def _update_search_request_status_history (отправитель, экземпляр, ** kwargs): current_status = SearchRequest.objects.filter (search = instance) .first () если не current_status или current_status.status! = instance.status: SearchRequestStatus.objects.create (поиск = экземпляр, status = instance.status, status_detail = instance.status_detail)

Конечно, вы должны добавить поля к вашей SearchRequest модели, а также добавить кортеж STATUSES, чтобы ограничить выбор статусов

status = models.CharField(max_length=15, choices=STATUSES.items(), default=`STARTED`)
status_detail = models.CharField(max_length=80, null=True, blank=True)
...