-
Notifications
You must be signed in to change notification settings - Fork 3
Open
Labels
Description
开发及测试数据准备
- 通过迁移脚本创建一些互相关注或屏蔽的开发用户
./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'))注意
- 这里的多对多关联是关联的自身上。所以引用时使用特殊的
self标识。 - 同时在我们这里采用了中间表,并且表示的也并非对称性的关系,所以
symmetrical=False through字段中由于UserRelation数据模型声明在wepost_snsapp中。所以在wepost_authapp 中引用需要加全限定。through_fields中两个字段的逻辑是field1即from_user相当于source,field2即to_user相当于target.
原来 from_user 和 to_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)测试相关代码,跟我的节点中测试代码逻辑类同,因此在此不再赘述。
Reactions are currently unavailable