2

다음 관계를 기록한 created 필드가있는 중간 모델을 만들려고합니다.QuerySet order_by 중간 모델

모델은 다음과 같습니다 :

class Profile(models.Model): 
    user = models.OneToOneField(User, related_name='profile') 
    realname = models.CharField(max_length=20, verbose_name='真實姓名', blank=True) 
    nickname = models.CharField(max_length=20, verbose_name='暱稱/顯示名稱') 

## the intermediate model is connected through following field ## 
    followings = models.ManyToManyField('self', through='FollowShip', 
             related_name='followers', symmetrical=False, 
             through_fields=('profile_from', 'profile_to')) 

    total_followers = models.IntegerField(default=0) 

    def __str__(self): 
     return 'Profile of User:{}'.format(self.user.username) 


class FollowShip(models.Model): 
    profile_from = models.ForeignKey(Profile, related_name='follow_from_set') 
    profile_to = models.ForeignKey(Profile, related_name='follow_to_set') 
    created = models.DateField(auto_now_add=True, db_index=True) 

    def __str__(self): 
     return "{} follows {}".format(self.profile_from, self.profile_to) 

    class Meta: 
     unique_together = ('profile_from', 'profile_to') 

그것은 잘 작동합니다. 그러나, created 필드에 의해모델의 QuerySet 순서에 액세스하려고했을 때. 오류가 발생합니다. manage.py shell에서

는 : 중간 모델 설정이 정확하지 않은 것처럼

>>> user.profile.followings.order_by('followship__created') 
Traceback (most recent call last): 
    File "<console>", line 1, in <module> 
    File "/Users/young/Desktop/env/strayvoice/lib/python3.5/site-packages/django/db/models/query.py", line 232, in __repr__ 
    data = list(self[:REPR_OUTPUT_SIZE + 1]) 
    File "/Users/young/Desktop/env/strayvoice/lib/python3.5/site-packages/django/db/models/query.py", line 256, in __iter__ 
    self._fetch_all() 
    File "/Users/young/Desktop/env/strayvoice/lib/python3.5/site-packages/django/db/models/query.py", line 1087, in _fetch_all 
    self._result_cache = list(self.iterator()) 
    File "/Users/young/Desktop/env/strayvoice/lib/python3.5/site-packages/django/db/models/query.py", line 54, in __iter__ 
    results = compiler.execute_sql() 
    File "/Users/young/Desktop/env/strayvoice/lib/python3.5/site-packages/django/db/models/sql/compiler.py", line 824, in execute_sql 
    sql, params = self.as_sql() 
    File "/Users/young/Desktop/env/strayvoice/lib/python3.5/site-packages/django/db/models/sql/compiler.py", line 369, in as_sql 
    extra_select, order_by, group_by = self.pre_sql_setup() 
    File "/Users/young/Desktop/env/strayvoice/lib/python3.5/site-packages/django/db/models/sql/compiler.py", line 47, in pre_sql_setup 
    order_by = self.get_order_by() 
    File "/Users/young/Desktop/env/strayvoice/lib/python3.5/site-packages/django/db/models/sql/compiler.py", line 293, in get_order_by 
    field, self.query.get_meta(), default_order=asc)) 
    File "/Users/young/Desktop/env/strayvoice/lib/python3.5/site-packages/django/db/models/sql/compiler.py", line 553, in find_ordering_name 
    field, targets, alias, joins, path, opts = self._setup_joins(pieces, opts, alias) 
    File "/Users/young/Desktop/env/strayvoice/lib/python3.5/site-packages/django/db/models/sql/compiler.py", line 586, in _setup_joins 
    pieces, opts, alias) 
    File "/Users/young/Desktop/env/strayvoice/lib/python3.5/site-packages/django/db/models/sql/query.py", line 1402, in setup_joins 
    names, opts, allow_many, fail_on_missing=True) 
    File "/Users/young/Desktop/env/strayvoice/lib/python3.5/site-packages/django/db/models/sql/query.py", line 1327, in names_to_path 
    "Choices are: %s" % (name, ", ".join(available))) 
django.core.exceptions.FieldError: Cannot resolve keyword 'followship' into field. Choices are: follow_from_set, follow_to_set, followers, followings, id, nickname, realname, total_followers, user, user_id 

것 같습니다. 그래서 내가 쿼리 followship 찾을 수 없습니다. 그러나 양측에 잘 접근 할 수 있습니다. 예를 들어 :

>>> user.profile.followings.all() 
`<QuerySet [<Profile: Profile of User:222222>, <Profile: Profile of User:333333>]>` 
>>> user.profile.followers.all() 
`<QuerySet [<Profile: Profile of User:222222>]>` 

이의 잘못 무슨 단서가 없다.

+0

같은 오류 메시지가 표시됩니다. 중간 모델이 다른 모델을 가리키는 것과 다른 행동을하는 '자체'에 대한 m2m 관계를 나타내는 것처럼 보입니다. – JianWei

답변

1

p.follow_from_set.order_by('created')을 사용하십시오.

user.profile.followingsuser.profile의 프로필을 의미합니다.
user.profile.followersuser.profile을 추적 한 프로필을 의미합니다.
user.profile.followersuser.profile.followings은 모두 Profile의 쿼리 세트를 반환하며 사용자, 실제 이름, 닉네임과 같은 Profile 필드로만 주문할 수 있습니다. 당신이 use.profile 및 order_by created 다음에 된 프로필을 찾으려면

, 당신은 사용할 수 있습니다

result = [] 
for profile_id in user.profile.follow_from_set.order_by('created').values('profile_to'): 
    result.append(Profile.objects.get(id=profile_id)) 

을 많은 다음이 있다면, 아마도 당신이하여 SQL을 최적화 할 수 있습니다

profile_ids = user.profile.follow_from_set.order_by('created').values('profile_to') 
profiles = Profile.objects.filter(id__in=profile_ids) 

F 차례로 profile_ids 순서로 프로필 순서를 변경하십시오.

result = [] 
result_dict = {} 
for profile in profiles: 
    result_dict[profile.id] = profile 
for id in profile_ids: 
    result.append(result_dict[id]) 
return result 

아마도이 문제를 해결하는 더 좋은 방법이 있습니다. 어느 누구도 더 나은 해결책을 제시 할 수 있습니까?

+0

[django document] (https://docs.djangoproject.com/en/1.10/topics/db/models/#intermediary-manytomany)의 마지막 부분을보십시오. 문서처럼, >>>> Person.objects.filter ( ... group__name = 'The Beatles', ... membership__date_joined__gt = date (1961,1,1))와 같은 질의를 할 수 있습니다. – JianWei

+0

당신의 방법은 작동합니다. 하지만 이렇게하려면 데이터베이스에 히트를 여러 번 추가해야합니다. 비용은 엄청납니다. – JianWei

+0

쿼리 집합'Profile.objects.filter (followers__nickname__contains = '')는 당신이 추천 한 것과 같습니다. 여기서'Profile.objects.filter (follower_from_set__created__lt = datetime.date (2016,1,1))'또는'Profile.objects.filter (followers__created__lt = datetime.date (2016,1,1))'과 같은 것을 원할 것입니다. (두 모델 모두 작동하지 않았습니다.) – ramwin