Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ModelForm order field based on count

I'm converting a rather complex self-made form into a ModelForm in Django. As this form is used in production for over a year, i'm trying to remove as much pitfalls as possible and give the users extra functionality.

I have three models: Transaction, Commission and Unit_type. Transaction is the central model in my usage and has a Unit_type. The Commissionis derived from the Unit_type's base_type.

BASE_CHOICES = (
    ('R', 'rent'),
    ('S', 'sale'),
)

class Unit_type(models.Model):
    unit_name = models.CharField(max_length=250)
    base_type = models.CharField(max_length=1, choices=BASE_CHOICES)


class Commission(models.Model):
    commission_name = models.CharField(max_length=250)
    base_type = models.CharField(max_length=1, choices=BASE_CHOICES)


class Transaction(models.Models):
    unit_type = models.ForeignKey(Unit_type)
    commission = models.ForeignKey(Commission, blank=True, null=True)

When i display my form i can show only the Commissions which have the same base_type as Unit_typeby using:

class TransactionForm(forms.ModelForm):

    class Meta:
        model = Transaction

    def __init__(self, unit_type, *args, **kwargs):
        super(TransactionForm, self).__init__(*args, **kwargs)

        self.fields['commission'].queryset = Commission_type.objects.filter(base_type=unit_type.base_type)

I always create my form as TransactionForm(instance=transaction, unit_type=unit_type) in my view.

Now, an easy query in MySQL learned me that some Commissions are used more or less depending on the Unit selected:

SELECT `unit_type_id`, `commission_id`, COUNT(*)
FROM `app_transaction`
GROUP BY `unit_type_id`, `commission_id`

With as result:

+----------------+-----------------+------------+
|  unit_type_id  |  commission_id  |  COUNT(*)  |
+----------------+-----------------+------------+
|             1  |              1  |       367  |
|             1  |              3  |         2  |
|             1  |              4  |        26  |
|             2  |              1  |       810  |
|             2  |              3  |        54  |
|             2  |              4  |       865  |
|             3  |              6  |      2065  |
|             3  |              7  |        16  |
|             3  |              8  |        79  |
+----------------+-----------------+------------+

Now i'd like to order my queryset in self.fields['commission'] based on the above count. I've already tried using values() in __init__():

def __init__(self, unit, *args, **kwargs):
        super(TransactionForm, self).__init__(*args, **kwargs)

        transactions = Transaction.objects.filter(unit_type=unit)
        transactions = transactions.values('commission').annotate(Count('commission)).order_by('-commission')

But now i'm stuck on how i can keep this order in my queryset. Is there an easy way to perform a new queryset based on this ValuesQuerySet? Or am i seeing this completely wrong?

like image 310
J. Ghyllebert Avatar asked Mar 03 '26 23:03

J. Ghyllebert


1 Answers

You just need to use a kwarg for Count and use the same kwarg in order_by

transactions = transactions.annotate(commission_count=Count('commission)).order_by('-commission_count')

https://docs.djangoproject.com/en/1.5/topics/db/aggregation/#cheat-sheet

like image 95
tuxcanfly Avatar answered Mar 05 '26 17:03

tuxcanfly



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!