Comme indiqué dans le titre, j'utilise Django, GraphQL, Apollo et VueJS dans mon projet. Je le développe en tant que SPA (Application à une page).

Tout fonctionne bien, jusqu'à ce que j'appuie sur le bouton F5 et que j'actualise la page. En effet, il affiche une page inconnue. Le fait est que VueRouter gère le SPA et que cela fonctionne bien. Mais lorsque j'appuie sur F5, c'est Django qui essaie de servir une page pour l'URL actuelle et comme il ne la connaît pas, il ne peut pas servir la page appropriée.

Je sais que je peux définir le mode "historique" de VueRouter, ce que j'ai fait, et ajouter une URL à Django qui sert index.html quelle que soit l'URL.

Mon problème est le suivant : Lorsque je suis sur une vue de formulaire particulière (c'est-à-dire une vue de formulaire Utilisateur) mon URL est la suivante :

http://localhost:8000/user

Étant donné que j'utilise GraphQL pour mon API, les données récupérées ne sont pas basées sur l'URL. En fait, c'est mon composant VueJS qui dit : Hey Apollo, run that GraphQL to retrieve the User I want.

Ainsi, lorsque je rafraîchis, oui, cela sert à la vue du formulaire utilisateur.. mais vide.

La question est : comment pourrais-je résoudre cela ?

À des fins de clarification, voici quelques exemples de code :

Mes URL Django :

# (... other imports here ...)
from .schema import schema

urlpatterns = [
    path('admin/', admin.site.urls),
    path('graphql', csrf_exempt(GraphQLView.as_view(graphiql=True, schema=schema))),  # 'schema' is the main GraphQL schema
    path('', TemplateView.as_view(template_name='index.html')),
    re_path(r'^.*$', TemplateView.as_view(template_name='index.html'))  # I saw that many times to serve the page whatever the URL is when refreshing the page
]

Mon routeur Vue :

export default new Router({
  mode: 'history',
  routes: [
    { path: '/', name: 'MainApp' },
    // ...
    { path: '/users', name: 'UserList', component: UserList },
    { path: '/user/create', name: 'UserFormCreate', component: UserForm, props: true },
    { path: '/user', name: 'UserFormView', component: UserForm, props: true },
    { path: '/user/edit', name: 'UserFormEdit', component: UserForm, props: true },
    // Same pattern for other models like 'Group' ...
  ]

Mon exemple de composant VueJS :

<script>
import {
  // ...
  USER_QUERY,
  // ...
} from '../../graphql/base/user.js'

export default {
  name: 'UserForm',
  props: {
    userId: Number,
    editing: {
      type: Boolean,
      default: false
    }
  },
  apollo: {
    user: {
      query: USER_QUERY,
      variables () { return { id: this.userId } },
      skip () { return this.userId === undefined },
      result ({ data }) {
        this.form.username = data.user.username
        this.form.firstName = data.user.firstName
        this.form.lastName = data.user.lastName
      }
    }
  },
  data () {
    return {
      form: {
        username: '',
        password: '',
        firstName: '',
        lastName: ''
      },
      // ...
    }
  },
  methods: {
    // ...
  }

Je dois mentionner que j'ai vu des sujets plus ou moins liés mais cela ne résout pas mon problème.

Merci d'avance pour votre aide !

2
lbris 24 févr. 2020 à 13:10

1 réponse

Meilleure réponse

Modifiez vos chemins d'itinéraire pour utiliser les paramètres. Par exemple:

{ path: '/user/:userId', name: 'UserFormView', component: UserForm, props: true }

Désormais, l'application interprétera tout nombre suivant le chemin user/ comme un accessoire appelé userId. (props: true est important ici pour utiliser les paramètres comme accessoires.)

Le seul autre changement que vous devez faire est d'ajuster vos liens de routeur pour inclure également le id (Ex. : http://localhost:8000/user/1) afin que lorsque la page sera rafraîchie, il y aura un paramètre à lire.

1
Dan 24 févr. 2020 à 10:33