我正在尝试发布 json 文件并将模型保存到数据库中。 AttributeName 和 AttributeValue 已正确生成,但保存的属性没有“nazev_atributu_id”和“hodnota_atributu_id”。
[
{
"AttributeName": {
"id": 2,
"nazev": "Barva"
}
},
{
"AttributeValue": {
"id": 2,
"hodnota": "modrá"
}
},
{
"Attribute": {
"id": 1,
"nazev_atributu_id": 2,
"hodnota_atributu_id": 2
}
}
]
模型.py
from django.db import models
class AttributeValue(models.Model):
unique_id = models.AutoField(primary_key=True)
id = models.IntegerField(unique=True)
hodnota = models.CharField(max_length=255, null=True, blank=True)
def __str__(self):
return f"AttributeValue with id: {self.id}"
class AttributeName(models.Model):
unique_id = models.AutoField(primary_key=True)
id = models.IntegerField()
nazev = models.CharField(max_length=255, null=True, blank=True)
kod = models.CharField(max_length=255, null=True, blank=True)
zobrazit = models.BooleanField(default=False)
def __str__(self):
return f"AttributeName with id: {self.id}"
class Attribute(models.Model):
unique_id = models.AutoField(primary_key=True)
id = models.IntegerField(unique=True)
nazev_atributu_id = models.ManyToManyField(AttributeName, through='AttributeAttributeNameMapping')
hodnota_atributu_id = models.ManyToManyField(AttributeValue, through='AttributeAttributeValueMapping')
def __str__(self):
return f"Attribute with id: {self.id}"
class AttributeAttributeNameMapping(models.Model):
attribute = models.ForeignKey(Attribute, on_delete=models.CASCADE)
attribute_name = models.ForeignKey(AttributeName, on_delete=models.CASCADE)
class Meta:
unique_together = ('attribute', 'attribute_name')
class AttributeAttributeValueMapping(models.Model):
attribute = models.ForeignKey(Attribute, on_delete=models.CASCADE)
attribute_value = models.ForeignKey(AttributeValue, on_delete=models.CASCADE)
class Meta:
unique_together = ('attribute', 'attribute_value')
序列化器
from rest_framework import serializers
from .models import *
class AttributeNameSerializer(serializers.ModelSerializer):
class Meta:
model = AttributeName
fields = '__all__'
class AttributeValueSerializer(serializers.ModelSerializer):
class Meta:
model = AttributeValue
fields = '__all__'
class AttributeSerializer(serializers.ModelSerializer):
nazev_atributu_id = serializers.SlugRelatedField(queryset=AttributeName.objects.all(),slug_field='id')
hodnota_atributu_id = serializers.SlugRelatedField(queryset=AttributeValue.objects.all(),slug_field='id')
class Meta:
model = Attribute
fields = ["unique_id", "id", "nazev_atributu_id", "hodnota_atributu_id"]
def create(self, validated_data):
# Extract many-to-many fields from the validated data
print("**************************")
print(validated_data)
print("**************************")
nazev_atributu_id = validated_data.pop('nazev_atributu_id')
hodnota_atributu_id = validated_data.pop('hodnota_atributu_id')
# Create the Attribute instance
attribute = Attribute.objects.create(**validated_data)
print("???????????????????")
print(nazev_atributu_id.__dict__)
print(hodnota_atributu_id.__dict__)
print("?????????????")
print(attribute, type(attribute))
print(attribute.__dict__)
print("------------------")
print(attribute.nazev_atributu_id)
print(attribute.hodnota_atributu_id)
print("------------------")
# Set many-to-many relationships
attribute.nazev_atributu_id.add(nazev_atributu_id)
attribute.hodnota_atributu_id.add(hodnota_atributu_id)
print("////////////////////")
print(attribute.__dict__)
print("////////////////////")
return attribute
但还是不明白为什么属性前后相同
attribute.nazev_atributu_id.add(nazev_atributu_id)
attribute.hodnota_atributu_id.add(hodnota_atributu_id)
这是调用post请求后的打印输出:
**************************
{'id': 1, 'nazev_atributu_id': <AttributeName: AttributeName with id: 2>, 'hodnota_atributu_id': <AttributeValue: AttributeValue with id: 2>}
**************************
???????????????????
{'_state': <django.db.models.base.ModelState object at 0x000001E7E56E99D0>, 'unique_id': 206, 'id': 2, 'nazev': 'Barva', 'kod': None, 'zobrazit': False}
{'_state': <django.db.models.base.ModelState object at 0x000001E7E56E9070>, 'unique_id': 214, 'id': 2, 'hodnota': 'modrá'}
?????????????
Attribute with id: 1 <class 'api.models.Attribute'>
{'_state': <django.db.models.base.ModelState object at 0x000001E7E56E9310>, 'unique_id': 78, 'id': 1}
------------------
api.AttributeName.None
api.AttributeValue.None
------------------
////////////////////
{'_state': <django.db.models.base.ModelState object at 0x000001E7E56E9310>, 'unique_id': 78, 'id': 1}
////////////////////
观点
class LoadJson(viewsets.ModelViewSet):
def create(self, request):
post_successful = True
over_all_result_ok = []
over_all_result_nok = []
sorted_json = sort_json_data(request.data, get_model_ordering())
for item in sorted_json:
model_type = list(item.keys())[0]
model_values = list(item.values())[0]
result = serialize_model(model_type, model_values)
if result[0] is False:
post_successful = False
add_result_into_dict(over_all_result_nok, model_type, result)
else:
add_result_into_dict(over_all_result_ok, model_type, result)
if post_successful:
return Response({"status": over_all_result_ok}, status=status.HTTP_201_CREATED)
return Response({"status": over_all_result_nok}, status=status.HTTP_400_BAD_REQUEST)
def get_model_ordering():
# model_ordering = [
# 'AttributeName', 'AttributeValue', 'Attribute',
# 'Product', 'ProductAttributes', 'Image',
# 'ProductImage', 'Catalog'
# ]
model_ordering = [
'AttributeName', 'AttributeValue', 'Attribute',
]
return model_ordering
def sort_json_data(json_data, model_ordering):
sorted_list = []
for process in model_ordering:
for item in json_data:
if list(item.keys())[0] == process:
sorted_list.append(item)
return sorted_list
def add_result_into_dict(over_all_result, model_type, result):
over_all_result.append(
{
"model_type": model_type,
"result": result[0],
"message": result[1]
}
)
return over_all_result
def serialize_model(model_type, model_values):
serializer_class = SerializersLink().get_serializer_class(model_type)
if serializer_class:
serializer = serializer_class(data=model_values)
if serializer.is_valid():
serializer.save()
return True, f"Json data '{model_values}' for model '{model_type}' are correct according serializer"
else:
return False, f"Invalid json data '{model_values}' input in model type: '{model_type}'"
else:
return False, f"Not implemented model type: '{model_type}'"
class LoadJson(viewsets.ModelViewSet):
def create(self, request):
post_successful = True
over_all_result_ok = []
over_all_result_nok = []
sorted_json = sort_json_data(request.data, get_model_ordering())
for item in sorted_json:
model_type = list(item.keys())[0]
model_values = list(item.values())[0]
result = serialize_model(model_type, model_values)
if result[0] is False:
post_successful = False
add_result_into_dict(over_all_result_nok, model_type, result)
else:
add_result_into_dict(over_all_result_ok, model_type, result)
if post_successful:
return Response({"status": over_all_result_ok}, status=status.HTTP_201_CREATED)
return Response({"status": over_all_result_nok}, status=status.HTTP_400_BAD_REQUEST)
class SerializersLink:
def __init__(self):
# self._map_dict = {
# "AttributeName": AttributeNameSerializer,
# "AttributeValue": AttributeValueSerializer,
# "Attribute": AttributeSerializer,
# "Product": ProductSerializer,
# "ProductAttributes": ProductAttributesSerializer,
# "Image": ImageSerializer,
# "ProductImage": ProductImageSerializer,
# "Catalog": CatalogSerializer,
# }
self._map_dict = {
"AttributeName": AttributeNameSerializer,
"AttributeValue": AttributeValueSerializer,
"Attribute": AttributeSerializer,
}
def get_serializer_class(self, model_name):
if model_name in self._map_dict:
return self._map_dict[model_name]
return False
使用自定义 BaseManyToManySerializer:
class BaseManyToManySerializer(serializers.ModelSerializer):
def to_internal_value(self, data):
data = dict(data)
for field_name, model_class in self.get_id_conversion_mappings():
self._convert_ids_to_unique_ids(data, field_name, model_class)
return super().to_internal_value(data)
def _convert_ids_to_unique_ids(self, data, field_name, model_class):
if field_name in data:
ids = data.get(field_name)
if not isinstance(ids, list):
ids = [ids]
objects = model_class.objects.filter(id__in=ids)
id_map = {}
for obj in objects:
if obj.id not in id_map:
id_map[obj.id] = []
id_map[obj.id].append(obj.unique_id)
data[field_name] = [unique_id for id in ids for unique_id in id_map.get(id, [])]
def create(self, validated_data):
many_to_many_data = {field_name: validated_data.pop(field_name, []) for field_name, field_class in
self.get_many_to_many_fields()}
instance = self.Meta.model.objects.create(**validated_data)
for field_name, field_class in self.get_many_to_many_fields():
if field_name in many_to_many_data:
field_value = many_to_many_data[field_name]
if hasattr(instance, field_name):
getattr(instance, field_name).set(field_value)
return instance
def to_representation(self, instance):
representation = super().to_representation(instance)
for field_name, field_class in self.get_many_to_many_fields():
if hasattr(instance, field_name):
representation[field_name] = [item.id for item in getattr(instance, field_name).all()]
return representation
def get_id_conversion_mappings(self):
raise NotImplementedError("Subclasses must implement this method.")
def get_many_to_many_fields(self):
raise NotImplementedError("Subclasses must implement this method.")
具体用法:
class AttributeSerializer(BaseManyToManySerializer):
nazev_atributu_id = serializers.PrimaryKeyRelatedField(queryset=AttributeName.objects.all(), many=True,
required=False)
hodnota_atributu_id = serializers.PrimaryKeyRelatedField(queryset=AttributeValue.objects.all(), many=True,
required=False)
class Meta:
model = Attribute
fields = ["unique_id", "id", "nazev_atributu_id", "hodnota_atributu_id"]
def get_id_conversion_mappings(self):
return [
('nazev_atributu_id', AttributeName),
('hodnota_atributu_id', AttributeValue)
]
def get_many_to_many_fields(self):
return [
('nazev_atributu_id', AttributeName),
('hodnota_atributu_id', AttributeValue)
]