2016-06-10 4 views
1

Ich habe ein Modell, das eine Session (sagen eine Stunde Klasse für Kinder), die eine Reihe von Task s, die eine Reihenfolge folgen müssen, darstellt. Einfacher zu verstehen:Django - Reorder (update) Objekte mit unique_together = (ForeignKey, IntegerField)

class Task(models.Model): 
    (...) 
    order = models.PositiveIntegerField('offset from the beginning of a Session') 
    session = models.ForeignKey(Session, related_name='tasks') 

    unique_together = ('session', 'order') 
    ordering = ('order',) 

Say I order (man stelle sich einen gemeinsamen Drag & Drop-Neuordnungs) einer Sitzung des aktualisieren möchten. Wenn ich also die Reihenfolge einer Aufgabe aktualisieren würde, müsste ich den Rest der Aufgaben neu ordnen, so dass die Eindeutigkeit nicht bremst.

Graphical Beispiel (sagen wir, ich Aufgabe in der zweiten Position zu sein mit pk=5014 wollen (order=1))

Initial state:     Final state: 

| pk | order | name |   | pk | order | name | 
|------|-------|------|   |------|-------|------| 
| 5011 | 0  | A |   | 5011 | 0  | A | 
| 5012 | 1  | B | ----> | 5014 | 1  | D | 
| 5013 | 2  | C |   | 5012 | 2  | B | 
| 5014 | 3  | D |   | 5013 | 3  | C | 

Meine Frage ist, wie es mit Django ORM (wenn möglich) zu aktualisieren oder was ein wäre elegante Weise, es zu tun, da ich nur daran denken kann, die gewünschte Aufgabe mit einer neuen Reihenfolge zu speichern (sagen Sie Ordnung = 50), dann ordnen Sie nacheinander die restlichen Aufgaben neu und ordnen schließlich die gewünschte Reihenfolge der gewünschten Aufgabe zu.

Gibt es so etwas wie ein bulk_update (Ich fand nichts ähnliches nach einer langen Forschung), die mir erlaubt, die order Felder für alle Aufgaben zu ändern und dann alle auf einmal zu speichern? Oder muss ich mich um dieses einzigartige Paar kümmern?

+1

Es ist in der Regel am besten bestehenden Lösungen wiederzuverwenden https://github.com/bfirsh/django-ordered-model obwohl es läuft immer noch auf 2 nacheinander speichert: http://dba.stackexchange.com/questions/131118/how-can-i-swap-zwei-Werte-von-bestimmten-Spalte-in-Tabelle-in-Postgres Siehe auch: https://www.djangopackages.com/grids/g/model- ordering/ Am besten wäre es, eine benutzerdefinierte SQL-Abfrage zu schreiben, etwas in der Richtung von http: //dba.stackexchange.com/questions/131118/how-can-i-swap-two-values-from-particular-spalte-in-tabelle-in-postgres Es ist auch eine gute Idee, DB Constraints als Ihre 'unique_together' – seeg

+0

Vielen Dank Wirklich viel, das war, was ich suchte. Ich schaue nach und berücksichtige alle Ideen! – vabada

+0

@seeg Wenn es Ihnen nichts ausmacht Ihren Kommentar als Antwort zu posten, werde ich ihn als akzeptiert markieren, da er mein Problem gelöst hat – vabada

Antwort

1

Es ist in der Regel am besten bestehenden Lösungen wiederzuverwenden:

https://github.com/bfirsh/django-ordered-model

obwohl es noch zu 2 in der Reihenfolge speichert läuft darauf hinaus:

https://github.com/bfirsh/django-ordered-model/blob/master/ordered_model/models.py#L122-L123

Siehe auch:

https://www.djangopackages.com/grids/g/model-ordering/

beste Wette wäre eine benutzerdefinierte SQL-Abfrage, etwas entlang der Linien von

gute Idee zu haben DB Einschränkungen als unique_together in Ihrem Beispiel Es ist auch

https://dba.stackexchange.com/questions/131118/how-can-i-swap-two-values-from-particular-column-in-a-table-in-postgres

zu schreiben.

0

Ich poste den Code, den ich entwickelt habe, als eine Lösung für mein Problem; Obwohl ich nicht ganz glücklich bin (ich denke da muss es irgendwie eine bessere Lösung geben), aber nur für den Fall, dass es jemandem hilft.

definiert ich diese Methode für das Modell Task:

def update_order(self, new_order): 
    """ 
    Update the order of this task and reorder the rest of tasks 
    of the session accordingly 
    """ 
    current_order = self.order 
    tasks = Task.objects.filter(session=self.session) 
    current_highest_order = tasks.last().order 
    if new_order > current_highest_order or new_order < 0: 
     raise ValidationError(_('New order out of range')) 
    operation = -1 if new_order < current_order else +1 
    # set temporary order higher than any other to allow reordering the rest 
    self.order = current_highest_order + 1 
    self.save() 
    # reassign the rest of tasks' order accordingly 
    tasks = Task.objects.filter(session=self.session) 
    for i in range(current_order, new_order, operation): 
     task = tasks[i + operation] if operation == -1 else tasks[i] 
     task.order -= operation 
     task.save() 
    # Restore a proper order value (the desired new_order) to this task 
    self.order = new_order 
    self.save() 

Alle Kommentare werden wirklich geschätzt.

Verwandte Themen