On 2/12/2023 12:19 am, Thomas Couch wrote:
Can I just check I understand the broader requirements here:

* The user completes the form, which includes a list of items, and clicks submit * For each item in the list you want Django to create a new object and save it to the database * It tends to be a very long list and/or each item takes a long time to process * The user should see a progress bar while the server is working its way through the list * When all items have been processed the progress bar should be replaced with a done message

If that's the case

Yes it is.


I think you should think about using Celery

I looked at the docs for Celery and hesitate to add so much technology just to kick off a progress bar, or actually now a spinner will temporarily suffice as mentioned earlier.

It is why I looked at htmx.

I'm now thinking/wondering if a htmx timed execution - say every one or two seconds - might call a view which monitors a singleton being updated by the main view kicked off by the form's submit button.

What pushes me in that direction is that a singleton could be updated with number processed which would be needed if it ever gets to become a progress bar.

I think Celery might be overkill until needed for scaling up.

I do accept that Celery is the obvious solution and used everywhere. I just need to exhaust potentially simpler methods.

Many thanks Thomas for persisting.

Cheers

Mike

to create tasks for each item. That'll allow your initial htmx post to return without being blocked. The htmx endpoint for the progress bar can then check completed count for the task group.

On Thursday, November 30, 2023 at 3:42:39 AM UTC Mike Dewhirst wrote:

    On 29/11/2023 9:56 pm, Thomas Couch wrote:
    Not sure if it's related, but you've got a div inside a p element
    there:
    <p><div hx-get="/hx_usr_progress" hx-trigger="every 1s"></div></p>

    That'll probably get corrected by the browser to:
    <p></p> <div hx-get="/hx_usr_progress" hx-trigger="every
    1s"></div> <p></p>

    It all seems OK to my untrained eye and things stop working if I
    play with those elements. I'll take them out later and resort to
    css for positioning once it is all working. I didn't know div
    inside a p was wrong.





    Another thing is, it doesn't look like there's anything linking
    the submit button click to the initial htmx

    You are right. That button is in an unbound Django forms.Form and
    submit triggers the database processing - which is all working
    fine returning correct results.

    As an enhancement I tried to detect something else to trigger htmx
    for a progress indicator.



    request, and there's no htmx in the response.

    The response is either a downloaded .csv file or a table of comma
    separated values for the user to copy and paste into a spreadsheet
    - depending on whether the input was pasted into a text field or
    uploaded as a file (list or csv).

    Sadly, the response doesn't return until the processing is
    complete. So it cannot kick off a progress bar.

    Perhaps I need to embark on the async ship? That's a strange land
    for me.


    Have you tried replicating the progress bar example?
    https://htmx.org/examples/progress-bar/

    I looked at that and felt it was too heavily contrived generating
    time increments to expand the bar across the page. It didn't seem
    the right place to start.

    If I was going to use it (and I would/will) I first need to obtain
    progress numbers based on my incrementing count as records are
    created in the database. I can easily put them into the user
    instance. That works well within the main view called by the
    submit button as indicated by print statements as it loops.

    I cannot find a way to get the incrementing number across into the
    htmx view even though it is the same user in the hx-request - as
    indicated by a print statement.

    In breaking news, I have tried to get a spinner going to amuse the
    user while database records are being created. Not properly
    successful. It does start spinning if I click the submit button a
    second time but that is less than satisfactory. I have to
    experiment after studying the htmx docs some more.

    Here is the current form html ... you can see if there IS a
    result, the waiting is over and I use htmx to stop the spinner.

    <form method="post" enctype="multipart/form-data">

        {% csrf_token %}

        {% if form.non_field_errors %}

            {{ form.non_field_errors }}

        {% endif %}

        <div class="indent5">

        <table>

        {% for field in form %}

            <tr>

                <td width="=10%">&nbsp;</td>

                <td width="90%"class="nobullets">{{ field }}</td>

            </tr>

            {% if field.help_text %}

                <tr>

                    <td colspan="2">{{ field.help_text }}</td>

                </tr>

            {% endif %}

        {% endfor %}

        <tr>

            <td width="10%"><p>&nbsp;</p></td>

            <td width="90%">

            {% if not result %}

              <p><div class="g-recaptcha" data-sitekey={{ sitekey
    }}></div></p>

              <p>

              <div class="submit-row">

                <div hx-get="/hx_usr_progress" hx-target="#progress"
    hx-trigger="click">

                  <input type="submit" value="     {{ btn_label
    }}      "/>

                </div>

              </div>

              </p>

            {% else %}

              <p>&nbsp;</p>

              <p>

              <div class="submit-row">

                <div hx-get="/hx_usr_progress_stop"
    hx-target="#progress" hx-trigger="every 1s">

                  <input type="submit" value="     More      "/>&nbsp;

              </div>

              </p>

            {% endif %}

            <div id="progress"></div>

            </td>

        </tr>

        </table>

    </form>

    </div>

    </div>

    <p>{{ result }}</p>

    </div>


    So I have two problems: One is getting the numbers to animate a
    progress bar and two is triggering htmx in parallel with the
    submit button click.

    Many thanks for taking an interest.

    Cheers

    Mike



    On Tuesday, November 28, 2023 at 2:26:20 AM UTC Mike Dewhirst wrote:

        I'm trying but failing to get htmx to deliver a progress
        indication.

        The task is creating records in the database for each item in
        a list provided by the logged in user.

        The view with the submit button collects the list and does
        the database insertion. I added a "progress" property to the
        User model as follows ...

        class User(AbstractUser):

             def __init__(self, *args, **kwargs):

                 super().__init__(*args, **kwargs)

                 self.progress = ""

             ...

             def set_progress(self, value):

                 self.progress = value

             @property

             def get_progress(self):

                 return f"{self.progress}"

             ...



        In the view I update user.progress with the record insertion
        counter and get_progress returns the correct value in the
        view itself as proven by print statements. So that part is
        working.

        In the template, I have ...

           <div class="submit-row">

             <input type="submit" value="     {{ btn_label }}      "/>

           </div>

           <p><div hx-get="/hx_usr_progress" hx-trigger="every 1s"></div></p>


        ... which in theory should fetch progress every second if the
        htmx docs are correct. See https://htmx.org/docs/#polling

        This is the htmx view ...

        def hx_usr_progress(request):

             progress = request.user.progress

             print(f"\n{progress} ... {request.user}")

             return HttpResponse(mark_safe(f"<p>... {progress}</p>"))


        When the import [Submit] button is clicked, the print
        statement in hx_usr_progress fires with a blank progress
        value as per the User.__init__() method AND on the page
        beneath the Submit button the 3 dots shown above in the last
        line of the hx_usr_progress() view but nothing further even
        though the main view is definitely incrementing the count.

        That tells me it is being called at least once instead of
        every second. It should have fired at least 3 or 4 times.

        Or if it did perhaps the original response is cached - I
        don't know.

        How can I get this ticking over?

        Thanks for any hints.

        Cheers

        Mike

-- You received this message because you are subscribed to the
    Google Groups "Django users" group.
    To unsubscribe from this group and stop receiving emails from it,
    send an email to django-users...@googlegroups.com.
    To view this discussion on the web visit
    
https://groups.google.com/d/msgid/django-users/020a98ef-4a10-4560-afdd-0a8b065e7235n%40googlegroups.com
    
<https://groups.google.com/d/msgid/django-users/020a98ef-4a10-4560-afdd-0a8b065e7235n%40googlegroups.com?utm_medium=email&utm_source=footer>.


-- Signed email is an absolute defence against phishing. This email has
    been signed with my private key. If you import my public key you can
    automatically decrypt my signature and be sure it came from me. Your
    email software can handle signing.

--
You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/2155bccd-11c3-4560-97ab-809ccbe2d2c4n%40googlegroups.com <https://groups.google.com/d/msgid/django-users/2155bccd-11c3-4560-97ab-809ccbe2d2c4n%40googlegroups.com?utm_medium=email&utm_source=footer>.


--
Signed email is an absolute defence against phishing. This email has
been signed with my private key. If you import my public key you can
automatically decrypt my signature and be sure it came from me. Your
email software can handle signing.

--
You received this message because you are subscribed to the Google Groups "Django 
users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/fdb26322-b8dd-42d9-804a-dedaa8543ce3%40dewhirst.com.au.

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature

Reply via email to