/ / Modèle de validation de champ datetime pour les champs avec auto_now - django, datetime, python-3.x, django-rest-framework

Modèle de validation de champ datetime pour les champs avec auto_now - django, datetime, python-3.x, django-rest-framework

Je suis très nouveau dans django et python en général, et j'essayais d'apprendre rest_framework pour créer des API RESTful.

J'ai donc un modèle comme celui-ci:

class Listing(models.Model):
listingid           = models.BigIntegerField(primary_key=True)
sellerid            = models.IntegerField()
createdon           = models.DateTimeField(auto_now_add=True, editable=False)
expirydate          = models.DateTimeField(null=True)
validationstatus    = models.SmallIntegerField(default=0)
listingstatus       = models.SmallIntegerField(
choices=((0, "Active"),
(1, "Hidden"),
(2, "Suspended"),
(4, "Expired"),
(5, "Deleted"),
),
default=0)

Maintenant, je dois valider que le date d'expiration est toujours supérieur au créé sur rendez-vous amoureux.

Je sais que je peux le faire dans les vues, je suppose que ce ne serait pas une bonne idée, puisque maintenant la validation n'existe que dans les vues.
Cela me laisse donc avec les sérialiseurs et le modèle.

Je sais que je peux passer outre save méthode pour faire vérifier ceci comme ceci:

class MasterListing(models.Model):
# fields here..

def save(self, *args, **kwargs):
if self.expirydate > self.createdon:
super().save(*args, **kwargs)
return ValidationError("Expiry date cannot be greater than created date ("++")")

mais je ne sais pas si ce serait une bonne idée, puisque maintenant je lève une erreur que le programmeur peut oublier d'attraper. Je ne sais pas non plus si les champs seraient remplis lorsque cette méthode s'exécuterait.
Une autre façon dont je lis dans la documentation est la clean méthode que je ne pouvais pas vraiment comprendre si bien.

Quelqu'un peut-il me guider sur la façon de gérer des situations comme celle-ci lorsque vous travaillez avec le rest_framework?
Certaines des choses que j'ai lues sur la validation jusqu'à présent:

  1. Validation du sérialiseur
    • Validation au niveau du terrain
    • Validateurs
  2. Validation du modèle
    • passer outre clean méthode
    • passer outre save méthode
  3. Faites-le simplement manuellement dans les vues

Il semble y avoir tellement d'options, et je pourraisai même laissé quelques-uns, je ne pouvais pas clairement me faire une idée de quand utiliser où. Je suis désolé si c'est un peu au niveau débutant, mais je suis nouveau dans les frameworks et django semble être très différent de ce que je faisais en PHP. Tout conseil est le bienvenu!

Edit: J'utiliserai django pour le rest_framework uniquement et rien d'autre, car nous voulons uniquement construire des API RESTful.

Réponses:

4 pour la réponse № 1

Framework Django REST utilisé pour appeler Model.clean, qui était auparavant l'emplacement recommandé pour mettre la logique de validation qui devait être utilisée dans les formulaires Django et les sérialiseurs DRF. À partir de DRF 3.0, Ce n'est plus le cas et Model.clean ne sera plus appelé pendant le cycle de validation. Avec ce changement, il existe désormais deux emplacements possibles pour insérer une logique de validation personnalisée qui fonctionne sur plusieurs champs.

Si vous n'utilisez que le framework Django REST pour la validation, et vous n’avez pas d’autres zones où les données doivent être validées manuellement (comme un ModelForm, ou dans l'admin Django), alors vous devriez examiner Framework de validation du framework Django REST.

class MySerializer(serializers.ModelSerializer):
# ...

def validate(self, data):
# The keys can be missing in partial updates
if "expirydate" in data and "createdon" in data:
if data["expirydate"] < data["createdon"]:
raise serializers.ValidationError({
"expirydata": "Expiry date cannot be greater than created date",
})

return super(MySerializer, self).validate(data)

Si vous avez besoin d'utiliser le framework Django REST en combinaison avec un composant Django qui utilise la validation au niveau du modèle (comme l'admin Django), vous avez deux options.

  1. Dupliquez votre logique dans les deux Model.clean et Serializer.validate, violant le Principe DRY et vous ouvrir aux problèmes futurs.
  2. Faites votre validation dans Model.save et j'espère que rien d'étrange n'arrivera plus tard.

mais je ne sais pas si ce serait une bonne idée, puisque maintenant je lève une erreur que le programmeur peut oublier d'attraper.

Je me risquerais à dire que il vaudrait mieux que l'erreur soit soulevée que les données sauvegardées deviennent éventuellement invalides exprès. Une fois que vous commencez à autoriser les données invalides, vous devez effectuer des vérifications partout où les données sont utilisées réparer. Si vous ne l'autorisez pas à entrer dans un état invalide, vous ne rencontrez pas ce problème.

Je ne sais pas non plus si les champs seraient remplis lorsque cette méthode s'exécuterait.

Vous devez être en mesure de supposer que si un objet doit être enregistré, les champs ont déjà été remplis avec leurs valeurs.


2 pour la réponse № 2

Si vous souhaitez à la fois la validation du modèle etValidation du sérialiseur à l'aide de Django REST Framework 3.0, vous pouvez forcer votre sérialiseur à utiliser la validation du modèle comme ceci (vous ne vous répétez donc pas):

import rest_framework, django
from rest_framework import serializers

class MySerializer(serializers.ModelSerializer):
def validate(self, data):
for key, val in data.iteritems():
setattr(self.instance, key, val)
try:
self.instance.clean()
except django.core.exceptions.ValidationError as e:
raise rest_framework.exceptions.ValidationError(e.message_dict)

return data

J'ai pensé à générer une nouvelle fonction à partir du code de la fonction clean () de mon modèle et à la faire cracher django.core.exceptions.ValidationError ou rest_framework.exceptions.ValidationError, basé sur un paramètre source (ou quelque chose) à la fonction. Ensuite, je l'appellerais à partir du modèle et du sérialiseur. Mais cela ne me paraissait guère mieux.


0 pour la réponse № 3

Si vous voulez vous assurer que vos données sont valides au niveau le plus bas, utilisez la validation de modèle (elle doit être exécutée par la classe de sérialiseur ainsi que par les classes de formulaire (modèle) (par exemple, admin)).

Si vous souhaitez que la validation se produise uniquement dans votre API / formulaires, placez-le dans une classe de sérialiseur / formulaire. Le meilleur endroit pour valider devrait donc être Model.clean().

La validation ne devrait jamais avoir lieu dans les vues, car elles ne devraient pas être trop gonflées et la vraie logique métier devrait être encapsulée dans des modèles ou des formes.