vendredi 14 novembre 2014

python - Django modèle avec un sous-ensemble filtré de champs connexes - Stack Overflow


The Django docs are not very clear on how to filter objects such that they contain a filtered subset of related fields.


Suppose I have the following models:


class Device(models.Model):
name = models.CharField(max_length=50)

class DeviceEvent(models.model):
device=models.ForeignKey(Device, null=False, related_name='device_events')
handled = models.BooleanField(default=Fasle)

Now suppose I want to retrieve a list of all Devices that have unhandled DeviceEvents. How can I write a query in Django to do that?


The end result should be devices where devices is a list of Device objects, and for each device object "device" we have device.device_events is the list of unhandled DeviceEvent objects. Is this possible to do in Django?


Or, can I do it in python like this:


all_devices=Device.objects.all()
devices=[]
for thedevice in all_devices:
unhandled_device_events=thedevice.device_events.\
annotate(num_events=Count('device_events')).\
filter(device_event__device=thedevice).\
filter(num_events__gt=0).\
filter(device_event__handled=False).all()
if unhandled_device_events:
thedevice.device_events=unhandled_device_events
devices.append(thedevice)

In the above I am creating a new list called devices, then looping through all Device objects and manually adding a device to devices only if it has at least one unhandled event, AND that device object now has device.device_events=the unhandled device events (not ALL the device events). Is this allowed or at all efficient?


Or when I refer to one of the device_events as "device_event" and not "deviceevent" which is correct?




If I understood correctly your question, I think this should work


Device.objects.get(Device.device_events.handled = False)



Since it's a ForeignKey relationship, I believe you can grab all of the DeviceEvents keyed to a device with this (assume d is an instance of the Device class):


d.deviceevent_set.all()

You should be able to filter that like so:


d.deviceevent_set.filter(handled=False)

I haven't tested this but I think it'll work.



The Django docs are not very clear on how to filter objects such that they contain a filtered subset of related fields.


Suppose I have the following models:


class Device(models.Model):
name = models.CharField(max_length=50)

class DeviceEvent(models.model):
device=models.ForeignKey(Device, null=False, related_name='device_events')
handled = models.BooleanField(default=Fasle)

Now suppose I want to retrieve a list of all Devices that have unhandled DeviceEvents. How can I write a query in Django to do that?


The end result should be devices where devices is a list of Device objects, and for each device object "device" we have device.device_events is the list of unhandled DeviceEvent objects. Is this possible to do in Django?


Or, can I do it in python like this:


all_devices=Device.objects.all()
devices=[]
for thedevice in all_devices:
unhandled_device_events=thedevice.device_events.\
annotate(num_events=Count('device_events')).\
filter(device_event__device=thedevice).\
filter(num_events__gt=0).\
filter(device_event__handled=False).all()
if unhandled_device_events:
thedevice.device_events=unhandled_device_events
devices.append(thedevice)

In the above I am creating a new list called devices, then looping through all Device objects and manually adding a device to devices only if it has at least one unhandled event, AND that device object now has device.device_events=the unhandled device events (not ALL the device events). Is this allowed or at all efficient?


Or when I refer to one of the device_events as "device_event" and not "deviceevent" which is correct?



If I understood correctly your question, I think this should work


Device.objects.get(Device.device_events.handled = False)


Since it's a ForeignKey relationship, I believe you can grab all of the DeviceEvents keyed to a device with this (assume d is an instance of the Device class):


d.deviceevent_set.all()

You should be able to filter that like so:


d.deviceevent_set.filter(handled=False)

I haven't tested this but I think it'll work.


0 commentaires:

Enregistrer un commentaire