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à.
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
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