2008-11-11 4 views
4

을 감안할 때 :Django에서 모델에 대해 역 관계로 모든 클래스 집합을 얻으려면 어떻게해야합니까?

from django.db import models 

class Food(models.Model): 
    """Food, by name.""" 
    name = models.CharField(max_length=25) 

class Cat(models.Model): 
    """A cat eats one type of food""" 
    food = models.ForeignKey(Food) 

class Cow(models.Model): 
    """A cow eats one type of food""" 
    food = models.ForeignKey(Food) 

class Human(models.Model): 
    """A human may eat lots of types of food""" 
    food = models.ManyToManyField(Food) 

방법 일 수 있습니다 만, 클래스 음식 제공, 그것은에 "역의 관계를"이 모든 클래스의 집합을 얻을. 나는. 주어진 클래스 음식, 어떻게 하나 얻을 수있는 클래스 고양이, 암소인간. Food.cat_set, Food.cow_setFood.human_set :

나는 음식이 세 가지 "역의 관계"가 있기 때문에 가능하다고 생각합니다.

도움 의뢰 & 감사합니다. 당신이 가설 얻을, 위 모델에이 기능을 사용하여,

def get_all_related_objects(self, local_only=False): 

def get_all_related_many_to_many_objects(self, local_only=False) 

그리고 :

장고/DB/모델/options.py을 :

답변

7

어느

A) multiple table inheritance를 사용하고 "먹는"기본 클래스, 그 고양이, 암소를 생성하고 인간에서 상속합니다.

B) 식품을 다른 모델과 연결할 수있는 Generic Relation을 사용하십시오.

잘 설명되어 있고 공식적으로 지원되는 기능이므로 자신의 코드를 깨끗하게 유지하고 대안을 피하고 향후에도 계속 지원 될 수 있도록해야합니다.

-

그래서, 여기에 특별한 경우를위한 조리법이다 ("명성 창녀가 될하는 방법"일명) EDIT.

Cat, Cow 및 Human을위한 별도의 모델이 절대적으로 필요하다고 가정합시다. 실제 응용 프로그램에서는 "범주"필드가 작업을 수행하지 않는 이유를 스스로에게 묻고 싶습니다.

일반적인 관계를 통해 "실제"클래스에 쉽게 접근 할 수 있으므로 여기에 B에 대한 구현이 있습니다. Person, Cat 또는 Cow에서 'food'필드를 사용할 수 없거나 같은 문제. 그래서 우리는 중개자 "FoodConsumer"모델을 만들 것입니다. 인스턴스에 대해 하나 이상의 음식을 필요로하지 않으면 추가 검증 테스트를 작성해야합니다.

from django.db import models 
from django.contrib.contenttypes.models import ContentType 
from django.contrib.contenttypes import generic 

class Food(models.Model): 
    """Food, by name.""" 
    name = models.CharField(max_length=25) 

# ConsumedFood has a foreign key to Food, and a "eaten_by" generic relation 
class ConsumedFood(models.Model): 
    food = models.ForeignKey(Food, related_name="eaters") 
    content_type = models.ForeignKey(ContentType, null=True) 
    object_id = models.PositiveIntegerField(null=True) 
    eaten_by = generic.GenericForeignKey('content_type', 'object_id') 

class Person(models.Model): 
    first_name = models.CharField(max_length=50) 
    last_name = models.CharField(max_length=50) 
    birth_date = models.DateField() 
    address = models.CharField(max_length=100) 
    city = models.CharField(max_length=50) 
    foods = generic.GenericRelation(ConsumedFood) 

class Cat(models.Model): 
    name = models.CharField(max_length=50) 
    foods = generic.GenericRelation(ConsumedFood)  

class Cow(models.Model): 
    farmer = models.ForeignKey(Person) 
    foods = generic.GenericRelation(ConsumedFood)  

지금은 그냥이 doctest 작업을 쓸 수 설명합니다 : 응답에 대한

""" 
>>> from models import * 

Create some food records 

>>> weed = Food(name="weed") 
>>> weed.save() 

>>> burger = Food(name="burger") 
>>> burger.save() 

>>> pet_food = Food(name="Pet food") 
>>> pet_food.save() 

John the farmer likes burgers 

>>> john = Person(first_name="John", last_name="Farmer", birth_date="1960-10-12") 
>>> john.save() 
>>> john.foods.create(food=burger) 
<ConsumedFood: ConsumedFood object> 

Wilma the cow eats weed 

>>> wilma = Cow(farmer=john) 
>>> wilma.save() 
>>> wilma.foods.create(food=weed) 
<ConsumedFood: ConsumedFood object> 

Felix the cat likes pet food 

>>> felix = Cat(name="felix") 
>>> felix.save() 
>>> pet_food.eaters.create(eaten_by=felix) 
<ConsumedFood: ConsumedFood object> 

What food john likes again ? 
>>> john.foods.all()[0].food.name 
u'burger' 

Who's getting pet food ? 
>>> living_thing = pet_food.eaters.all()[0].eaten_by 
>>> isinstance(living_thing,Cow) 
False 
>>> isinstance(living_thing,Cat) 
True 

John's farm is in fire ! He looses his cow. 
>>> wilma.delete() 

John is a lot poorer right now 
>>> john.foods.clear() 
>>> john.foods.create(food=pet_food) 
<ConsumedFood: ConsumedFood object> 

Who's eating pet food now ? 
>>> for consumed_food in pet_food.eaters.all(): 
... consumed_food.eaten_by 
<Cat: Cat object> 
<Person: Person object> 

Get the second pet food eater 
>>> living_thing = pet_food.eaters.all()[1].eaten_by 

Try to find if it's a person and reveal his name 
>>> if isinstance(living_thing,Person): living_thing.first_name 
u'John' 

""" 
+0

안녕 빈센트, 감사합니다. 질문에 대답하기 위해 MTI 또는 GR을 정확히 사용하는 방법에 대한 예는 많이 감사하겠습니다. :). –

+0

Brilliant, btw. :) 감사! –

14

소스 코드의 일부 파고 밝혀

>>> Food._meta.get_all_related_objects() 
[<RelatedObject: app_label:cow related to food>, 
    <RelatedObject: app_label:cat related to food>,] 

>>> Food._meta.get_all_related_many_to_many_objects() 
[<RelatedObject: app_label:human related to food>,] 

# and, per django/db/models/related.py 
# you can retrieve the model with 
>>> Food._meta.get_all_related_objects()[0].model 
<class 'app_label.models.Cow'> 

: 나는 아마도 Model._meta은 '불안'이다 듣고는 이후 장고 - 1.0 세계에 의존 할해야하지 않는다.

읽어 주셔서 감사합니다. :)