【问题标题】:proper way to combine a field outside of my model in a pre-existing database将我的模型之外的字段组合到预先存在的数据库中的正确方法
【发布时间】:2018-01-25 17:29:28
【问题描述】:

我正在使用一个名为 Employee 的预先存在的数据库。我想将三个单独的字段合并为一个字段,但我无法向预先存在的数据库添加其他字段。

我知道使用python将多个字段组合成一个字段的正确方法是

'%s - %s %s' % (self.username, self.firstname, self.lastname)

但是,我不能在模型之外调用 self,或者至少我不确定在哪里调用 self。

我的最终目标是拥有一个包含组合字段的选择框,用户可以搜索名字、姓氏或帐户名。我当前的模型如下所示:

class Employee(models.Model):
        staff_id = models.IntegerField(db_column = 'Employee_ID')
        status_id = models.IntegerField(db_column = 'StatusID')
        username = models.CharField(db_column = 'SamAccountName',primary_key = True, max_length = 31)
        lastname = models.CharField(db_column = 'Surname', max_length = 63)
        firstname = models.CharField(db_column = 'GivenName', max_length = 63)
        title = models.CharField(db_column = 'Title', max_length = 127)

        class Meta:
            managed = False
            db_table = '[Employee]'

我试图添加到我的模型中,但是当我调用 full_username 时,它​​说该字段不存在,这是真的,因为数据库中没有字段。我们不允许向数据库添加新字段。

def get_full_name(self):

        full_username = '%s - %s %s' % (self.username, self.firstname, self.lastname)

        return full_username.split()

理想情况下,我希望我的视图看起来像这样(我知道它不会按原样工作,我会用 'full_username 替换它):

activeuserlist = Employee.objects.filter(staff_id = '1').values_list('%s - %s %s' % (Employee.username, Employee.firstname, Employee.lastname), flat = True)  

我如何将全名添加到我的视图中,我的逻辑缺少什么或放置它的正确位置?

【问题讨论】:

    标签: python django


    【解决方案1】:

    你可以试试这个:

    from django.db.models.functions import Concat
    from django.db.models import F, Value
    
    employees = Employee.objects.annotate(full_username=Concat(F('username'), Value(' - '), F('firstname'), Value(' '), F('lastname')))\
        .filter(staff_id='1', full_username__icontains='hello')
    

    icontains bits 只是一个演示,通过此查询,您也可以根据组合名称过滤结果。

    如果您必须在任何地方使用它,那么我建议您在模型中创建自己的查询集/管理器,然后将此注释放入默认查询集中。之后,您可以在任何地方使用您的 full_username 过滤器,而无需先添加注释。

    【讨论】:

    • 当我尝试使用 concat 时,它给了我以下 AttributeError: can't set attribute [25/Jan/2018 12:06:25] "GET /account/profile/ HTTP/1.1" 500 96620 可能是因为我不想过滤到单个用户名,而是一个列表。
    • 您可能会引用实际的列名而不是别名,即。 F('username') 将是 F('SamAccountName')
    • 我试过了,它仍然在 /account/profile/ 处抛出 AttributeError 无法设置属性
    • 我可以看看你的查询吗?
    • activeuserlist = Employee.objects.annotate(full_username=Concat(F('samaccountname'), Value(' - '), F('givenname'), Value(' '), F(' surname')))\ .filter(staff_id ='1') 当我尝试原始时,它抛出一个错误,给我存在的字段名称列表,在我更正后,我得到了无法设置属性错误。
    【解决方案2】:

    首先,尝试以一种好的方式格式化字符串

    full_username = '{} - {} {}'.format(self.username, self.firstname, self.lastname)

    其次,您可以在模型中的方法get_full_name() 并从模型对象中调用它。

    employee = Employee.objects.get(id=1) full_name = employee.get_full_name()

    应该可以。 :)

    【讨论】:

    • 只有在有一名员工时才有效,但我正在寻找所有在职员工。
    • 如果你循环列表你将得到单个对象并且你可以以相同的方式访问......
    • 我得到 'QuerySet' 对象没有属性 'get_full_username' 使用以下。 emplist= Employee.objects.all() activeempoloyee = emplist.get_full_username 我的模型显示如下: @property def full_username(self): full_username = '{} - {} {}'.format(self.username, self.firstname, self.lastname) 返回 (full_username)
    【解决方案3】:

    尝试使用property

    from django.db import models
    
    class Person(models.Model):
        first_name = models.CharField(max_length=50)
        last_name = models.CharField(max_length=50)
        birth_date = models.DateField()
    
        def baby_boomer_status(self):
            "Returns the person's baby-boomer status."
            import datetime
            if self.birth_date < datetime.date(1945, 8, 1):
                return "Pre-boomer"
            elif self.birth_date < datetime.date(1965, 1, 1):
                return "Baby boomer"
            else:
                return "Post-boomer"
    
        @property
        def full_name(self):
            "Returns the person's full name."
            return '%s %s' % (self.first_name, self.last_name)
    

    【讨论】:

    • 当我尝试在我的视图中调用 full_username 或 get_full_username 时,它​​仍然表示不存在任何属性。
    • 你在使用属性装饰器吗?
    • 是的,我在模型中添加了以下内容:@property def full_username(self): full_username = '{} - {} {}'.format(self.username, self.firstname, self.lastname ) 然后我返回 full_username
    【解决方案4】:

    如果你不需要 QuerySet 的功能,试试这个

    activeuserlist = [
        '{} - {} {}'.format(user.username, user.firstname, user.lastname)
        for user in Employee.objects.filter(staff_id = '1')
    ]
    

    如果您确实需要 QuerySet,我认为这在 python 级别是不可能的,只能在 SQL 级别。有关注释,请参阅 this thread

    【讨论】:

      猜你喜欢
      • 2020-05-23
      • 2016-08-02
      • 1970-01-01
      • 2014-04-29
      • 1970-01-01
      • 1970-01-01
      • 2015-06-01
      • 2013-03-18
      • 1970-01-01
      相关资源
      最近更新 更多