2

私はcreatedフィールドに次の関係の時間を記録して中間モデルを作成しようとしています。クエリセット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フィールドでFollowShipモデルのクエリセットの注文にアクセスしようとしました。エラーが発生します。 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.followingsは、user.profileが従うプロファイルを意味します。
user.profile.followersは、user.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ドキュメント](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