admin.py and forms.py

dependent select get data from JSON
 avatar
unknown
python
2 years ago
8.2 kB
3
Indexable



# admin.py
class OrderAdmin(admin.ModelAdmin):
    form = OrderAdminForm
    # change_form_template = 'admin/cargo/order/custom_form.html'
    actions = [send_mass_invoices]

    list_display = ['invoice_no', 'order_sender', 'order_total_price', 'order_payment', 'send_single_invoice']
    list_filter = ['order_sender__user', 'created', 'order_payment']

    fieldsets = (
        (None, { 'fields': ('order_sender', 'invoice_no', 'order_partner', 'order_shipping_variant', 'order_weight', 'order_notes', 'order_payment', 'order_total_price') }),
        ('Asal', {'fields': ('orig_province', 'orig_city')}),
        ('Tujuan', {'fields': ('dest_province', 'dest_city', 'dest_subdistrict',)}),
    )

    class Media:
        js = [
            'https://code.jquery.com/jquery-3.6.1.min.js',
            # 'https://cdn.jsdelivr.net/npm/bootstrap-select@1.13.14/dist/js/bootstrap-select.min.js',
            '/static/js/national-address-chain.js'
        ]

    # def add_view(self, request, form_url="", extra_context=None):
    #     extra_context = extra_context or {}
    #     extra_context['form'] = self.get_form(request)
    #     return super(OrderAdmin, self).add_view(request, form_url=form_url, extra_context=extra_context)

    def user_sender_name(self, obj):
        return obj.order_sender.fullname

    def get_urls(self):
        urls = super().get_urls()
        custom_urls = [
            path(
                'send_invoice/<int:id>',
                self.admin_site.admin_view(self.process_invoice),
                name='send_invoice'
            )
        ]
        return custom_urls + urls

    def send_single_invoice(self, obj):
        if obj.order_payment == 'NoPayment':
            return format_html(
                '<a  class="button" style="background-color:blue; color: white; padding: 5px; border-radius:5px;" href="{}">Send Invoice</a>&nbsp;',
                reverse('admin:send_invoice', args=[obj.pk]),
            )
        else:
            # return obj.order_payment
            return format_html(
                f'<a style="background-color:green; color: white; padding: 5px; border-radius:5px;" class="button">{obj.get_order_payment_display()}</a>&nbsp;',
            )

    send_single_invoice.short_description = 'Send Invoice'
    send_single_invoice.allow_tags = True

    def process_invoice(self, request, id, *args, **kwargs):
        obj = Order.objects.get(id=id)
        obj.order_payment = 'SendInvoice'
        obj.save()
        messages.success(request, 'Invoice has been sent!')
        return HttpResponseRedirect(request.META.get('HTTP_REFERER'))



# forms.py
# this form is used for the admin dashboard, the goal is to make dependent select in the given addresses 
class OrderAdminForm(forms.ModelForm):
    class Meta:
        model = Order
        fields = [
            'order_from_address',
            'order_to_address',
            'order_weight',
            'order_shipping_variant',
            'orig_province',
            'orig_city',
            'dest_province',
            'dest_city',
            'dest_subdistrict',
            'order_notes'
        ]
        
    order_total_price = forms.CharField(label='Biaya Kirim Total', help_text='Automatic filled',
                                        widget=forms.TextInput({'readonly': True}))

    orig_province = forms.ChoiceField(
        label='Provinsi Asal')
    orig_city = forms.CharField(label='Kota Asal')
    dest_province = forms.CharField(label='Provinsi Tujuan')
    dest_city = forms.CharField(label='Kota Tujuan')
    dest_subdistrict = forms.CharField(label='Kecamatan Tujuan')


    # this one is also used in the client section and doing just fine. 
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for f in ['orig_province', 'orig_city', 'dest_province', 'dest_city', 'dest_subdistrict', ]:
            self.fields[f].show_hidden_initial = True
            self.fields[f].initial = '-----'
            selectAttrs = {'class': 'selectpicker',
                           'data-live-search': 'true',
                           'title': '-----'}
            if f != 'orig_province':
                selectAttrs['disabled'] = 'true'
            self.fields[f].widget = forms.Select(attrs=selectAttrs)
        self.fields['orig_province'].choices = [
            (p, p.title()) for p in SicepatPrice().get_orig_province()]
            



# The JS file 
<script src="https://cdn.jsdelivr.net/npm/bootstrap-select@1.13.14/dist/js/bootstrap-select.min.js"></script>
<script>
    String.prototype.toTitle = function () {
        return this.replace(/(^|\s)\S/g, function (t) { return t.toUpperCase() });
    }

    // const submitBtn = $('#submit_btn')

    function resetDropdown(targets) {
        // submitBtn.attr('disabled')
        targets.forEach(t => {
            t.html(null)
            t.attr('disabled', true)
            t.val(undefined)
            t.selectpicker('refresh')
        });
    };

    function generateSelectOptions(target, list) {
        resetDropdown([target]);
        list.forEach(val => {
            target.append(`<option value="${val}">${val.toTitle()}</option>`);
        });
        target.attr('disabled', false);
        target.selectpicker('refresh')
        target.selectpicker('toggle')
    };

    function ajaxBase(ask, data) {
        return {
            url: '/api/prices/national/reference',
            type: 'get',
            data: {
                ask,
                ...data
            }
        }
    }

    (function () {
        const inputElements = {
            orig_province: $('#id_orig_province'),
            orig_city: $('#id_orig_city'),
            dest_province: $('#id_dest_province'),
            dest_city: $('#id_dest_city'),
            dest_subdistrict: $('#id_dest_subdistrict'),
        };

        inputElements.orig_province.change(function () {
            $.ajax({
                ...ajaxBase('orig_city', { orig_province: inputElements.orig_province.val() }),
                success: function (resp) {
                    generateSelectOptions(inputElements.orig_city, resp.data);
                    resetDropdown([inputElements.dest_province, inputElements.dest_city, inputElements.dest_subdistrict,]);
                }
            });
        });

        inputElements.orig_city.change(function () {
            $.ajax({
                ...ajaxBase('dest_province', {
                    orig_province: inputElements.orig_province.val(),
                    orig_city: inputElements.orig_city.val(),
                }),
                success: function (resp) {
                    generateSelectOptions(inputElements.dest_province, resp.data);
                    resetDropdown([inputElements.dest_city, inputElements.dest_subdistrict,]);
                }
            });
        });

        inputElements.dest_province.change(function () {
            $.ajax({
                ...ajaxBase('dest_city', {
                    orig_province: inputElements.orig_province.val(),
                    orig_city: inputElements.orig_city.val(),
                    dest_province: inputElements.dest_province.val()
                }),
                success: function (resp) {
                    generateSelectOptions(inputElements.dest_city, resp.data);
                    resetDropdown([inputElements.dest_subdistrict,]);
                }
            });
        });

        inputElements.dest_city.change(function () {
            $.ajax({
                ...ajaxBase('dest_subdistrict',
                    {
                        orig_province: inputElements.orig_province.val(),
                        orig_city: inputElements.orig_city.val(),
                        dest_province: inputElements.dest_province.val(),
                        dest_city: inputElements.dest_city.val()
                    }),
                success: function (resp) {
                    generateSelectOptions(inputElements.dest_subdistrict, resp.data);
                }
            });
        });
        // inputElements.dest_subdistrict.change(function () {
        //     submitBtn.removeAttr('disabled')
        // })
    })();
</script>
Editor is loading...