2010-01-03 2 views
2

Je cherchais un moyen de permettre à l'utilisateur de changer facilement l'ordre des entrées dans un formset. J'ai trouvé a StackOverflow question qui aborde ce sujet, avec la réponse acceptée référençant un Django Snippet qui utilise un outil JQuery pour permettre le glisser-déposer des entrées. C'est génial et cool, mais j'ai un problème avec les entrées 'supplémentaires'. Si une entrée « extra » est modifiée puis traîné je reçois une erreur sur le soumettre:Glisser-déposer du formset avec des entrées supplémentaires

(1048, "Column 'order' cannot be null")

je crois que Django conserve les entrées supplémentaires « » séparer, car ils doivent être insérés à la place des mises à jour. Donc, le réarrangement confonde probablement les choses. Existe-t-il un moyen de faire fonctionner ce système ou existe-t-il d'autres suggestions pour réorganiser et/ou ajouter de nouvelles entrées?

Modifier: Ajout de quelques extraits de code pertinents. J'essaie cela dans l'admin, comme le montre l'extrait. Je voudrais le mettre dans ma propre page en fin de compte, cependant.

models.py:

class Section(models.Model): 
    section_id = models.AutoField(primary_key=True) 
    section_name = models.CharField(max_length=135) 
    score_order = models.IntegerField() 
    def __unicode__(self): 
     return self.section_name 
    class Meta: 
     db_table = u'section' 
     ordering = [u"score_order"] 

class Chair(models.Model): 
    chair_id = models.AutoField(primary_key=True) 
    member = models.ForeignKey(Member, null=True, blank=True, 
     limit_choices_to={'current_member': True}) 
    section = models.ForeignKey(Section) 
    description = models.CharField(max_length=135) 
    order = models.IntegerField(blank=True, null=True) 
    def __unicode__(self): 
     return "%s - %s" % (self.description, self.member) 
    class Meta: 
     db_table = u'chair' 
     ordering = (u'section', u'order') 

admin.py

class SectionForm(forms.ModelForm): 
    model = Section 
    class Media: 
     js = (
      '/scripts/jquery.js', 
      '/scripts/ui.core.js', 
      '/scripts/ui.sortable.js', 
      '/scripts/section-sort.js', 
     ) 

class ChairInline(admin.StackedInline): 
    model = Chair 

admin.site.register(Section, 
        inlines = [ChairInline], 
        form = SectionForm, 
) 
+0

Pourriez-vous poster votre modèle et n'importe quel code de formulaire personnalisé pour donner un meilleur contexte? –

+0

En outre, tous les JS pertinents qui ne figurent pas dans les extraits liés. –

Répondre

2

J'ai trouvé ma propre solution. L'extrait définissait l'ordre pour chaque ligne ayant une valeur de clé primaire non vide. Mais les lignes supplémentaires ont une clé primaire vide, et je pense qu'elles doivent rester vides pour que Django sache qu'elles doivent être insérées au lieu d'être mises à jour. J'ai modifié la fonction de vérifier les autres champs étant vide (heureusement, je ne dispose que d'un couple), ainsi que la clé primaire:

jQuery(function($) { 
    $('div.inline-group').sortable({ 
     items: 'div.inline-related', 
     handle: 'h3:first', 
     update: function() { 
      $(this).find('div.inline-related').each(function(i) { 
       if ($(this).find('input[id$=chair_id]').val() || 
        $(this).find('select[id$=member]').val() || 
         $(this).find('select[id$=description]').val()) { 
        $(this).find('input[id$=order]').val(i+1); 
       } 
      }); 
     } 
    }); 
    $('div.inline-related h3').css('cursor', 'move'); 
    $('div.inline-related').find('input[id$=order]').parent('div').hide(); 
}); 

Cela a fait l'affaire pour moi. Je pourrais peut-être l'améliorer en ajoutant un champ caché au formulaire qui est défini chaque fois qu'un champ d'une rangée est modifié. Mais à ce stade, je suis toujours un jQuery n00b, donc cela va faire. Si quelqu'un a de meilleures idées, n'hésitez pas à commenter ou ajouter une autre réponse.

1

je formsets triables dans l'une de mes applications. J'utilise ce plugin drag and drop jQuery:

http://www.isocra.com/2008/02/table-drag-and-drop-jquery-plugin/

Je lie l'événement onDrop du plug-in à une fonction qui remet à zéro la valeur de tous les champs « ordre ».

De plus, je transmets les données initiales au formset de sorte que les champs supplémentaires "order" du formset ont toujours une valeur dans les cas où il n'y a pas de javascript disponible - l'utilisateur ne pourra pas réordonner les lignes, mais éditer et publier des modifications sans l'erreur null que vous avez décrite.

+0

Merci pour votre réponse. J'ai trouvé ma propre solution, que je posterai sous peu. Ce plugin ressemble au plugin jQuery UI que j'utilise. Je ne peux pas utiliser les valeurs initiales puisque j'utilise un [inline formset] (http://stackoverflow.com/questions/442040/pre-populate-an-inline-formset), et je ne pense pas que cela aiderait . Cela éviterait l'erreur, mais les lignes supplémentaires modifiées n'obtiendraient toujours pas l'ordre correct. Je ne sais pas, si vous avez ce travail, vous devez avoir résolu cela. –

Questions connexes