как вернуть представление django из задачи сельдерея?

Мне нужно вернуть форму из задачи django celery. Моя задача вызывается из следующего представления django:

class MyView(CreateView):
    model = MyModel
    form_class = MyForm
    success_url = '/create/form'

    def form_valid(self, form):
        form.save()
        # I call my task in here
        period.delay()
        print("Loading task...")

        return super(MyView, self).form_valid(form)

Моя задача называется "период", и она сравнивает даты с целью открытия события, пока условие в моем IF истинно. Мое "событие" — это формуляр, который пользователь должен подтвердить.

Мое задание:

from .views import MyAnotherView 
# others imports...

"""
    in my settings.py, I had to call tha task every minute:
    CELERYBEAT_SCHEDULE = {
    'add-periodic-events': {
        'task': 'myapp.tasks.period',
        'schedule': crontab(minute='*'),
        }
    }
"""

@shared_task(serializer='json')
def period():
    event = MyModel.objects.get(id=1) # I limited my model to receive only one object

    request = RequestFactory.get('/another/form') 
    view = MyAnotherView() 

    week_d = week_day(event.day) # day is a field of my model
    event_d = event_day(week_d, event.hour) # hour is a field of my model
    conf_d = presence_confirm(event.before_days, event.begin_hour, event_d) # before_days and begin_hour are fields of my model

    utc_now = pytz.utc.localize(datetime.utcnow())
    n = utc_now.astimezone(pytz.timezone('America/Recife'))
    t_str = '{}-{}-{}'.format(n.year, n.month, n.day)
    t_hour = ' {}:{}'.format(n.hour, n.minute)

    today = t_str + t_hour
    today = datetime.strptime(today, '%Y-%m-%d %H:%M')

    if (today >= conf_d) and (today < event_d):
        # HOW TO CALL MY FORMULARY???
        print("Call my formulary")
        view.setup(request)

    else:
        # another thing

Формуляр, который я хочу показать после вызова моей задачи, и пока условие истинно. Это произойдет из модели django следующим образом:

class MyAnotherModel(models.Model):
    OPTIONS = (
        (True, 'Sim'),
        (False, 'Não'),
    )

    player = models.OneToOneField(MyUserModel, primary_key=True, on_delete=models.CASCADE)
    confirm = models.BooleanField(choices=OPTIONS, default=False)
    modified = models.DateTimeField(auto_now_add=True)

Короче говоря, я хочу, чтобы мой формуляр появлялся, пока мое условие верно. Итак, я попытался использовать в своей задаче RequestFactory.get, чтобы перехватить URL-адрес и вызвать представление (MyAnotherView).

     # ...
     request = RequestFactory.get('/another/form') 
     view = MyAnotherView() # View responsável em instanciar MyAnotherModel 
     # ...
     if (today >= conf_d) and (today < event_d):
        view.setup(request)

Однако я получил сообщение ImportError: невозможно импортировать имя MyAnotherView. Если кто-нибудь может мне помочь, я признателен!


person Thales    schedule 08.01.2020    source источник
comment
Ну, ваша ошибка совершенно ясна, она просто говорит, что у вас нет MyAnotherView, определенного в .views. Вам нужно будет показать нам структуру папки, чтобы понять, почему ее нельзя импортировать. Но мой главный вопрос о том, что вы пытаетесь здесь сделать. Ваша задача celery не выполняется в рамках цикла запроса, поскольку она асинхронна. Поэтому показать вид невозможно. Показывать кому? Исходный запрос пользователя уже получил ответ от MyView, поэтому браузер ничего не ждет.   -  person dirkgroten    schedule 08.01.2020
comment
@dirkgroten, поверь мне, моя структура правильная. Это действительно немного сбивает с толку. Извини за это! Я хочу включить форму на определенный период времени, чтобы мои пользователи могли ее заполнить. У меня есть время события и когда пользователи могут подтвердить посещение. Именно в этот промежуток (между подтверждением посещения и днем ​​мероприятия) я хотел бы активировать свою форму. Если есть другой способ, который вы можете показать мне, я ценю это.   -  person Thales    schedule 08.01.2020
comment
что вы подразумеваете под появлением моего формуляра (в любом случае, что такое формуляр)? Появляется где? Если вы хотите проверить, должна ли форма отображаться или нет, зачем вам для этого асинхронная задача? Ваш вопрос и объяснение не имеют никакого смысла.   -  person dirkgroten    schedule 08.01.2020
comment
Я хочу, чтобы форма могла заполнить временные рамки, которые я упомянул. Чтобы проверить, соответствует ли сегодняшний день указанному пользователем диапазону времени, я использовал сельдерей, как показано выше. Отныне я хочу включить/показать/пользователю, когда он нажимает на ссылку, что-то в этом роде. Я не знаю, лучший ли это способ. Извините за неясность. У меня нет знаний о сельдерее, чтобы задать идеальный вопрос, извините за это, но я стараюсь быть максимально ясным.   -  person Thales    schedule 08.01.2020


Ответы (1)


Моя проблема заключалась в том, чтобы проверить, находится ли сегодняшняя дата между двумя датами. Если да, то я должен "показать" форму. Эту проверку я сделал с сельдереем. И мой вопрос здесь заключался в том, как я могу сделать, если сегодняшняя дата находится между датами, чтобы включить форму. Я решил проблему следующим образом:

  • Моя задача сельдерея не выполняется в цикле запроса, так как она асинхронная — @dirkgroten — вскоре я подумал о создании нового поля в моей модели django (MyModel):
enable = models.BooleanField(default=False)
  • Обновите это поле в моей задаче:
    # ...
    if (today >= conf_d) and (today < event_d):
        event.enable = True
        event.save()

    else:
        event.enable = False
        event.save()
  • Вернуть эту информацию в качестве контекста в моем шаблоне из моего представления формы
    # In MyAnotherView
    model = MyAnotherModel
    fields = ['player', 'confirm']
    success_url = '/list/users'
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        obj = MyModel.objects.get(id=1)
        context['enable'] = obj.enable
        return context
<!--This is the template that shows form-->
{% if enable %}
    {{ form }}
{% else %}
    <h2> Don't show <h2>
{% endif %}

Если кто-то думает, что есть лучший способ, они могут предложить мне, но пока у меня будет этот ответ.

person Thales    schedule 08.01.2020