2015-12-02 11 views
7

Mam formularz kontaktowy na stronie, która publikuje do CreateAPIView, aby utworzyć nową instancję modelu (która jest ostatecznie wysyłana pocztą elektroniczną do administratora) . Na moim serializatorze mam pole honeypot, które pomaga odrzucić spam.DRF: Usuń pole serializatora modelu po sprawdzeniu poprawności, ale przed utworzeniem (w CreateAPIView)

Model:

class Message(models.Model): 
    name = ... 
    message = ... 

i serializer:

class MessageSerializer(serializers.ModelSerializer): 

    # Honeypot field 
    url = serializers.CharField(allow_blank=True, required=False) 

    class Meta: 
     model = Message 
     fields = '__all__' 

    def validate_url(self, value): 
     if value and len(value) > 0: 
      raise serializers.ValidationError('Spam') 
     return value 

i widok:

class MessageView(generics.CreateAPIView): 
    ''' Create a new contact form message. ''' 
    serializer_class = MessageSerializer 

Moim problemem jest to, że w obecnej formie, kiedy pisać z tym poglądem, że błąd:

TypeError: Got a TypeError when calling Message.objects.create() . This may be because you have a writable field on the serializer class that is not a valid argument to Message.objects.create() . You may need to make the field read-only, or override the MessageSerializer.create() method to handle this correctly.

więc oczywiście seriazlier próbuje uratować pola url do modelu w CreateApiView.perform_create()

próbowałem dodając read_only pola serializer, ale oznacza to, że metoda url_validate jest pominięty.

Jak mogę zachować pole w serializatorze do czasu sprawdzenia poprawności, usunięcie go przed wywołaniem serializer.save() w perform_create()?

Odpowiedz

5

można to zrobić przesłanianie metody tworzenia takich jak:

class MessageSerializer(serializers.ModelSerializer): 

    # Honeypot field 
    url = serializers.CharField(allow_blank=True, required=False) 

    class Meta: 
     model = Message 
     fields = '__all__' 

    def validate_url(self, value): 
     if value and len(value) > 0: 
      raise serializers.ValidationError('Spam') 
     return value 

    def create(self, validated_data): 
     data = validated_data.pop('url') 
     return Message.objects.create(**data) 
+0

Ha, wyobraziłem go i pisał dokładnie jak ty. Możesz mieć punkty;) –

+2

dzięki za odpowiedź, ale 'Message.objects.create (** data)' jest niepoprawne powinieneś przekazać 'validated_data' zamiast tego mam na myśli' Message.objects.create (** validated_data) ' – shotgunner

0

OK, nie poprawnie odczytać błąd. Jak to wyraźnie mówi:

override the MessageSerializer.create() method to handle this correctly.

Szukałem na nadpisanie metody CreateAPIView.create() który nie ma sensu.

to działa:

class MessageSerializer(serializers.ModelSerializer): 

    # Honeypot field 
    url = serializers.CharField(allow_blank=True, required=False) 

    class Meta: 
     model = Message 
     fields = '__all__' 

    def validate_url(self, value): 

     if value and len(value) > 0: 
      raise serializers.ValidationError('Error') 
     return value 

    def create(self, validated_data): 
     if "url" in validated_data: 
      del validated_data["url"] 
     return Message.objects.create(**validated_data)