Skip to content

查询我关注的及屏蔽的用户 #12

Description

@codetalks-new

开发及测试数据准备

  1. 通过迁移脚本创建一些互相关注或屏蔽的开发用户
    ./manage_dev.py makemigrations wepost_sns --empty --name dev_user_follow_some_user

迁移脚本如下:

from django.db import migrations

from wepost.apps.auth.models import WepostUser
from wepost.apps.sns.services import UserRelationService


def dev_user_follow_block_some_users(apps,se):
    import random
    dev_users = list(WepostUser.objects.filter(username__istartswith="dev"))
    user_set = set(dev_users)
    for user in user_set:
        service = UserRelationService(user)
        other_users = set(user_set)
        other_users.remove(user)
        k = int(len(other_users) * 0.1)
        blocked_users = set(random.choices(list(other_users), k=k))
        for to in other_users:
            if to not in blocked_users:
              service.follow(to)
            else:
              service.block(to)





class Migration(migrations.Migration):

    dependencies = [
        ('wepost_sns', '0001_initial'),
    ]

    operations = [
        migrations.RunPython(dev_user_follow_block_some_users)
    ]

创建多对多关联

class WepostUser(AbstractUser):
  followed_or_blocked = models.ManyToManyField('self',
                                               symmetrical=False,
                                               through='wepost_sns.UserRelation',
                                               through_fields=('from_user', 'to_user'))

注意

  1. 这里的多对多关联是关联的自身上。所以引用时使用特殊的 self 标识。
  2. 同时在我们这里采用了中间表,并且表示的也并非对称性的关系,所以 symmetrical=False
  3. through 字段中由于 UserRelation 数据模型声明在 wepost_sns app中。所以在 wepost_auth app 中引用需要加全限定。
  4. through_fields 中两个字段的逻辑是 field1from_user 相当于 source, field2to_user 相当于 target.

原来 from_userto_user 的 related_name 的设置的名称的语义不正确。更新后如下:

class UserRelation(BaseModel):
  from_user = models.ForeignKey(WepostUser, on_delete=models.CASCADE, verbose_name="用户",
                                related_name="userrelation_from", )
  to_user = models.ForeignKey(WepostUser, on_delete=models.CASCADE, verbose_name="目标用户", related_name="userrelation_to")

然后实现的查询接口代码如下:

  def _query_related(self, state: UserRelationState, keyword: str = None):
    user_set = self.user.followed_or_blocked.filter(userrelation_to__state=state).order_by(
      "-userrelation_to__created")
    if keyword:
      user_set = user_set.filter(username__icontains=keyword)

    return user_set

  def query_followed_users(self, keyword: str = None):
    return self._query_related(state=UserRelationState.FOLLOWING, keyword=keyword)

  def query_blocked_users(self, keyword: str = None):
    return self._query_related(state=UserRelationState.BLOCKING, keyword=keyword)

测试相关代码,跟我的节点中测试代码逻辑类同,因此在此不再赘述。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions