2

我在我的项目中使用了 Django、GraphQL (graphene-django)、VueJS 和 Apollo Client 的组合。在我尝试管理 many2many 关系之前,一切正常。通常,当我对已经在缓存中的对象进行更新突变时,会检测到它并更新显示的数据。问题是,在我的新案例中,我正在更新我的两个对象之间的 many2many 关系并且它没有更新,而它在数据库中正确完成(甚至在缓存中,当我在控制台中打印它时,它是奇怪的)。通常,我试图在组中/从组中添加/删除用户。也许我已经看我的代码太久了,我看不到明显的东西。无论如何这是我的代码:

我的 Django 模型:

class Group(models.Model):

  def _get_users_count(self):
      return self.user_ids.count()

  name = models.CharField(max_length=255)
  user_ids = models.ManyToManyField(User, related_name="group_ids", db_table="base_group_user")
  users_count = property(fget=_get_users_count, doc="type: Integer")

  def __str__(self):
      return self.name

class User(AbstractUser):

  def _get_full_name(self):
      return "%s %s" % (self.first_name, self.last_name.upper())

  full_name = property(fget=_get_full_name, doc="type: String")

  def __str__(self):
      return self.full_name

  def _has_group(self, group_name):
      return self.group_ids.filter(name=group_name).exists()

我的模式:

class GroupType(DjangoObjectType):

  class Meta:
      model = Group
      fields = ('id', 'name', 'user_ids',)

  users_count = graphene.Int()

class UserType(DjangoObjectType):

  class Meta:
      model = User
      fields = (
          'id',
          'username',
          'password',
          'first_name',
          'last_name',
          'is_active',
          'group_ids',
      )

  full_name = graphene.String()

我的突变体:

class AddUserInGroup(graphene.Mutation):
  id = graphene.ID()
  name = graphene.String()

  class Arguments:
    group_id = graphene.ID()
    user_id = graphene.ID()

  class Meta:
    output = GroupType

  def mutate(self, info, **kwargs):
      group = get_object_or_404(Group, id=kwargs['group_id'])
      user = get_object_or_404(User, id=kwargs['user_id'])
      group.user_ids.add(user)
      return group


class RemoveUserFromGroup(graphene.Mutation):
  id = graphene.ID()
  name = graphene.String()

  class Arguments:
    group_id = graphene.ID()
    user_id = graphene.ID()

  class Meta:
    output = GroupType

  def mutate(self, info, **kwargs):
    group = get_object_or_404(Group, id=kwargs['group_id'])
    user = get_object_or_404(User, id=kwargs['user_id'])
    group.user_ids.remove(user)
    return group

我的 js 常量(gql 查询):

const ADD_USER_IN_GROUP_MUTATION = gql`
  mutation addUserInGroupMutation ($groupId: ID!, $userId: ID!) {
    addUserInGroup(
      groupId: $groupId,
      userId: $userId
    ) {
      id
      name
      usersCount
      userIds {
        id
        username
      }
    }
  }
`

const REMOVE_USER_FROM_GROUP_MUTATION = gql`
  mutation remoteUserFromGroupMutation ($groupId: ID!, $userId: ID!) {
    removeUserFromGroup(
      groupId: $groupId,
      userId: $userId
    ) {
      id
      name
      usersCount
      userIds {
        id
        username
      }
    }
  }
`

const GROUPS_QUERY = gql`
  query {
    groups {
      id
      name
      usersCount
      userIds {
        id
        username
      }
    }
  }
`

我的模板(样本):这些是 2 列。当我删除一个用户时,它应该从左列中删除,它应该出现在不在组中的用户(右列)中,当我添加一个用户时,它应该从右列转到左列。

     <b-tab>
      <template v-slot:title>
        Users
        <b-badge class="ml-2">{{ group.usersCount }}</b-badge>
      </template>
      <b-row>
        <b-col>
          <b-table :items="group.userIds" :fields="table_fields_users_in">
            <template v-slot:cell(actionOut)="row">
              <b-button @click="removeUserFromGroup(row.item)" size="sm" variant="danger" title="Remove">
                <font-awesome-icon :icon="['fas', 'minus-circle']"/>
              </b-button>
            </template>
          </b-table>
        </b-col>
        <b-col>
          <b-table :items="users" :fields="table_fields_users_out">
            <template v-slot:cell(actionIn)="row">
              <b-button @click="addUserInGroup(row.item)" size="sm" variant="success" title="Add">
                <font-awesome-icon :icon="['fas', 'plus-circle']"/>
              </b-button>
            </template>
          </b-table>
        </b-col>
      </b-row>
    </b-tab>

我的数据:(以便您了解它们的来源)。请注意,我应该将“用户”细化为尚未/不再在组中的用户。

props: {
 group: Object,
 editing: {
   type: Boolean,
   default: false
 }
},
apollo: { users: USERS_QUERY },

最后是我的方法

addUserInGroup (user) {
  this.$apollo.mutate({
    mutation: ADD_USER_IN_GROUP_MUTATION,
    variables: {
      groupId: this.group.id,
      userId: user.id
    },
    update: (cache, { data: { addUserInGroup } }) => {
      console.log('cache : ') // currently used for debugging, will be removed
      console.log(cache) // currently used for debugging, will be removed
      console.log('query answer: ') // currently used for debugging, will be removed
      console.log(addUserInGroup) // currently used for debugging, will be removed
    }
  })
  console.log('Added ' + user.username + ' to ' + this.group.name + ' group.')
},
removeUserFromGroup (user) {
  this.$apollo.mutate({
    mutation: REMOVE_USER_FROM_GROUP_MUTATION,
    variables: {
      groupId: this.group.id,
      userId: user.id
    },
    update: (cache, { data: { removeUserFromGroup } }) => {
      console.log('cache : ') // currently used for debugging, will be removed
      console.log(cache)  // currently used for debugging, will be removed
      console.log('query answer : ')  // currently used for debugging, will be removed
      console.log(removeUserFromGroup)  // currently used for debugging, will be removed
    }
  })
  console.log('Removed ' + user.username + ' from ' + this.group.name + ' group.')
}

如果你们需要更多代码(有些部分我会忘记),请随时告诉我,我会提供。

我正在做的一个示例(这样你会注意到我的演示数据实际上是通过砸我的键盘制作的):

在此处输入图像描述

4

1 回答 1

0

最后,对于我的用例,我注意到由于数据(在数据库中)有很多潜在的变化,缓存不是最相关或最可靠的数据源。因此,我将默认的 apollo 更改fetchPolicy'network-only'.

const apolloProvider = new VueApollo({
  defaultClient: apolloClient,
  defaultOptions: {
    $query: {
      fetchPolicy: 'network-only'
    }
  }
})

如此处记录并在此处解释。

因此,每次我挂载具有 apollo 语句的组件时,它都会从网络(从数据库)获取查询。剩下的唯一需要更改缓存的时刻是当我希望当前渲染的组件动态更新某些元素时。

于 2020-02-28T09:17:45.543 回答