2014-10-07 3 views
0

У меня есть две модели, которые имеют атрибут в общем, я хотел бы два объединить их, если атрибуты в оба равны, каждый из которых извлекает данные из различных баз данных:быстрый способ объединить две модели с помощью атрибута в Django

первая модель

class User(models.Model): 
     matricula = models.CharField(max_length=100) 

     def __unicode__(self): 
      return self.matricula 

Вторая модель

class UserMoodle(models.Model): 
     matricula = models.CharField(max_length=100) 

     def __unicode__(self): 
      return self.matricula 

Пример

Если у меня есть:

lists_users = [<User: 123>, <User: 2345>,<User:567>] 
lists_users_moodle = [<UserMoodle:123>, <UserMoodle:2345>, <UserMoodle:897>] 

Я хотел бы объединить их и получить этот результат:

combined_models_lists = [[<User: 123>, <UserMoodle: 123>], [<User: 2345>, <UserMoodle: 2345>], [<User: 567>, None],[None, <UserMoodle: 897>]] 

Спасибо заранее!

ответ

2

Одним из способов были бы создать dicts из этих списков (или QuerySet), а затем перебрать объединение ключей этой dicts, чтобы получить желаемый результат:

dict_users = {x.matricula : x for x in lists_users} 
dict_moodle = {x.matricula : x for x in lists_users_moodle} 

combined_models_lists = [[dict_users.get(x), dict_moodle.get(x)] 
              for x in set(dict_users).union(dict_moodle)] 

Другим способом будет итерации по отсортированной версии каждого QuerySet, а затем популяции списка, таким образом мы будем использовать меньшую память по сравнению с вышеуказанным методом:

users = User.objects.all().order_by('matricula') #order by field `matricula` 
moodles = UserMoodle.objects.all().order_by('matricula') 

out = [] 

it1 = iter(users) 
it2 = iter(moodles) 

prev1 = next(it1) 
prev2 = next(it2) 

while True: 
    if prev1.matricula == prev2.matricula: 
     out.append([prev1, prev2]) 
     try: 
      prev1 = next(it1) 
      prev2 = next(it2) 
     except StopIteration: 
      out.extend([x, None] for x in it1) 
      out.extend([None, x] for x in it2) 
      break 

    if prev1.matricula < prev2.matricula : 
     out.append([prev1, None]) 
     try: 
      prev1 = next(it1) 
     except StopIteration: 
      out.append([None, prev2]) 
      out.extend([None, x] for x in it2) 
      break 

    if prev1.matricula > prev2.matricula : 
     out.append([None, prev2]) 
     try: 
      prev2 = next(it2) 
     except StopIteration: 
      out.extend([prev1, None]) 
      out.extend([x, None] for x in it1) 
      break 
Смежные вопросы