2014-12-01 12 views
6

In corso di aggiornamento a Django REST Framework 3.0 dalla 2.4.4 e voglio avere un campo utente di sola lettura, ma questo non funziona perché "utente" è richiesto da l'UniqueTogetherValidator (credo)DRF 3.0: UniqueTogetherValidator con un campo di sola lettura

ho modello (errori di battitura scusa, questa è semplificata e il codice funziona IRL fine):

class ExampleModel(models.Model): 
    some_attr = models.PositiveSmallIntegerField() 
    other_attr = models.PositiveSmallIntegerField() 
    user = models.ForeignKey(User) 

    class Meta: 
     unique_together = ('some_attr', 'other_attr', 'user') 

Viewset:

class ExampleViewSet(viewsets.ModelViewSet): 
    queryset = ExampleModel.objects.all() 
    serializer_class = ExampleSerializer 

    def perform_create(self, serializer): 
     serializer.save(user=self.request.user) 

    def perform_update(self, serializer): 
     serializer.save(user=self.request.user) 

Serializer:

class ExampleSerializer(serializers.ModelSerializer): 
    user = UserSerializer(read_only=True) 

    class Meta: 
     model = ExampleModel 

Ora, io continuo a ricevere errori dicendo: {"user":["This field is required."]}, che non era il caso prima. In un esempio leggermente diverso con lo stesso problema di base, ottengo l'errore di asserzione May not set both 'read_only' and 'required' anche se non sto impostando l'utente come richiesto.

Ricevo lo stesso errore indipendentemente se aggiungo required=False per l'attributo utente nel serializzatore o se aggiungo utente ai campi esclusi nella meta del serializzatore.

Quando uso la pratica nuova stampa serializzatore, vedo:

class Meta: 
    validators = [UniqueTogetherValidator(queryset=ExampleModel.objects.all(), fields=('user', 'some_attr', 'other_attr'))] 

che viene aggiunto automaticamente in base unique_together del modello. Se lo sovrascrivo esplicitamente e non includo 'utente' nei campi per UniqueTogetherValidator allora tutto funziona come prima.

Questa è una conseguenza prevista dell'aggiornamento 3.0? Mi sembra che l'aggiunta di request.user nel perform_create/perform_update sia una procedura DRF molto standard come dimostrato nel tutorial. Mi rendo conto che non avere la nuova convalida equivale semplicemente a fallire a livello di DB, e la nuova validazione probabilmente fornisce migliori messaggi di errore, ma

C'è una soluzione oltre a ignorare la convalida per ogni serializzatore dove questo è un problema ?

Grazie in anticipo per qualsiasi aiuto!

+0

hey, sarei curioso di sapere come si usa la * comoda stampante di serializzazione * come se io chiami 'print repr (serializer)' come descritto [qui] (http: //www.django-rest-framework. org/api-guide/serializers/# inspecting-a-modelserializer) Non vedo alcun dato relativo a Meta. Grazie! :) – gru

+0

Per me, le uniche informazioni Meta visualizzate sono i validatori. Inoltre, per quanto posso dire, puoi semplicemente chiamare 'YourSerializer()' e l'output è lo stesso di 'print repr (YourSerializer())' – baylee

risposta

7

Questo è a known issue che siamo in fase di indirizzamento all'interno di Django REST Framework. A partire da ora, non v'è una nota nella documentation about UniqueTogtherValidator che dice

Nota: La classeUniqueTogetherValidation impone sempre un vincolo implicito che tutti i campi si applica a sono sempre trattati come richiesto. I campi con valori default rappresentano un'eccezione poiché forniscono sempre un valore anche se omessi dall'input dell'utente.

Questo spiega perché si sta vedendo un errore perché il campo è obbligatorio, anche se sono le impostazioni in modo esplicito read_only=True. Si consiglia di esaminare il numero CurrentUserDefault class, che potrebbe soddisfare le proprie esigenze evitando il problema con lo UniqueTogetherValidator.

class ExampleSerializer(serializers.ModelSerializer): 
    user = UserSerializer(
     read_only=True 
     default=serializers.CurrentUserDefault() 
    ) 

    class Meta: 
     model = ExampleModel 

Questo dovrebbe fare la stessa cosa come i vostri perform_create e perform_update ganci.

+1

Ah, scusa, stavo solo guardando le note di rilascio e non vedi quella documentazione 'CurrentUserDefault' ha fatto il trucco però! Grazie per la risposta rapida. – baylee

+0

Non penso che 'default' si applica a' perform_update' - ma normalmente/spesso è sufficiente impostare il riferimento utente su create. –

Problemi correlati