2008-12-16 28 views
7

Giả sử tôi muốn có một dự án, và một đối với các công việc cần làm và muốn sắp xếp lại các mục công việc tùy ý?trong SQL, hoặc Django ORM, cách thông thường để có một đơn đặt hàng là gì?

Trước đây, tôi đã thêm trường đơn hàng được đánh số và khi ai đó muốn thay đổi thứ tự, phải cập nhật tất cả các mục có số thứ tự mới của họ. Đây có lẽ là cách tiếp cận tồi tệ nhất, vì nó không phải là nguyên tử & yêu cầu một số cập nhật.

Tôi nhận thấy Django có giá trị CommaSeparatedIntegerField đa giá trị có thể chứa thứ tự bằng cách lưu các khóa đã đặt vào các mục trong bảng mục công việc phải trong một trường của bảng dự án.

Tôi đã cân nhắc hệ thống thập phân màu đỏ ở nơi nếu tôi muốn lấy mục 3 và đặt nó từ 1 đến 2, tôi sẽ thay đổi số đơn đặt hàng thành 1,5.

Có điều gì đó cho tôi biết có một lựa chọn dễ dàng hơn mà tôi đang thiếu ...

Bạn đặt hàng cho mối quan hệ một-nhiều như thế nào?

Trả lời

5

Tôi ghét vấn đề này ... và tôi luôn gặp phải vấn đề này.

Đối với trang web Django gần đây nhất của chúng tôi, chúng tôi có Bản tin chứa N Bài viết và, tất nhiên, thứ tự là quan trọng. Tôi đã gán thứ tự mặc định như Article.id tăng dần, nhưng điều này không thành công nếu các bài viết được nhập vào thứ gì đó khác với thứ tự "đúng".

Trên trang news_form.html Bản tin tôi đã thêm một chút phép thuật jQuery bằng cách sử dụng plugin Giao diện (http://interface.eyecon.ro/). Tôi hiển thị tiêu đề của các bài viết liên quan và người dùng có thể kéo chúng xung quanh theo ý muốn. Có một trình xử lý onChange để tính toán lại trường Article_id trong trường article_order.

Thưởng thức,
Peter

Đối với ứng dụng = nội dung, mô hình = Bản tin, sau đây là trong templates/admin/content/newslettter/change_form.html

{% extends 'admin/change_form.html' %} 

{% block form_top %}{% endblock %} 
{% block extrahead %}{{ block.super }} 
<script type="text/javascript" src="/media/js/jquery.js"></script> 
<script type="text/javascript" src="/media/js/interface.js"></script> 
<script> 
$(document).ready(
    function() { 
     $('ol.articles').Sortable(
      { 
       accept :  'sortableitem', 
       helperclass : 'sorthelper', 
       activeclass : 'sortableactive', 
       hoverclass : 'sortablehover', 
       opacity:  0.8, 
       fx:    200, 
       axis:   'vertically', 
       opacity:  0.4, 
       revert:   true, 
       trim:   'art_', 
       onchange: 
        function(list){ 
         var arts = list[0].o[list[0].id]; 
         var vals = new Array(); 
         var a; 
         for (a in arts) { 
          vals[a] = arts[a].replace(/article./, ''); 
         } 
         $('#id_article_order').attr('value', vals.join(',')); 
        } 
      }); 
    } 
); 
</script> 
{% endblock %} 

{% block after_related_objects %} 
{% if original.articles %} 
<style> 
.sortableitem { 
    cursor:move; 
    width: 300px; 
    list-style-type: none; 
    } 
</style> 

<h4>Associated Articles</h4> 
<ol class="articles" id="article_list"> 
{% for art in original.articles %} 
    <li id="article.{{art.id}}" class="sortableitem">{{art.title}}</li> 

{% endfor %} 
</ol> 
{% endif %} 
{% endblock %} 
1

Tôi đã chạy vào quá nhiều lần mà tôi đã giải quyết về việc quản lý các động này trong BL hoặc giao diện người dùng và sau đó chỉ cần duy trì thứ tự cho cột được xây dựng có mục đích khi người dùng hài lòng. SQL chỉ được thiết kế một cách có chủ ý để không xử lý các lệnh, và nó luôn chiến đấu trở lại.

2

"thêm một trật tự đánh số lĩnh vực "- tốt.

"cập nhật tất cả các mục có số thứ tự mới của chúng" - tránh được.

Sử dụng các số có khoảng trống.

  • Điểm nổi. Bằng cách đó, ai đó có thể chèn "1,1" giữa 1 và 2. Tôi thấy rằng điều này hoạt động độc đáo, như hầu hết mọi người có thể hiểu cách thức hoạt động của trình tự. Và bạn không phải lo lắng quá nhiều về bao nhiêu không gian để lại - có rất nhiều và rất nhiều không gian giữa mỗi số.

  • Trên tải ban đầu, hãy đếm số lượng bài viết theo 100 hoặc 1000 hoặc thứ gì đó có khoảng cách giữa mỗi bài. Trong trường hợp này, bạn phải đoán có bao nhiêu chữ số để lại để sắp xếp lại.

  • Vị trí được phân cách bằng dấu phẩy. Ban đầu, chúng là tất cả (1,0), (2,0), (3,0), vv Nhưng khi bạn muốn sắp xếp lại mọi thứ, bạn có thể phải giới thiệu (2,1) và (2,2) đi sau (2.0) nhưng trước (3.0).

    Điều này có vẻ phức tạp, nhưng một số người thích loại phức tạp này. Về bản chất, nó giống như dấu phẩy động, ngoại trừ một số duy nhất được thay thế bằng một bộ tóan (toàn bộ số, ẩn). Và điều này mở rộng để xử lý phân cấp.

+0

Tốt. Nhắc tôi về số dòng trong BASIC. :-) –

0

Đây là câu trả lời cuối cho câu hỏi, nhưng tôi chỉ muốn kêu gọi và chỉ ra rằng B-Trees là cấu trúc dữ liệu tuyệt vời cho loại điều này, đặc biệt là nếu mẫu truy cập của bạn không yêu cầu bạn để lấy toàn bộ danh sách cùng một lúc.

http://en.wikipedia.org/wiki/B-tree

2

Tôi đã gặp vấn đề này với hai dự án tôi đã làm việc trong một thời gian ngắn. Đối với giải pháp ví dụ của tôi, tôi có một "Biểu mẫu" có nhiều "Biến" được gán cho nó và thứ tự của các biến trên biểu mẫu cần phải được sắp xếp. Vì vậy, tôi đã thực hiện như sau:

models.py

class Form(models.Model): 
    FormName = models.CharField(verbose_name="Form Name:", max_length=40) 
    VariableOrder = models.CommaSeparatedIntegerField(default="[]", editable=False) 

    def __unicode__(self): 
     return "%s" % (self.FormName) 

class Variable(models.Model): 
    FormID = models.ForeignKey(Form, default=0, editable=False, related_name="Variable") 
    VarName = models.CharField(max_length=32, verbose_name="Name of variable in the database:") 

    def __unicode__(self): 
     return "%s" % self.VarName 

Mấu chốt từ trên là VariableOrder CommaSeparatedIntegerField là nơi chúng ta sẽ lưu trữ thứ tự của các biến trên Form, và chúng ta sẽ được sử dụng nó như là một danh sách python, đó là lý do tại sao mặc định là [].

Đối với mẫu, tôi hiển thị Biến của mình ở dạng mà chúng tôi sẽ thực hiện kéo và thả có thể sắp xếp (các phần tử danh sách mà tôi thực sự sử dụng có thêm kiểu dáng và thông tin liên quan đến CSS).

<ul id="sortable"> 

{% for Variable in VarList %} 
    <li id="{{ Variable.id }}">{{ Variable }}</li> 
{% endfor %} 

</ul> 

Bây giờ chúng tôi sẽ thực hiện kéo và thả danh sách cho việc thay đổi thứ tự. Để làm việc này bạn cần phải có đoạn AJAX CSRF từ trang web Django vào đầu

$(function() { 
    $("#sortable").sortable({ 
     placeholder: "ui-state-highlight", 
     update: function(event, ui){ 
      $.ajax({ 
      type:"POST", 
      url:"{% url builder.views.variableorder %}", 
      data: {Order: JSON.stringify($('#sortable').sortable('toArray')) }, 
      success: function(data){ 
      // Do stuff here - I don't do anything. 
      } 
      }); 
     } 
    }); 
    $("#sortable").disableSelection(); 
}); 

Phần quan trọng trên là "cập nhật" gọi hàm mỗi khi có sự thay đổi vị trí của bất kỳ các biến, sẽ gửi AJAX. toArray trên sortable cùng với stringify JSON được chúng tôi gửi từ trên xuống dưới của mỗi biến, được sử dụng bởi khung nhìn như sau. Lưu ý: Tôi giữ đối tượng Form đang hoạt động dưới dạng biến phiên, nhưng trong trường hợp khác, bạn chỉ cần gọi đối tượng Biểu mẫu mà bạn muốn thay đổi thứ tự.

def variableorder(request): 
    if request.is_ajax(): 
     Order = request.POST['Order'] 
     updateOrder = request.session['FormID'] 
     updateOrder.VariableOrder = newOrder 
     updateOrder.save() 
     request.session['FormID'] = Form.objects.get(id=updateOrder.id) 
     return HttpResponse("Order changed.") 
    else: 
     pass 

Mấu chốt của tất cả điều này là bạn có thể sử dụng CommaSeparatedIntegerField này như một danh sách bằng cách đánh giá chuỗi.Ví dụ:

Thêm một biến:

aForm = Form.objects.get(id=1) 
currentOrder = aForm.VariableOrder 
currentOrder = eval(currentOrder) 
newVar = Variable(stuff in here) 
newVar.save() 
currentOrder.append(newVar.id) 
aForm.VariableOrder = currentOrder 
aForm.save() 

Loại bỏ một Variable:

aForm = Form.objects.get(id=1) 
currentOrder = aForm.VariableOrder 
currentOrder = eval(currentOrder) 
# Variable ID that we want to delete = 3 
currentOrder.remove(3) 
aForm.VariableOrder = currentOrder 
aForm.save() 

Rendering các biến trong tự:

aForm = Form.objects.get(id=1) 
currentOrder = aForm.VariableOrder 
currentOrder = eval(currentOrder) 
VarList = [] 
for i in currentOrder: 
    VarList.append(Variable.objects.get(id=i)) 

Đây là bản nháp đầu tiên về những gì tôi sẽ sử dụng, nhưng nó hoạt động tốt cho tôi. Sự cải thiện rõ ràng đầu tiên là việc đánh giá danh sách python là một phương thức trong lớp. ví dụ.

def getVarOrder(self): 
    return eval(self.VariableOrder) 

và sau đó chỉ cần gọi Form.getVarOrder() khi muốn thao tác danh sách. Trong mọi trường hợp, hy vọng điều này sẽ giúp ích.

JD

Các vấn đề liên quan