0

Ich benutze einfache Formulare und das generische CBV UpdateView für alle Benutzer, um "Tokens" zu verwenden, um anderen Benutzern Extra-Kredit zu geben. Ein Benutzer sollte nicht berechtigt sein, sich ein Extra-Guthaben zu geben, daher sollten sie nicht als Auswahl im Auswahlfeld erscheinen. Ich verwende hier kein Modell und würde gerne wissen, wie das geht. Hier ist mein Code so weit:Formularfelder in CreateView einschränken, um Aktuellen Benutzer nicht als Auswahl in Vorlage anzuzeigen

models.py

class ExtraCredit(models.Model): 
    recipient = models.ForeignKey(Developer, related_name='extracredit_recipient') 
    sender = models.ForeignKey(Developer, related_name='extracredit_sender') 
    skill = models.ForeignKey(Skill, related_name='extracredit_skill') 
    description = models.TextField(blank=True, null=True) 
    date_credited = models.DateField(auto_now_add=True) 

    def __str__(self): 
     return '%s %s -> %s %s - %s' % (self.sender.user.first_name, self.recipient.user.last_name, self.recipient.user.first_name, self.recipient.user.last_name, self.skill.name) 

views.py

class ExtraCreditCreateView(CreateView): 
    model = ExtraCredit 
    template_name = 'extracredit_create.html' 

    def __init__(self, *args, **kwargs): 
     user = kwargs.pop('user', None) 
     super(ExtraCreditCreateView, self).__init__(*args, **kwargs) 

     self.fields['recipient'].queryset = ExtraCredit.objects.exclude(recipient=user) 
     self.fields['description'].help_text = "Why does this user deserve extra credit?" 

    def get_form_kwargs(self): 
     kwargs = super(ExtraCreditCreateView, self).get_form_kwargs() 
     kwargs.update({'user': self.request.user}) 
     return kwargs 

    def get_success_url(self): 
     return reverse('my_developer_details') 

    def form_invalid(self, form): 
     return self.render_to_response(self.get_context_data(form=form)) 

    def form_valid(self, form): 
     form.save(commit=False) 
     sender = get_object_or_404(Developer, user_id=self.request.user.id) 
     extra_credit_tokens = Developer.objects.get(user_id=sender.user_id).extra_credit_tokens 

     if extra_credit_tokens: 
      Developer.objects.filter(user_id=sender.user_id).update(extra_credit_tokens=extra_credit_tokens-1) 

      form.instance.sender = sender 
      form.save() 

      return super(ExtraCreditCreateView, self).form_valid(form) 
     else: 
      raise forms.ValidationError("The user does not have enough tokens") 

    fields = ['recipient', 'skill', 'description'] 

Der einzige Grund, ich habe die get_form_kwargs(self) Funktion zu versuchen, ist self.request.user in der Funktion zu verwenden. Wenn ich self.request.user in der __init__ Funktion verwende, erhalte ich eine Fehlermeldung, dass die Anfrage kein Attribut von ExtraCreditCreateView ist. Wenn ich eine Anfrage zu den Optionen hinzufüge, wie __init__(self, request, *args, **kwargs):, dann bekomme ich eine Fehlermeldung, dass ich zwei Argumente benötige und nur eins liefere. So wie es jetzt eingerichtet ist, bekomme ich einen TypeError: list indices must be integers, not str.

Was wäre der richtige Weg, um sicherzustellen, dass der aktuell angemeldete Benutzer nicht im Feld "Empfänger" ist, wenn das Formular in der Vorlage erstellt wird?

AKTUALISIERT (bezogen auf das @ Alasdair der Antwort):

class ExtraCreditForm(forms.ModelForm): 
    class Meta: 
     model = ExtraCredit 
     exclude = ['id', 'sender', 'date_credited'] 

    def __init__(self, *args, **kwargs): 
     user = kwargs.pop('user', None) 
     super(ExtraCreditForm, self).__init__(*args, **kwargs) 

     self.fields['recipient'].queryset = self.fields['recipient'].queryset.exclude(user_id=user.id) 
     self.fields['description'].help_text = "Why does this user deserve extra credit?" 

class ExtraCreditCreateView(CreateView): 
    template_name = 'extracredit_create.html' 
    form_class = ExtraCreditForm 

    def get_form_kwargs(self): 
     kwargs = super(ExtraCreditCreateView, self).get_form_kwargs() 
     kwargs.update({'user': self.request.user}) 
     return kwargs 

    def get_success_url(self): 
     return reverse('my_developer_details') 

    def form_valid(self, form): 
     form.save(commit=False) 
     sender = get_object_or_404(Developer, user_id=self.request.user.id) 
     extra_credit_tokens = Developer.objects.get(user_id=sender.user_id).extra_credit_tokens 

     if extra_credit_tokens: 
      Developer.objects.filter(user_id=sender.user_id).update(extra_credit_tokens=extra_credit_tokens-1) 

      form.instance.sender = sender 
      form.save() 

      return super(ExtraCreditCreateView, self).form_valid(form) 
     else: 
      raise forms.ValidationError("The user does not have enough tokens") 
+1

Sie können dies nicht tun, ohne ein ModelForm zu definieren. Ihre Ansicht ist keine Form und es hat keinen Sinn, ihre Init-Methode zu überschreiben oder auf 'self.fields' zuzugreifen. –

Antwort

3

Sie sagen, dass Sie ein Modell Form vermeiden wollen definieren, aber das ist der beste Ansatz hier. Es könnte möglich sein, die Felder des Formulars in der get_form Methode zu hacken, aber Sie sollten dies nicht tun.

Das Festlegen des Abfrage-Sets des Empfängers gehört in das Formular, nicht die Methode __init__ der Ansicht.

class ExtraCreditForm(forms.ModelForm): 

    def __init__(self, *args, **kwargs): 
     user = kwargs.pop('user', None) 
     super(ExtraCreditForm, self).__init__(*args, **kwargs) 

     self.fields['recipient'].queryset = ExtraCredit.objects.exclude(recipient=user) 
     self.fields['description'].help_text = "Why does this user deserve extra credit?" 

dann die __init__ Methode aus der Ansicht entfernen, und setzte form_class so dass es Ihre Modellform verwendet. Sie haben bereits get_form_kwargs aktualisiert, um den Benutzer an die Methode __init__ des Formulars zu übergeben. Sie sollten daher keine weiteren Änderungen vornehmen müssen. Ihre form_invalid Methode macht nichts besonderes, also können Sie sie entfernen.

class ExtraCreditCreateView(CreateView): 
    form_class = ExtraCreditForm 
    ... 
+0

Danke! du führst mich in die richtige Richtung. Ich poste meine endgültige Lösung als Update oben, aber die wichtigste Änderung ist: 'self.fields ['recipient']. Queryset = self.fields ['recipient']. Querieset.exclude (user_id = user.id)' um den aktuellen Benutzer auszuschließen. – charlwillia6

Verwandte Themen