1

Given the following models, how can I limit the number of ManyToMany relationships that can be created to the value of "count" in the Key model?

For example, if "count" is 2 then only 2 devices can use that key.

Models:

class Device(models.Model):
    name = models.CharField(max_length=100, unique=True)

class Key(models.Model):
    key = models.CharField(max_length=100, unique=True)
    count = models.IntegerField(default=1)
    device = models.ManyToManyField(Device, blank=True, null=True)

I would need to raise an exception if the user tries to add a key to too many devices, or if they reduce "count" to less than the number of devices already using the key. A device can have any number of keys.

(I'm using the admin site for data entry)

Vaughan
  • 391
  • 5
  • 18

2 Answers2

1

This functionality is not built into the Django framework, but you can create your own filter inside the view method.

For example,

MAXKEYS = 3

def addNewKey(request):
  if request.user.is_authenticated():
    deviceRequest = Device.objects.get(pk = request.GET["deviceId"])
    keys = Key.objects.filter(device = deviceRequest)

    if len(keys) < MAXKEYS:
      #add new key reference
    else:
      #return an error or something

  else:
    #return user is not authenticated error message
Jason
  • 11,263
  • 21
  • 87
  • 181
  • where exactly would this fit in given that I'm using the admin site and I haven't defined my own views? – Vaughan Nov 11 '13 at 20:21
  • Adding views to Django admin site: https://docs.djangoproject.com/en/1.5/ref/contrib/admin/#adding-views-to-admin-sites – Jason Nov 11 '13 at 20:47
1

You can listen to the m2m_changed django signal which gets sent every time you add a device to the Key instance.

It will look something like this:

def device_added(sender, **kwargs):
     print "action == %s"%kwargs['action'] # You should intercept when action is 'pre_add'
     print "keyInstanceCount == %s"%kwargs['instance'].count # this is where you can check the current count field and raise your exception if it is exceeding the limit

m2m_changed.connect(device_added, sender=Key.device.through)

Once you connect m2m_changed to device_added, everytime you add a device to a key instance device_added function gets notified as well.

  • 1
    I've gotten this part to work and it shows the exception in the browser. Is there a standard way to make it show an error message and prevent the item from being saved? Is there a particular type of exception I should be raising? – Vaughan Nov 11 '13 at 20:24
  • Try [this](http://stackoverflow.com/a/16799658/1866378) answer. I think it tries to solve a problem that is almost identical to your issue. You may not need to use signals at all. Just overriding the `through` class (`KeyDevice`) might solve the problem. – MindObjects223 Nov 12 '13 at 10:53