Mit django-rest-framework arbeiten Ich benutze einen Serializer mit vielen = True, nach bereits vorhandenen Elementen zu suchen und sie ungültig zu machen.Django Rest Framework: Einen einzelnen Teil eines multiserialisierten POST ungültig machen
Das Problem ist:
Wenn ein Teil einer Anforderung ungültig ist, die ganze Anforderung zurückgewiesen, ohne die gültigen Objekte zu schaffen.
Probe Nutzlast: [{'record_timestamp': '2016-03-04T09:46:04', 'reader_serial': u'00000000f9b320ac', 'card_serial': u'048EC71A0F3382', 'gps_latitude': None, 'gps_longitude': None, 'salt': 34, 'reader_record_id': 1063}, {'record_timestamp': '2016-03-04T09:46:06', 'reader_serial': u'00000000f9b320ac', 'card_serial': u'04614B1A0F3382', 'gps_latitude': None, 'gps_longitude': None, 'salt': 34, 'reader_record_id': 1064}]
Beispielantwort: [{"last_record_id":[2384],"error":["This record already exists"]},{}]
Ideal Antwort: [{"last_record_id":[2384],"error":["This record already exists"]},{'reader': 10, 'card': 12, 'gps_latitude': None, 'gps_longitude': None, 'reader_record_id': 1064}}]
ich den ersten Datensatz möchte den Fehler geben, aber der zweite Datensatz korrekt erstellt werden , wobei die Antwort das erzeugte Objekt ist.
class CardRecordInputSerializer(serializers.ModelSerializer):
class Meta:
model = CardRecord
fields = ('card', 'reader', 'bus', 'park', 'company', 'client',
'record_timestamp', 'reader_record_id')
read_only_fields = ('card', 'reader', 'bus', 'park', 'company'
'client')
def validate(self, data):
"""
Check that the record is unique
"""
#import ipdb; ipdb.set_trace()
hash_value = data.get("hash_value", None)
if CardRecord.objects.filter(hash_value=hash_value):
raise ValidationError(
detail={"error":"This record already exists",
"last_record_id":data.get("reader_record_id", None)})
else:
return data
def to_internal_value(self, data):
internal_value = super(CardRecordInputSerializer, self)\
.to_internal_value(data)
card_serial = data.get("card_serial", None).upper()
reader_serial = data.get('reader_serial', None).upper()
record_timestamp = data.get('record_timestamp', None)
date_altered = False
record_date = dateutil.parser.parse(record_timestamp)
#check if clock has reset to 1970
if record_date < datetime.datetime(2014, 4, 24):
record_date = datetime.datetime.now().isoformat()
date_altered = True
#create a hash to check that this record is unique
salt = data.get('salt', None)
hash_generator = hashlib.sha1()
hash_generator.update(card_serial)
hash_generator.update(reader_serial)
hash_generator.update(str(record_timestamp))
hash_generator.update(str(salt))
hash_value = str(hash_generator.hexdigest())
internal_value.update({
"card_serial": card_serial,
"reader_serial": reader_serial,
"salt": salt,
"hash_value": hash_value,
"record_timestamp": record_date,
"date_altered": date_altered
})
return internal_value
def create(self, validated_data):
#import ipdb; ipdb.set_trace()
'''
Create a new card transaction record
'''
try:
card_serial = validated_data.get('card_serial', None)
card = Card.objects.filter(uid=card_serial).last()
reader_serial = validated_data.get('reader_serial', None)
reader = Reader.objects.filter(serial=reader_serial).last()
#if we havent seen this reader before, add it to the list
if not reader:
reader = Reader.objects.create(serial=reader_serial)
company = card.company
client = reader.client
park = reader.park
record_timestamp = validated_data.get('record_timestamp', None)
reader_record_id = validated_data.get('reader_record_id', None)
#if datetime is naive, set it to utc
if record_timestamp.tzinfo is None \
or record_timestamp.tzinfo.utcoffset(d) is None:
record_timestamp = pytz.utc.localize(record_timestamp)
hash_value = validated_data.get('hash_value', None)
date_altered = validated_data.get('date_altered', None)
return CardRecord.objects.create(card = card,
reader = reader,
company = company,
client = client,
park = park,
record_timestamp = record_timestamp,
reader_record_id = reader_record_id,
hash_value = hash_value,
date_altered = date_altered)
#Usually a card that doesn't have company
except AttributeError:
return {
'status': 'Bad Request',
'message': 'One of the values was malformed or does not exist.'
}
Wie kann ich gültige Objekte erstellen und Fehler für die ungültigen Objekte bereitstellen?
Erhalten Sie Ihre Daten von einem Formular auf einer Webseite? Wenn dem so ist, denke ich, dass dies mehr Arbeit (und Ärger) sowohl auf der Vorder- als auch auf der Rückseite verursachen wird. Angenommen, Sie können dem Benutzer anzeigen, welche Instanzen ungültig sind. Da POST-Anfragen ** nicht ** idempotent sind (dh jedes Mal, wenn Sie die gleiche Anfrage machen, ist das Ergebnis anders - es erstellt jedes Mal eine neue Instanz, wenn Sie eine Anfrage stellen), müssen Sie auf der Front-End-Seite Entfernen Sie die bereits erstellten Objekte aus der Anforderungsnutzlast, sodass keine Duplikate erstellt werden. – iulian
@iulian Daten werden von einem Python Requests Rest Client empfangen. Die POSTs sind idempotent, da der Serialisierer prüft, ob dieses Objekt bereits existiert. Sie können 2 Erstellungsanforderungen für dasselbe Objekt senden, und nur 1 Objekt wird erstellt. Ich möchte, dass jedes Objekt separat behandelt wird, ohne dass für jedes Objekt eine neue HTTP-Anfrage erstellt werden muss. –