2

I have two separate django (version >=2.2) apps: campus and equipment.

campus

  • Building
  • Room

equipment (all use base class Device for common attributes)

  • Camera
  • Display
  • Switcher
  • Source
  • etc.

There's a lot of foreign key nesting going on, ex. source -> switcher -> room -> building, and all that works fine. I'm able to do things like source_list = Source.objects.filter(switcher__room_id=room_id) with no issues.

I'm creating an API for equipment that will be using raw UDP strings, so I'm a little bit limited in how fancy it can be. My question is, can I somehow figure out what specific object is being referenced by the .id alone? I can narrow the query to the equipment app since I can figure out Building/Room based on the host IP address.

In other words, my plan is to send a string from the external device with something like 1356|True|hdmi1|whatever|123|abc|stuff| with 1356 being the .id, and then in django efficiently figure out what equipment object 1356 is referring to. I'm good on the whole transport portion of getting the string into a django view, I just need to identify what 1356 is.

Doing something (pseudo code) like this can't be the best way:

try:
    Display.objects.get(id=1356)
except:
    not a display...
try:
    Switcher.objects.get(id=1356)
except:
    not a switcher...
try:
    etc., etc., etc.

Thanks in advance for any help on what is probably a dumb question. Logan

UPDATE I was hoping that since my devices used a common base class that they would have unique ids, but I was able to get their generated ids to conflict after all, as @arulmr warned me. The solution I found definitely adds some length to the strings, but django's way of creating unique ids is as follows:

import uuid

class Device(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

That's it. You now have a 16 bit id that is realistically not going to be replicated in our lifetimes. By the time it goes out UDP it ends up having a length of 36 if that's relevant to anyone but me.

With that solved, all I had to do was:

def fb_view(request, fb):
    fb = fb.split('|')
    id = fb.pop(0)  # pull out the id

    try:
        # .get() will except if there's no match,
        # so I'm using that as my if/elif to match the id
        Display.objects.get(id=id)
        Display.objects.filter(id=id).update(
            things=fb[0],
            other_things=int(fb[1]),
            )
        # not used, just there to send a 200
        return HttpResponse(id, content_type='text/plain')
    except:
        # match was on another device
        pass

    try:
        Switcher.objects.get(id=id)
        Switcher.objects.filter(id=id).update(
            things=fb[0],
            other_things=int(fb[1]),
            )
        return HttpResponse(id, content_type='text/plain')
    except:
        pass

    # etc, etc

Thank you both!! I ended up with the try/except chain after all, but since the feedback handling is unique to each model it worked out fine anyway. Plus I could always move the feedback handling .update() stuff to separate functions if I wanted to clean it up.

logan
  • 55
  • 6
  • There is a possibility for duplicates in the IDs from different models. You might be able to identify the object based on all the details available. But with ID alone, it could be from any model. – arulmr Nov 19 '20 at 18:15
  • Thank you @arulmr I didn't realize that! I haven't dug through Francois' answer yet but you probably just saved me a ton of confusion down the road when the conflict comes true. – logan Nov 19 '20 at 22:17
  • Glad it helped! – arulmr Nov 20 '20 at 17:18

1 Answers1

1

It is no a dumb question at all.

You may want to take a look at model inheritance: https://docs.djangoproject.com/en/2.2/topics/db/models/#model-inheritance

You can setup an abstract equipment base model in which you put your id field. Then each of your specific equipment model (camera, display, switcher, etc.) inherit form this base table.

You can bonify your base model with this technic in order to get the child object from a search on its parent.

  • Thank you! I had already done that with a Model named Device with power_state, ip_address, etc. without realizing it would help with this. – logan Nov 19 '20 at 22:46