2

J'ai un modèle utilisateur étendu dans Django, et il est de type Client. J'utilise le cadre de repos django (DRF). Alors, en passant par docs dans DRF Je suis venu à connaître l'écriture dans les modèles imbriqués, donc je ne override créer et méthodes de mise à jour dans sérialiseur, la création fonctionne bien, mais pas la mise à jour comme il est dit:Le cadre de repos Django ne met pas à jour le modèle utilisateur étendu

HTTP 400 Bad Request 
Allow: GET, PUT, PATCH, DELETE, OPTIONS 
Content-Type: application/json 
Vary: Accept 

{ 
    "user": { 
     "username": [ 
      "A user with that username already exists." 
     ] 
    } 
} 

Voici mon modèle client:

from django.db import models 
from django.contrib.auth.models import User 


class Customer(models.Model): 
    user = models.OneToOneField(User, related_name="customer", on_delete=models.CASCADE) 
    date_of_birth = models.DateField(max_length=8) 

    def __unicode__(self): 
     return u'%s' % self.user.username 

mon utilisateur sérialiseur:

from django.contrib.auth.models import User 

from rest_framework import serializers 


class UserSerializer(serializers.HyperlinkedModelSerializer): 
    class Meta: 
     model = User 
     fields = ('url', 'username', 'email', 'is_staff') 

Et mon modèle de client étendu sérialiseur:

from django.contrib.auth.models import User 
from django.contrib.auth import get_user_model 

from rest_framework import serializers 

from customers.models import Customer 
from api.serializers import UserSerializer 


class CustomerSerializer(serializers.HyperlinkedModelSerializer): 
    user = UserSerializer() 
    class Meta: 
     model = Customer 
     fields = ('url', 'date_of_birth', 'user') 
     depth = 1 

    def create(self, validated_data): 
     print "coming inside create" 
     user_data = validated_data.pop("user") 
     user = User.objects.create(**user_data) 
     customer = Customer.objects.create(user=user, **validated_data) 
     return customer 

    def update(self, instance, validated_data): 
     print "coming inside update" 
     user_data = validated_data.pop("user") 
     username = user_data.pop('username') 
     user = get_user_model().objects.get_or_create(username=username)[0] 
     user.email = user_data.get('email', user.email) 
     user.save() 

     instance.user = user 
     instance.date_of_birth = validated_data.get('date_of_birth', instance.date_of_birth) 
     instance.save() 



     return instance 

Voici la vue viewset:

from rest_framework import viewsets 

from customers.models import Customer 
from customers.serializers import CustomerSerializer 


class CustomerViewSet(viewsets.ModelViewSet): 
    serializer_class = CustomerSerializer 
    queryset = Customer.objects.all() 

Alors, qu'est-ce qui pourrait être mal ici qu'il crée un nouveau profil de client, même le nouvel utilisateur, mais pas la mise à jour?


Edit 1 Ok, donc je l'ai fait sur UserSerializer:

class UserSerializer(serializers.HyperlinkedModelSerializer): 
    class Meta: 
     model = User 
     fields = ('url', 'username', 'email', 'is_staff') 
     extra_kwargs = { 
      'username': {'validators': []}, 
     } 

Ainsi, la mise à jour est très bien pour tous les autres champs de champs d'utilisateur ou client, mais

  • si je essayer de définir un nouveau nom d'utilisateur, il crée un nouvel utilisateur,
  • et aussi en essayant de créer un nouvel utilisateur, il donne le foll erreur en raison:

    IntegrityError à/api/clients/

    double valeur de clé est contraire contrainte unique "de auth_user_username_key" DETAIL: Key (nom d'utilisateur) = (Customer1) existe déjà.

Répondre

2

Vous devriez laisser tomber le validateur unique pour le sérialiseur imbriqué:

class UserSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = User 
     fields = ('url', 'username', 'email', 'is_staff') 
     extra_kwargs = { 
      'username': {'validators': []}, 
     } 

Vous pouvez imprimer votre sérialiseur avant de vous assurer que vous n'avez pas d'autres validateurs sur ce champ. Si vous en avez, vous devrez les inclure dans la liste.

+0

Votre solution, crée un nouvel utilisateur si j'essaie de changer le nom d'utilisateur, mais bien sûr cela fonctionne pour le reste des champs, mais en essayant de créer un nouvel utilisateur, il jette une erreur, j'ai mentionné dans modifier la mise à jour de ma question . – Maverick

+0

Le code ci-dessus supprime le contrôle d'unicité de l'utilisateur. Vous devrez traiter cette contrainte explicitement dans votre code en levant une erreur ValidationError si vous êtes sur le point de créer l'utilisateur mais qu'il existe déjà. – Linovia