1

Ich habe ein Modell, das für sein Namensfeld unterschiedliche Validierung verwendet, abhängig davon, ob das Objekt von einem Benutzer oder vom System erstellt wurde.Django CreateView: Benutzer vor der Validierung festlegen

class Symbol(models.Model): 
    name = models.CharField(_('name'), unique=True, max_length=64) 
    creator = models.ForeignKey('User', null=True, on_delete=models.CASCADE) 
    def is_system_internal(self): 
     """ 
     whether or not this Symbol belongs to the system rather than having been created by a user 
     """ 
     return (self.creator is None) 
    def clean(self): 
     """ 
     ensure that the Symbol's name is valid 
     """ 
     if self.is_system_internal(): 
      if not re.match("^_[a-zA-Z0-9\-_]+$", self.name): 
       raise ValidationError(
        _("for system-internal symbols, the name must consist of letters, numbers, dashes (-) and underscores (_) and must begin with an underscore."), 
        params = { 'value' : self.name }, 
       ) 
     else: 
      if not re.match("^[a-zA-Z][a-zA-Z0-9\-_]*$", self.name): 
       raise ValidationError(
        _("the symbol name must consist of letters, numbers, dashes (-) and underscores (_) and must begin with a letter."), 
        params = { 'value' : self.name }, 
       ) 

Ich möchte ein Formular und eine CreateView erstellen, mit denen Benutzer die Objekte erstellen können. Wenn ein Benutzer ein solches Objekt erstellt, sollte der Benutzer als Wert für den Wert des Felds "Creator" verwendet werden.

Derzeit sieht es wie folgt aus:

class SymbolCreateForm(forms.ModelForm): 
    name = forms.CharField(max_length=Symbol._meta.get_field('name').max_length, required=True) 
    class Meta: 
     model = Symbol 
     fields = ('name',) 

class SymbolCreateView(LoginRequiredMixin, generic.CreateView): 
    form_class = SymbolCreateForm 
    template_name = 'main/symbol_create.html' 
    def form_valid(self, form): 
     # set the creator of the instance to the currently logged in user 
     form.instance.creator = self.request.user 
     return super(SymbolCreateView, self).form_valid(form) 

ich es so geschrieben, weil dass die Antwort auf diese Frage im Zusammenhang war:

Accessing request.user in class based generic view CreateView in order to set FK field in Django

Leider funktioniert es nicht: Die View erlaubt mir nur Symbole zu erstellen, die mit einem Unterstrich beginnen, wo es das Gegenteil tun sollte. Wenn ich jedoch ein Symbol erstelle, wird das Erstellerfeld trotzdem korrekt gesetzt.

Ich denke, das Problem ist, dass das Creator-Feld erst gesetzt wird, nachdem die clean() -Methode bereits ausgeführt wurde.

Wie setze ich das Creator-Feld, BEVOR die clean() -Methode aufgerufen wird?

Oder gibt es eine bessere Möglichkeit zu tun, was ich versuche zu tun? Es scheint mir, als sollte es eine effektivere Möglichkeit geben, die Logik zu automatisieren, dass ich zwei verschiedene Validatoren für das Namensfeld habe, deren Auswahl vom Erzeugerfeld abhängt.

Antwort

2

Sie können instance.creator in der get_form_kwargs-Methode festlegen.

class SymbolCreateView(LoginRequiredMixin, generic.CreateView): 
    form_class = SymbolCreateForm 

    def get_form_kwargs(self): 
     kwargs = super(SymbolCreateView, self).get_form_kwargs() 
     if kwargs['instance'] is None: 
      kwargs['instance'] = Symbol() 
     kwargs['instance'].creator = self.request.user 
     return kwargs 

prüfen if kwargs['instance'] is None bedeutet, dass der Code funktioniert sowohl mit CreateView und UpdateView.

+0

Ich erhalte einen TypeError: "ModelFormMetaclass Objekt Argument nach ** muss ein Mapping sein, nicht NoneType" –

+0

Denken Sie daran, 'Kwargs' zurückzugeben – Alasdair

Verwandte Themen