2009-05-20 5 views
5

Próbuję zdefiniować wiele do jednego pola w klasie, która jest "wiele". Na przykład, wyobraźmy sobie sytuację, w której użytkownik może należeć tylko do jednej grupy, ale grupa może mieć wielu użytkowników:ManyToOneField w Django

class User(models.Model): 
    name = models.CharField() 

class Group(models.Model): 
    name = models.CharField() 
    # This is what I want to do -> users = models.ManyToOneField(User) 

Django docs powie zdefiniować pole grupy w modelu użytkownika jako ForeignKey, ale Muszę zdefiniować relację w modelu Grupy. O ile mi wiadomo, nie ma ManyToOneField i wolałbym nie korzystać z ManyToManyField.

+0

Dlaczego nie można użyć klucza obcego? –

+2

Pracuję nad istniejącym projektem i nie chcę wprowadzać zmian w modelach podstawowych, które są kontynuowane w głównym projekcie. – vacanti

Odpowiedz

8

Pole ManyToOne, jak można się domyślić, nosi nazwę ForeignKey w Django. Trzeba będzie zdefiniować go na swojej klasie User za logika działała prawidłowo, ale Django wykorzysta nieruchomość odwrotnej dostępny od modelu Groups automatycznie:

class Group(models.Model): 
    name = models.CharField(max_length=64) 

class User(models.Model): 
    name = models.CharField(max_length=64) 
    group = models.ForeignKey(Group) 

g = Group.objects.get(id=1) 
print g.user_set.all() # prints list of all users in the group 

Pamiętaj, że modele Django siedzieć na szczycie relacyjnej bazy danych. .. nie ma możliwości zdefiniowania pojedynczego pola FK w tabeli, która wskazuje na więcej niż jeden klucz obcy (bez M2M), więc umieszczenie relacji ManyToOne na obiekcie Grupy nie jest mapowane do baz danych danych. Jeśli pisałeś surowy SQL, możesz modelować tę relację z obcym kluczem z tabeli użytkownika do tabeli grupowej w każdym przypadku, jeśli pomaga to myśleć w ten sposób. Składnia i logika korzystania z właściwości ManyToOne, która jest zdefiniowana w instancji grupy, gdyby taka koncepcja istniała, byłaby znacznie mniej prosta niż klucz obcy zdefiniowany dla użytkownika.

+1

Dziękuję za wyjaśnienie, dlaczego nie było możliwe zrobienie tego, czego szukałem. Po prostu używam wielu do wielu dziedzin. – vacanti

1

Należy prawdopodobnie patrząc prosto za pomocą wbudowanego w wyszukiwania wstecznego:

group = Group.objects.get(id=1) 
users_in_group = group.user_set.all() 

tylnej zestawy przeglądowe są tworzone automatycznie dla wszelkich obcych kluczy lub wiele-do-wielu relacji do danego wzoru.

Jeśli chcesz zapoznać się to z przyjaznej nazwy, lub zapewnić dodatkowe filtrowanie przed powrotem, zawsze można zawinąć wywołanie w metodzie:

class Group(models.Model): 
    name = models.CharField(max_length=64) 

    def users(self): 
     return self.user_set.all() 

Albo może być wywoływana z szablonów:

{{ group.user_set.all }} 

{{ group.users }} 
+0

Dzięki! Właśnie tego używam w polu ManyToMany w klasie Group. – vacanti