1

I'm learning Django and looking for a best practice:

Imagine I have a model for a mobile phone device:

class Device(models.Model):
    vendor = models.CharField(max_length=100)
    line = models.CharField(max_length=100, blank=True)
    model = models.CharField(max_length=100)

Let's say I create an object like this:

Device.objects.create(vendor = "Apple",
    line = "iPhone",
    model = "SE"
)

or without "line":

Device.objects.create(vendor = "Xiaomi",
model = "Mi 6"
)

Then I'd like to track sales in my shop for every device, so I create a model for a "Deal" (I track only the deal date and the device sold, device as a ForeignKey):

class Deal(models.Model):
    device = models.ForeignKey(Device, on_delete=models.CASCADE)
    deal_date = models.DateTimeField(default=None)

Question: What is the best way to create a "Deal" object, if I want to query "Device" by its full, concatenated name, e.g. "Apple iPhone SE" or "Xiaomi Mi 6"? I've found something similar in Django database entry created by concatenation of two fields , however not sure if it's the right path in my case.

My best guess is something like this (where "name" is a concatenated field):

de = Device.objects.get(name = "Apple iPhone SE")
Deal.objects.create(device = de,
deal_date = datetime(2018, 4, 26, 15, 28)
)

What is the correct way to do this task? Many thanks for your help!

Fed
  • 11
  • 3
  • you can try to read this answer - https://stackoverflow.com/questions/6520445/overriding-get-method-in-models?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa . You should override `get()` method of model.Manager. Or, better, write your own `get_full_name()` method. If that doesn't help - i try to code tomorrow :) – Chiefir Apr 27 '18 at 23:59
  • Thanks for your comment, still I have some troubles understanding it :( I believe the function should look like this, however I still don't understand how to get an object with it: `def get_full_name(self): if line: fullname = vendor + " " + line + " " + model else: fullname = vendor + " " + model return fullname` – Fed Apr 28 '18 at 14:05

2 Answers2

0

Supposing that you var name contains your text search criteria, and usign your data models, you could use annotation to create a field to each object returned by your query set, and then filter using this field

You could try some as follow (it is not tested)

import datetime

from django.db.models import F
from your.app.models import Deal, Device


# supposing is in your view, but like sounds as a model method

def my_view(request, *args, **kwargs)
    name = request.POST.get('name')
    device_qs = Decive.objects.all().annotate(text_concatenated='{} {} {}'.format(F('vendor'), F('line'), F('model'))).filter(text_concatenated=name)

    try:
        device = device_qs.get()
    except Device.DoesNotExist:
        # to manage the scenario when doesn't exist any match
        # here you manage this situation
        pass
    except Device.MultipleObjectsReturned:
        # to manage the scenario when various devices have the same 'text concatenated', i dont know, maybe data model should be improved
        # here you manage this situation
        device = device_qs.first()

    deal = Deal.objects.create(device=device, deal_date=datetime.datetime.now())

    # build your response and return it
Angel F
  • 479
  • 3
  • 13
0

Thanks for your advice guys, searching a little bit more I've found an answer appropriate in my case: what I did is I tweaked save() method, which now populates a field automatically as a concatenation of 3 other fields. @propertywas usefull in this case too

Fed
  • 11
  • 3