proper way to combine a field outside of my model in a pre-existing database

204
January 25, 2018, at 11:05 PM

I am working with a pre-existing database called Employee. I have three separate fields i'd like to combine into a single field, but I can't add an additional field to the pre-exisiting database.

I know the proper way to combine multiple fields into one field using python is

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

However, I can't call self outside the model, or at least i'm not sure where I would call self.

My end goal is to have a select box with the combined field a user can search either first, last, or account name. My current model looks like the following:

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]'

I tried to add to my model, but when I call full_username it says the field doesn't exists, which is true because there isn't a field in the database. We aren't allowed to add a new field to the database.

def get_full_name(self):
        full_username = '%s - %s %s' % (self.username, self.firstname, self.lastname)
        return full_username.split()

Ideally i'd want my view to look something like this (i know it wont' work as is, i'd replace that with 'full_username):

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

How would I get the full name added to my view, what am I missing with my logic or where would be the correct place to put it?

Answer 1

You can give this a try:

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')

The icontains bits is just a demo, with this query you can filter the result based on the combined name as well.

If you have to use this everywhere, then I recommend you create your own queryset/manager in your model then put this annotation into the default queryset. After that you can use your full_username filter any where you want without having to add the annotation first.

Answer 2

First, try formatting the string in a good way

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

Second you can the method get_full_name() in model and call it from the model object.

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

That should work. :)

Answer 3

Try using a 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)
Answer 4

If you don't need the functionality of a QuerySet, try this

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

If you do need a QuerySet, I think it's not possible on python-level, only on SQL-level. See this thread on annotations.

READ ALSO
Can&#39;t change values of function in its frame [duplicate]

Can't change values of function in its frame [duplicate]

This question already has an answer here:

164
Open a chrome profile in python that is already signed into google

Open a chrome profile in python that is already signed into google

I'm trying to open up my chrome profile which is signed into google however am not having any luck

254
How to pass arguments to an event listener in SQLAlchemy?

How to pass arguments to an event listener in SQLAlchemy?

I have created an instance of SQLAlchemy model (User):

262