首页 > 解决方案 > Django 模型 - CharField 作为其他字段的串联

问题描述

我正在学习 Django 并寻找最佳实践:

想象一下,我有一个手机设备模型:

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

假设我创建了一个这样的对象:

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

或没有“线”:

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

然后我想跟踪我店里每台设备的销售情况,所以我为“交易”创建了一个模型(我只跟踪交易日期和售出的设备,设备作为外键):

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

问题:如果我想通过完整的连接名称查询“设备”,例如“Apple iPhone SE”或“小米米6”,创建“交易”对象的最佳方法是什么?我在通过连接两个字段创建的 Django 数据库条目中发现了类似的东西,但不确定在我的情况下它是否是正确的路径。

我最好的猜测是这样的(其中“名称”是一个连接字段):

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

执行此任务的正确方法是什么?非常感谢您的帮助!

标签: djangodjango-models

解决方案


假设您 varname包含您的文本搜索条件,并使用您的数据模型,您可以使用annotation为查询集返回的每个对象创建一个字段,然后使用此字段进行过滤

您可以尝试如下(未经测试)

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

推荐阅读