Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django M2M with a large table

I have a typical M2M scenario where promotion activities are related to our retailers. However we have a large number of retailers (over 10k) and therefore I can't use the normal multiple select widget.

What I would aim to do is have an 'activity' instance page with a 'retailer' sub-page which would have a table listing all those retailers currently related to the activity. In addition there would be a 'delete' checkbox next to each retailer so they could be removed from the list if necessary. (Naturally, I would also have another search/results page where users could select which retailers they want to add to the list, but I'm sure I can sort that out myself).

Could someone point me in the right direction regarding modelforms and formset factories as I'm not sure where to go from here. It would seem obvious to directly manipulate the app_activity_associated_retailers table but I don't think I can do this with the existing functions. Is there was a pattern for doing this.

class Activity(models.Model):
    budget = models.ForeignKey('Budget')
    activity_type = models.ForeignKey('ActivityType')
    amount = models.DecimalField(max_digits=8, decimal_places=2)
    associated_retailers = models.ManyToManyField('Retailer', related_name='associated_retailers')

class Retailer(models.Model):
    name = models.CharField(max_length=50)
    address01 = models.CharField(max_length=50)
    address02 = models.CharField(max_length=50, blank=True)
    postcode = models.CharField(max_length=5)
    city = models.CharField(max_length=20)
like image 848
alj Avatar asked Jul 13 '18 14:07

alj


1 Answers

All ManyToManyFields have a through model, whether you define one yourself or not. In your case, it'll have an id, an activity field and a retailer field. You can access the table with Activity.associated_retailers.through -- one "obvious" way is to just expose it as a "model" like

ActivityRetailer = Activity.associated_retailers.through

You can now manipulate these relationships like they were any ol' Django model, so you can i.e. generate querysets like

retailer_records_for_activity = ActivityRetailer.objects.filter(activity_id=1234)

... and you can also create model formsets (complete with that delete checkbox if so configured) for these pseudo-models.

like image 59
AKX Avatar answered Oct 23 '22 00:10

AKX