2017-09-29 3 views
0

TL; DR: Comment sauvegarder/valider plusieurs objets avec un attribut unique en utilisant un formset?Enregistrer plusieurs objets avec un attribut unique en utilisant Django formset

Disons que j'ai un Machine qui a plusieurs Setting s (voir les modèles ci-dessous). Ces paramètres doivent avoir une commande unique dans la machine. Ceci peut être accompli en définissant un attribut unique_together dans la classe Meta du modèle Setting:

unique_together = (('order', 'machine'),) 

Cependant, j'utilise un formset en ligne pour mettre à jour tous les Setting s d'un Machine. Supposons que j'ai les informations suivantes dans mon formset:

  • Réglage 1: machine = 1; order = 1
  • Réglage 2: machine = 1; order = 2

Si je devais changer l'ordre sur les deux Setting s:

  • Réglage 1: machine = 1; order = 2
  • Réglage 2: machine = 1; order = 1

et enregistrez le formulaire en utilisant le morceau de code suivant:

self.object = machine_form.save() 
settings = setting_formset.save(commit=False) 
for setting in settings: 
    setting.machine = self.object 
    setting.save() 

Puis-je obtenir une erreur unique depuis que je Constraint essaie de sauver Réglage 1 avec ordre = 2, mais Réglage 2 a toujours cet ordre. Je n'arrive pas à trouver une solution propre à ce problème. Je souhaite conserver la contrainte unique_together pour garantir l'exactitude de mes données. Je sais comment résoudre cela dans le frontend en utilisant Javascript, mais je veux une vérification dans mes modèles/formulaires. Looping sur les lignes de formset semble possible, mais laid?

class Machine(models.Model): 
    name = models.CharField(max_length=255) 

class Setting(models.Model): 
    name = models.CharField(max_length=255) 
    machine = models.ForeignKey(Machine, on_delete=models.CASCADE) 
    order = models.PositiveSmallIntegerField() 

Répondre

0

Il semble impossible de contraindre l'ordre au niveau de la base de données. Je ne dis pas que ce n'est pas possible, mais je ne sais pas comment.

Pour l'instant, j'ai ajouté une vérification dans mon formset. Je vais le laisser ici au cas où quelqu'un a un problème similaire.

class BaseSettingFormSet(BaseInlineFormSet): 
    '''FormSet to update the order of Settings in a Machine''' 

    def clean(self): 
     '''Checks if there are no two Settings with the same order.''' 
     if any(self.errors): 
      return 
     orders = [] 
     for form in self.forms: 
      if form.cleaned_data: 
       order = form.cleaned_data['order'] 
       if order in orders: 
        form.add_error('order', _('The order of each setting must be unique')) 
       else: 
        orders.append(order)