Это проблема, с которой я боролся некоторое время, и теперь я сдался.Я пишу модель User / Profile в Django 2.0.2 (python 3.6 + postgres 10 в Linux), которая выглядит следующим образом:
class Config_Table(models.Model):
entity_name = models.TextField(primary_key=True)
category = models.TextField()
description = models.TextField(blank=True,default='')
Над таблицей хранится некоторая статическая информация, которая доставляет мне неприятности.
class UserProfile(AbstractUser):
"The Profile of a user with details are stored in this model."
username = models.TextField(primary_key=True, max_length=11)
first_name = models.TextField(max_length=50,blank=True,default='')
last_name = models.TextField(max_length=100,blank=True,default='')
phone_number = models.TextField(max_length=11,blank=True,default='')
avatar = models.ImageField(blank=True, upload_to='Pictures/')
GENDER_CHOICES = (
('M','Male'),
('F','Female'),
)
gender = models.CharField(max_length=1,choices=GENDER_CHOICES, default='M')
city = models.TextField(max_length=25, blank=True, default='NY')
description = models.TextField(max_length=2000, blank=True, default='')
interests = models.ManyToManyField(Config_Table, blank=True, default='')
date_of_birth = models.DateField(blank=True)
official_docs = models.ImageField(blank=True, upload_to='Pictures/')
team_name = models.TextField(blank=True,default='')
debit_card_number = models.IntegerField(blank=True, default=0)
MUSIC_CHOICES = (
('Rock','Rock Music'),
('Trad','Traditional Music'),
('Elec','Electronic Music'),
('Clas','Classical Music')
)
favorite_music = ArrayField(models.TextField(blank=True,default=''),size=2,blank=True, default='{}')
class Meta:
permissions=(("User","User level permission"),
("Tour","Tourleader level permission"),
("Admin","Administrators"))
my views.py
:
class UserList(APIView):
"""
List all users, or create a new user.
"""
def get(self, request, format=None):
users = UserProfile.objects.all()
target_users = []
for user in users.iterator():
if user.is_superuser == False:
target_users.append(user)
serializer = UserProfileSerializer(target_users, many=True)
return Response(serializer.data)
def post(self, request, format=None):
serializer = UserProfileSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
print(serializer.errors)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class UserDetail(APIView):
"""
Retrieve, update or delete a User.
"""
pk_url_kwarg = 'username'
def get_object(self, pk):
try:
return UserProfile.objects.get(pk=pk)
except UserProfile.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
user = self.get_object(pk=pk)
if user.is_superuser == False:
serializer = UserProfileSerializer(user)
return Response(serializer.data)
else:
return Response(status=status.HTTP_404_NOT_FOUND)
def put(self, request, pk, format=None):
user = self.get_object(pk)
serializer = UserProfileSerializer(user, data=request.data, partial=True)
if serializer.is_valid():
for attr, value in serializer.validated_data.items():
if attr == 'password' and attr is None:
serializer.validated_data['password'] = user.password
break
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk, format=None):
user= self.get_object(pk)
user.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
и my serializers.py
:
def create(self, validated_data):
hashed_password = make_password(validated_data['password']) # get the hashed password
print(validated_data)
user = UserProfile(
username=validated_data['username'],
email = validated_data['email'],
first_name= validated_data['first_name'],
last_name= validated_data['last_name'],
phone_number=validated_data['phone_number'],
avatar=validated_data.pop('avatar'),
gender=validated_data['gender'],
city=validated_data['city'],
description=validated_data['description'],
date_of_birth=validated_data.pop('date_of_birth'),
# user_type=validated_data['user_type'],
official_docs=validated_data.pop('official_docs'),
team_name=validated_data['team_name'],
debit_card_number=validated_data['debit_card_number'],
favorite_music=validated_data['favorite_music'],
)
user.set_password(hashed_password)
interest = validated_data['interests']
user.interests.add(validated_data['interests'])
user.groups.add(validated_data['groups'])
user.save()
return user
Проблема, с которой я сталкиваюсь, возникает внутри сериализатора, когда я хочу отправитьнекоторый объект JSON через http, как показано ниже (пример данных для тестирования):
{
"username": "12345678004",
"password": "thisisatest",
"last_login": null,
"is_superuser": false,
"email" : "sample@gmail.com",
"first_name": "AAA",
"last_name": "BBB",
"phone_number": "12045678000",
"gender": "M",
"city": "NY",
"description": "",
"date_of_birth": "2010-03-28",
"team_name": "",
"avatar": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxAPBhAREQ8QDQ8PDxIWEBAWFRANDxAQFRUWFhURExUYHSggGBolGxUTITEhJSkrLi4uFx8zODMsNygtLisBCgoKBQUFDgUFDisZExkrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrK//AABEIAOEA4QMBIgACEQEDEQH/xAAbAAEAAgMBAQAAAAAAAAAAAAAABAUBAgMGB//EADIQAQABAwEHAQYEBwAAAAAAAAABAgMRBAUSITFBUXFhIjKRobHBM4HR8RMjQmJyguH/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhEDEQA/APpgCIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADDIAAAAAAAAAAAAAAAAAAAAAAANrduaq8RGZkGqVY0FdXON2PXn8E/SaOKIzPGrv0jwlAhW9nURHHNU/B3p0tER7sOwDjVpaJj3YcbmzqJjhmJTAFPf0FdPGPaj5/BEejRtVo4rjPKrv38gpRtdtzTXiYxLUAAAAAAAAAAAAAAAAAACIzOO670emi3b/unnP2Q9l2M1zVPKOXlaAAAAAAAAA4azTxct+scpUlVMxVieEw9ErNq2MVRVHXn57grwAAAAAAAAAAAAAAAAbW4zciO8x9QXekt7unpj0diOQAAAAAAAAA5aq3vWJj04eXUB5yRtejF2fMtQAAAAAAAAAAAAAAG9n8an/KPq0InE57A9GMUTmiJ7wyAAAAAAAAADFdWKJntAKDUT/Oq8tGa5zXPlgAAAAAAAAAAAAAAAAFxs29vWMdafolqLR39y9E9J4T4XkTmMxxiQZAAAAAAAARNpXd2xjrV9OqVM4jM8IhSay/v3pnpHLwDgAAAAAAAAAAAAAAAAAAnaDWbvs1cuk9kEB6OJ4Cp0F65E4iJqp7f9W0cgAAAAAVevuXJ4TE00+nHPkDX6ze9mn3es90AAAAAAAAAAAAAAAAAAAddPYqrrxH5z0gHOiiaqsRGZWWm2dEca+Pp0S9Pp6aKeEces9ZdQYpiIjEcIZAAAAAAnkAIep0FNWZp9mfkq71mqirEx+kvQNLtqKqcTGQefEjV6Sbc96Z5T9kcAAAAAAAAAAAAAGaKZmqIjnIN9PZmu5iPznsu7FmKLeI/dppNPFu1jrPOXcAAAAAAAAAAAAGK6YmnExmJUut0v8OvvTPKfsu2l63FduYnlIPPje/ami5MT+8NAAAAAAAAAAAFlsvT/wBc/wCv6oFm3vXYiOsr6imKaIiOUA2AAAAAAAAAAAAAAABE2jp9+1mPep+cKd6NSa6zuX57TxgEcAAAAAAAAAFjsm1xmr8o+6ycdJb3dPTHpxdgAAAAAAAAAAAAAAAAEPadresZ60/RMa105omO8A88NrlOLkx2lqAAAAAAA6aejev0x3lzStmU51XiJkFyAAAAAAAAAAAAAAAAAAACl2jRjUz6oyw2vT7VM+ivAAAAAAATdk/jz4AFsAAAAAAAAAAAAAAAAAAACBtb8KPKrAAAAAH/2Q==",
"official_docs": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxAPBhAREQ8QDQ8PDxIWEBAWFRANDxAQFRUWFhURExUYHSggGBolGxUTITEhJSkrLi4uFx8zODMsNygtLisBCgoKBQUFDgUFDisZExkrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrK//AABEIAOEA4QMBIgACEQEDEQH/xAAbAAEAAgMBAQAAAAAAAAAAAAAABAUBAgMGB//EADIQAQABAwEHAQYEBwAAAAAAAAABAgMRBAUSITFBUXFhIjKRobHBM4HR8RMjQmJyguH/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhEDEQA/APpgCIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADDIAAAAAAAAAAAAAAAAAAAAAAANrduaq8RGZkGqVY0FdXON2PXn8E/SaOKIzPGrv0jwlAhW9nURHHNU/B3p0tER7sOwDjVpaJj3YcbmzqJjhmJTAFPf0FdPGPaj5/BEejRtVo4rjPKrv38gpRtdtzTXiYxLUAAAAAAAAAAAAAAAAAACIzOO670emi3b/unnP2Q9l2M1zVPKOXlaAAAAAAAAA4azTxct+scpUlVMxVieEw9ErNq2MVRVHXn57grwAAAAAAAAAAAAAAAAbW4zciO8x9QXekt7unpj0diOQAAAAAAAAA5aq3vWJj04eXUB5yRtejF2fMtQAAAAAAAAAAAAAAG9n8an/KPq0InE57A9GMUTmiJ7wyAAAAAAAAADFdWKJntAKDUT/Oq8tGa5zXPlgAAAAAAAAAAAAAAAAFxs29vWMdafolqLR39y9E9J4T4XkTmMxxiQZAAAAAAAARNpXd2xjrV9OqVM4jM8IhSay/v3pnpHLwDgAAAAAAAAAAAAAAAAAAnaDWbvs1cuk9kEB6OJ4Cp0F65E4iJqp7f9W0cgAAAAAVevuXJ4TE00+nHPkDX6ze9mn3es90AAAAAAAAAAAAAAAAAAAddPYqrrxH5z0gHOiiaqsRGZWWm2dEca+Pp0S9Pp6aKeEces9ZdQYpiIjEcIZAAAAAAnkAIep0FNWZp9mfkq71mqirEx+kvQNLtqKqcTGQefEjV6Sbc96Z5T9kcAAAAAAAAAAAAAGaKZmqIjnIN9PZmu5iPznsu7FmKLeI/dppNPFu1jrPOXcAAAAAAAAAAAAGK6YmnExmJUut0v8OvvTPKfsu2l63FduYnlIPPje/ami5MT+8NAAAAAAAAAAAFlsvT/wBc/wCv6oFm3vXYiOsr6imKaIiOUA2AAAAAAAAAAAAAAABE2jp9+1mPep+cKd6NSa6zuX57TxgEcAAAAAAAAAFjsm1xmr8o+6ycdJb3dPTHpxdgAAAAAAAAAAAAAAAAEPadresZ60/RMa105omO8A88NrlOLkx2lqAAAAAAA6aejev0x3lzStmU51XiJkFyAAAAAAAAAAAAAAAAAAACl2jRjUz6oyw2vT7VM+ivAAAAAAATdk/jz4AFsAAAAAAAAAAAAAAAAAAACBtb8KPKrAAAAAH/2Q==",
"debit_card_number": 0,
"favorite_music": [],
"groups": [1],
"user_permissions": [],
"interests": ["Ski"]
}
Всегда возвращает TypeError:
user.interests.add(validated_data['interests'])
Exception Type: TypeError at /users/
Exception Value: unhashable type: 'list'
Я пробовал разные способы реализации "интересов" и "группы »в функции создания сериализатора.Я попытался проанализировать проверенные данные, выбрав дочерний элемент из Config_table и добавив его сюда, но ни один из них не работает.У меня на самом деле та же проблема с полем "группы".Кажется, что Django не может разархивировать проверенные данные в сериализаторе, и там он выдает ошибку.
Интересным моментом является то, что если я не заполняю поля "группа" и "интересы" при вызове метода POST, он работает нормально, и позже я могу обновить эти поля, вызвав PUT безпроблема.Что я могу сделать с этим?