Question

Je suis peut-être complètement hors de la réservation ici. (N'hésitez pas à me dire si je le suis.)

Mon cas d'utilisation est que j'ai une liste d'écoles. Le modèle scolaire est assez simple:

class School(models.Model):
    name = models.CharField(max_length=100)
    mascot = models.CharField(max_length=100, null=True, blank=True)

Lorsque mon utilisateur souhaite modifier l'une de ces écoles, je ne veux pas qu'ils modifient la copie principale. Au lieu de cela, je veux leur donner leur propre copie avec laquelle ils peuvent jouer. Lorsqu'ils ont fini de modifier leur copie, ils peuvent soumettre leur changement et quelqu'un d'autre l'approuvera. J'ai donc une autre classe pour la copie de l'école par l'utilisateur:

class UserSchool(models.Model):
    name = models.CharField(max_length=100)
    mascot = models.CharField(max_length=100, null=True, blank=True)
    master_school = models.ForeignKey(School)
    user = models.ForeignKey(settings.AUTH_USER_MODEL)

J'ai donc mis en place un formulaire pour gérer l'édition de Userschool:

class UserSchoolForm(forms.ModelForm):
    class Meta:
        model = UserSchool
        fields = ['name','mascot']

Et maintenant j'ai ma forme iditschool:

class EditSchool(UpdateView):
    model = School
    success_url = reverse_lazy('list_schools')
    form_class = UserSchoolForm

    def get(self, request, *args, **kwargs):
        school = self.get_object()

        # make a copy of the school for this user
        user_school, created = UserSchool.objects.get_or_create(
            master_school=school, user=request.user,
            defaults={'name' : school.name, 'mascot' : school.mascot})

        self.object = user_school
        form = UserSchoolForm()
        context = self.get_context_data(form=form)
        return self.render_to_response(context)

Je sais que get () fait la copie correctement, mais lorsque le formulaire s'affiche, aucune valeur n'est répertoriée dans les champs "nom" ou "par défaut". Mon soupçon est que le problème concerne le fait que Cls.Model = School, mais Self.Object est une instance d'utilisateurs.

Suis-je proche mais manque quelque chose? Suis-je complètement sur le mauvais chemin? Existe-t-il un meilleur modèle pour cela (comme avoir une instance unique avec un utilisateur spécial pour "Master")?

(Et une petite complication - comme je suis une vieille main à Django, mais une nouvelle vue basée sur les classes, j'essaie d'utiliser des vues de vanille parce que je trouve plus facile de comprendre ce qui se passe.)

Était-ce utile?

La solution

Juste pour exclure l'évidence - vous ne transmettez rien au constructeur de formulaire. L'avez-vous essayé avec instance=user_school? Il pourrait y avoir plus qui a besoin de travail, mais je commencerai là.

Pour développer un peu - à votre avis, vous remplacez complètement le intégré get méthode. C'est bien, mais cela signifie que vous contournez une partie du comportement automatisé de votre superclasse. Plus précisément, le get méthode de ProcessFormView (L'une de vos classes d'ancêtre) instancie la forme en utilisant le get_form Méthode de la classe de vue. FormMixin, un autre ancêtre, définit get_form:

return form_class(**self.get_form_kwargs())

Et get_form_kwargs sur ModelFormMixin ajouter self.object à la forme kwargs:

kwargs.update({'instance': self.object})

Parce que vous êtes remplacé get La méthode n'appelle pas get_form, ça n'appelle pas non plus get_form_kwargs et ne passe donc pas par tout le chemin qui fournit une liaison initiale pour la forme.

Personnellement, j'essaierais de gérer cela en modifiant le get_object Méthode de votre vue personnalisée et laissant le reste seul:

class EditSchool(UpdateView):
    model = School
    success_url = reverse_lazy('list_schools')
    form_class = UserSchoolForm

    def get_object(self, queryset=None):
        school = super(EditSchool, self).get_object(queryset=queryset)
        user_school, created = UserSchool.objects.get_or_create(
            master_school=school, user=self.request.user,
            defaults={'name' : school.name, 'mascot' : school.mascot})
        return user_school

Il peut y avoir plus de changements nécessaires - je n'ai pas testé cela - mais les deux get et set Méthodes Utilisation get_object, et le lier au formulaire le cas échéant.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top