On 2/03/2019 2:08 am, karim.at...@gmail.com wrote:
Hi Mike,

I tried what you wrote by overriding the *self.change_form_template* but the form does not appear. Would you please provide me the content of your model admin *billing_payment_view ?*

Sure. I recently asked for assistance here and posted most of the code ...

https://groups.google.com/forum/#!topic/django-users/809HBmPa9vk

You are right, my application is different. My template contains a script provided by Stripe which calls their API to collect a credit card payment. But overall it isn't much different than any other template called by any other view. The view just takes a different path depending on whether it is a POST or a GET request. My view looks complex because when the user clicks [Pay now] it happens in the Stripe js embedded in the template and the Stripe API - in turn - hits my view with the actual POST containing the result of the credit card transaction. I had to seed the form/template with hidden data so it travelled across the Stripe boundary and back to me so I could complete the processing. If you can see past that complication it should be clear that I'm using the form to clean the data and the view to interface with the ORM/database.

It is working well for me now and I'm in the middle of writing unit tests.

Good luck


Thanks.

Karim

Le vendredi 1 mars 2019 00:06:40 UTC+1, Mike Dewhirst a écrit :

    On 28/02/2019 9:46 pm, karim...@gmail.com <javascript:> wrote:
    Hi,

    I'm currently struggling with a custom ModelAdmin.

    Karim

    I haven't tried to fully understand your use case. However, this
    is what I think your process could be if you do not wish to ajax
    it ...

    1. Override the model save() method to call a model method which
    detects your trigger scenario and calls the code you wish to
    execute to collect all the data you wish to display. This might be
    in the parent model or the m2m 'through' model. Unlikely to be in
    the child model.

    2. Write a Form to reveal the data you wish to display. It
    probably needs to be a ModelForm

    3. Write a template for the data including any hidden fields for
    object pks and additionally consider calling {{ block.super }} to
    display inherited stuff if you are extending another template and
    using the same block. When I first started to work all this out I
    was able to get my form to appear at the top of the ModelAdmin
    form using block.super and spent a bit of time hiding the big red
    [Delete] button because it was too close to my big blue [Pay now]
    button. However, as I got deeper into it I somehow lost that and
    never got it back. I was so pleased with getting it working
    eventually that I persuaded myself I didn't really want it on the
    same page anyway. Your mileage may vary :) I think you need to
    hard-code the form in the ModelAdmin to get it appearing above
    everything else.

    4. Write any necessary urls

    5. Write a view to manipulate your data, based on the request and
    your form

    6. Get the Admin to display it on demand. The first line of the
    change_view() method below initialises the ModelAdmin to do
    absolutely nothing different than usual. Nothing will happen
    unless the trigger is detected. Then finally call to super to
    resume the normal course of events when your code is complete.
    What follows is my own recent experience. The comments should tell
    you more than the code

    def change_view(self, request, object_id, form_url='', extra_context=None):

         """ self = SubstanceAdmin
             request = wsgi request object
             object_id = substance
             form_url = no idea!
             extra_context = dict of apps, models, admin_urls and permissions

         https://docs.djangoproject.com/en/1.11/ref/contrib/admin/#django  
<https://docs.djangoproject.com/en/1.11/ref/contrib/admin/#django>.
         contrib.admin.ModelAdmin.change_view

         """
         # Let the ModelAdmin resume normal operations with its own template
         self.change_form_template = None
         # queryset of m2m records from the 'through' table
         ingredients = 
Substance_Ingredients.objects.filter(substance_id=object_id)
         subscription = None
         for sm2mi in ingredients:
             # sm2mi.fee_payable() is the detector which triggers the process
             payable, fee_type = sm2mi.fee_payable()  # eg., True, PAID_DATA
             if payable:
                 # generate a subscription record with blank token field or
                 # if one exists with a non-blank token, return None
                 subscription = billing_subscribe(sm2mi, fee_type)
                 if subscription:    # collect money for the owner
                     # switch the ModelAdmin to the new template
                     self.change_form_template = 'payment.html'
                     # assemble all the necessary data for the view
                     context = billing_collect_context(
                         sm2mi,
                         subscription,
                     )
                     # get everything into the payment_view context
                     if not extra_context:
                         extra_context = dict()
                     extra_context.update(self.admin_site.each_context(request))
                     extra_context.update(context)
                     # wrap the view to protect it with Admin permissions
                     self.admin_site.admin_view(
                         # call the view with request and context
                         billing_payment_view(
                             request,
                             sm2mi,
                             subscription,
                             context=extra_context,
                         )
                     )
                     # only one sm2mi at a time
                     break
         return super(SubstanceAdmin, self).change_view(
             request, object_id, form_url, extra_context
         )


    7. Call super in the model save() method *or* raise an exception
    to prevent saving. I'm actually not sure about this bit. It may go
    against the Django flow. However, I do use a BusinessRuleViolation
    exception which inherits from ValidationError and therefore lets
    me include a human readable message which appears in the Admin and
    *seems* to prevent saving. You would need to test this especially
    with m2m side-effects and atomicity consequences.

    I hope this helps.

    Mike


    Considering the following model:


    |
    # Bloc fonctionnel
    classAssembly(Item):

        product
    
=models.ForeignKey(to='ProductFamily',on_delete=models.CASCADE,null=True,verbose_name=_('Famille
    Produit'))
        functions
    =models.ManyToManyField(Function,verbose_name=_('Fonctions'))
    
*performances*=models.ManyToManyField(Performance,verbose_name=_('Performances'),related_name='performances')

    def_get_type(self):
    returnItemType.ASSEMBLY

    classMeta:
            verbose_name =_('Bloc Fonctionnel')
            verbose_name_plural =_('Blocs Fonctionnels')
    |



    I have a custom AssemblyAdmin related to it and also a custom
    AssemblyForm for customizing some fieds.

    The *performances* m2m field is critical.
    The performances are captured in the form with a dynamic_raw_id
    field, which works fine.

    But when this field is modified, some updates/deletions might be
    applied in other tables of the database.
    For this purpose, I need to collect the "performance" pk captured
    in the html form and compare them with those currently in the
    database.

    Basically, when the user clicks on the regular "Save" or "Save
    and continue" button, I would need to display an alert form (like
    when you click on the delete button) to explain what would happen.

    I struggled with some ajax routines but it does not work as
    expected.

    I don't know if it's really doable and how to achieve it.

    Any suggestion is welcome.

    Cheers.

    Z.







-- 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 <javascript:>.
    To post to this group, send email to django...@googlegroups.com
    <javascript:>.
    Visit this group at https://groups.google.com/group/django-users
    <https://groups.google.com/group/django-users>.
    To view this discussion on the web visit
    
https://groups.google.com/d/msgid/django-users/88135218-a965-46c8-a454-c0376a5682f1%40googlegroups.com
    
<https://groups.google.com/d/msgid/django-users/88135218-a965-46c8-a454-c0376a5682f1%40googlegroups.com?utm_medium=email&utm_source=footer>.
    For more options, visit https://groups.google.com/d/optout
    <https://groups.google.com/d/optout>.

--
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 <mailto:django-users+unsubscr...@googlegroups.com>. To post to this group, send email to django-users@googlegroups.com <mailto:django-users@googlegroups.com>.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/ba1fe4cd-420b-4683-be97-469c303deb86%40googlegroups.com <https://groups.google.com/d/msgid/django-users/ba1fe4cd-420b-4683-be97-469c303deb86%40googlegroups.com?utm_medium=email&utm_source=footer>.
For more options, visit https://groups.google.com/d/optout.

--
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 post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/1a32b6c9-8c7e-0abe-57f7-0f20630580d7%40dewhirst.com.au.
For more options, visit https://groups.google.com/d/optout.

Reply via email to