I need to return a form from inside a django celery task. My task is called from the following django view:
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)
The name of my task is "period" and It compares dates with the objective to open a event while the condition in my IF is true. My "event" is a formulary that user has to confirm presence.
My task:
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
The formulary that I want to show after call my task and while the condition is true It will come of the django Model following:
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)
In short, I want my formulary appears while my condition is true. So for, I had try using, into my task, RequestFactory.get to catch the URL and call the view (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)
However, I had receive ImportError: cannot import name 'MyAnotherView'. If anyone can help me, I aprecciate!
My problem was checking if today's date is between two dates. If so, I must "show" a form. This check I did with celery. And my question here was how I could do as long as today's date was between the dates to enable the form. I solved the problem as follows:
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 %}
If anyone thinks there is a better way, they can suggest me, but I will have that answer for now.