Django-tables2: صفوف الجدول مكررة بعد الفرز حسب رأس العمود

تم إنشاؤها على ٣ أغسطس ٢٠١٦  ·  32تعليقات  ·  مصدر: jieter/django-tables2

أواجه مشكلة حيث يتم عرض بعض الصفوف عدة مرات بدلاً من صفوف أخرى. تم استخدام الجدول المعني لتقديم صورة جيدة تمامًا في الإصدارات السابقة من django و django-table2. لقد قمت بترقية كلاهما في نفس الوقت إلى أحدث إصدار لكل منهما (django 1.10 ، django-table2 1.2.4) ثم بدأت هذه المشكلة في الحدوث.

شاهد هذه الصورة هنا لعرض توضيحي: http://imgur.com/a/pPRT8

عندما أقوم بتحميل جدول بدون اختيار ترتيب فرز حسب العمود ، لا أرى هذه المشكلة. بمجرد النقر فوق رأس العمود لتغيير ترتيب الفرز ، يتم تكرار الصفوف.

لقد حددت حتى الآن أن البيانات التي تم تمريرها إلى كائن BoundRows صحيحة ، مع عدم وجود عناصر مكررة. ومع ذلك ، يؤدي التكرار خلال الصفوف المنضمة إلى إرجاع إدخالات مكررة. لذلك يبدو أن شيئًا ما قد يغير كائن البيانات أثناء حدوث التكرار.

تحدث هذه المشكلة على جداول بطول 150 تقريبًا ، ولم أتمكن (بعد) من إعادة إنتاج هذه المشكلة باستخدام مجموعة بيانات اختبار أصغر.

يوضح هذا المقتطف رمز الاختبار الذي استخدمته لتضييق سبب المشكلة.

--- a/django_tables2/rows.py
+++ b/django_tables2/rows.py
@@ -8,6 +8,7 @@ from django.utils import six
 from .columns.linkcolumn import BaseLinkColumn
 from .utils import A, AttributeDict, call_with_appropriate, computed_values

+import sys

 class BoundRow(object):
     """
@@ -187,9 +188,17 @@ class BoundRows(object):
     def __init__(self, data, table):
         self.data = data
         self.table = table
+        for d in data:
+            print >>sys.stderr, d
+
+        print >>sys.stderr, "end data"
+

     def __iter__(self):
         for record in self.data:
+            print >>sys.stderr, "__iter__", record
             yield BoundRow(record, table=self.table)
bug

التعليق الأكثر فائدة

wohoo ، تم إصلاحه أخيرًا!

نعم ، سأطلق سراحه في غضون ساعة.

ال 32 كومينتر

تؤدي بلورة مجموعة الاستعلام عبر list () إلى إيقاف حدوث المشكلة:

+++ b/django_tables2/rows.py
@@ -8,6 +8,7 @@ from django.utils import six
 from .columns.linkcolumn import BaseLinkColumn
 from .utils import A, AttributeDict, call_with_appropriate, computed_values

+import sys

 class BoundRow(object):
     """
@@ -187,9 +193,26 @@ class BoundRows(object):
     def __init__(self, data, table):
         self.data = data
         self.table = table


     def __iter__(self):
+        print >>sys.stderr, type(list(self.data.data))

شكرًا على الإبلاغ ، الإرسال إلى القائمة غير مقبول كحل لأن ذلك لن يعمل مع مجموعات البيانات الأكبر.

هل يمكنك محاولة الرجوع إلى إصدار أقدم من إصدار django-table2 للتأكد من أنها ليست مشكلة في تحديث إصدار Django الخاص بك؟

نعم بالتأكيد ليس حلاً - لكنه قد يكون مؤشراً على السبب. السبب الآخر في أن التحويل إلى القائمة ليس حلاً مناسبًا لأنه لا يبدو دائمًا أنه مجموعة استعلام تحتوي على البيانات على أي حال ، وفي هذه الحالة لن تكون بيانات self.data موجودة.

wtfrank ، أرى أنه من المفيد حقًا إذا كان بإمكانك تقديم حالة اختبار

أعتقد أنني أواجه نفس المشكلة: في الجدول الخاص بي ، هناك صف مفقود وآخر مكرر ... بالنسبة لي بدأ هذا مع الإصدار 1.2.2.
الرجوع إلى الإصدار 1.2.1 "fixxes" هو المشكلة بالنسبة لي .... هل هناك أي معلومات يمكنني تقديمها لتسهيل البحث؟

سيكون من الجيد حقًا الحصول على الحد الأدنى من حالة الاختبار. يمكننا بعد ذلك تشغيل git bisect للعثور على الالتزام السيئ.

أنا أبحث في حالة اختبار في الوقت الحالي ، ولكن الغريب أنني لا أستطيع إعادة إظهار المشكلة في بيئة الاختبار الخاصة بي ...

محليًا (باستخدام ./manage runserver باستخدام sqlite) كل شيء على ما يرام ، بينما في الإنتاج (تشغيل uwsgi و mysql) توجد مشكلة المغفلين ... (تعمل كلتا البيئتين على إصدارات متساوية)

لا تحتوي مجموعة الاستعلام على أي مغفلين .... ولكن في الوقت الذي يتم فيه تقديم table.html ، تفتقد مجموعة الاستعلام كائنًا واحدًا وآخر مكرر ...

ونأمل أن نعود إليك قريبًا في حالة اختبار :)

تحدث المشكلة أيضًا في الإصدار 1.2.6. أعتقد أنه شيء مع # 329 أو # 330 لكن حتى الآن لا يمكنني إيجاد طريقة لإصلاحه.

هذه تنطبق فقط على 1.2.6 ، لذلك لا أتوقع أن يكونوا مصدر هذا الخطأ.

عذرًا ، لا يمكنني تقديم حالة مناسبة قابلة لإعادة الإنتاج ، لكن لدي للتو هذه المشكلة (أو ، على الأقل ، أعتقد أنها هذه المشكلة) ويمكنني القول أنها حدثت بالتأكيد بين 1.2.1 و 1.2.2 .

كلما رجعت إلى الإصدار 1.2.1 ، كل شيء يبدو على ما يرام. عندما أقوم بالترقية إلى 1.2.2 أو أعلى (بدأت مع الإصدار 1.2.6 الأحدث ، بالطبع) ، أفقد الصف الأول باستمرار (من بين ثلاثة لدي في DB) وأحصل على نسخة من صف آخر بدلاً من ذلك. على سبيل المثال ، عندما يكون لدي 1.2.1:

| التاريخ | يضرب | ... |
| --- | --- | --- |
| 2016-11-08 | 123 | ... |
| 2016-11-07 | 321 | ... |
| 2016-11-06 | 0 | ... |

في 1.2.2-1.2.6 ، أحصل دائمًا على هذا بدلاً من ذلك:

| التاريخ | يضرب | ... |
| --- | --- | --- |
| 2016-11-06 | 0 | ... |
| 2016-11-07 | 321 | ... |
| 2016-11-06 | 0 | ... |

أنا أستخدم Django 1.9.9 على Python 2.7.12 ، وقد بدأ المشروع باستخدام pydanny / cookiecutter-django (على الرغم من تعديله بشكل كبير بعد ذلك) ، ويبدو الكود الخاص بي كما يلي:

class DailySummaryTable(tables.Table):
    class Meta:
        model = DailySummary
        attrs = {"class": "paleblue"}
        empty_text = _("No stats yet")
        fields = ("date", "hits", ...long boring list...)
        # order_by = ("-date",)
        # orderable = False

النموذج Meta يحتوي فقط على عناصر verbose_name{,_plural} ، والمشاهدة عبارة عن DetailView بسيط يبدو كالتالي:

class SourceDetailView(LoginRequiredMixin, DetailView):
    model = Source
    ...
    def get_context_data(self, **kwargs):
        ctx = super(...)
        ctx["stats"] = DailySummaryTable(DailySummary.objects.filter(source=self.object))
        return ctx

وهناك ثلاثة صفوف في DB (PostgreSQL 9.6) ، وكلها لها نفس source_id (لديّ واحد فقط) ، لذا فهم جميعًا يطابقون الاستعلام. الغريب ، إذا استبدلت .filter(source=...) بـ .all() يبدو أن المشكلة تختفي.

هذا كل ما تمكنت من اكتشافه. آمل أن يساعد. أعتقد ، سألتزم فقط بـ 1.2.1 في الوقت الحالي :)

شكرًا لإظهار تجوالك ، سأبحث في هذه المشكلة لاحقًا.

لقد واجهت نفس المشكلة ، بلورة مجموعة الاستعلام عبر list () ليس حلاً قابلاً للتطبيق من جانبنا أيضًا.

@ op-alex-reid هل تستطيع mlyou محاولة تحويل حالة الاستخدام الخاصة بك إلى الحد الأدنى من حالة الاختبار القابلة للتكرار؟

أواجه نفس المشكلة (Django == 1.9، django-table == 1.2.3) مع الكود التالي:

class UserPlayerTable(tables.Table):
    actions = tables.LinkColumn('player:my_players_detail', args=[A('slug')],
                                text=_('View / Edit'),
                                verbose_name=_('View / Edit'), empty_values=())
    embed = tables.LinkColumn('player:my_players_embed', args=[A('slug')],
                                text=_('View / Embed now'),
                                verbose_name=_('View / Embed now'), empty_values=())

    class Meta:
        template = 'tables/table.html'
        model = Player
        fields = ('created', 'slug', 'actions', 'embed')
        attrs = {"class": "changeset"}
        order_by = ['-created']
        orderable = False

و

UserPlayerTable(Player.objects.filter(user=context['impersonate_user']))

من المثير للاهتمام ، عندما أقوم بتعيين orderable = True ، لا تحدث المشكلة.

في حالتي ، تبلور مجموعة الاستعلام عبر list () _is_ خيار (والإصلاح في الوقت الحالي) ، حيث لا يوجد سوى 5 صفوف على الأكثر في الجدول.

شكرا على المثال!

حاولت إعادة إنتاج هذا باستخدام هذا الرمز:

class Player(models.Model):
    person = models.ForeignKey(Person)
    created = models.DateTimeField(auto_now_add=True)
    score = models.PositiveIntegerField()

def test_issue_361(per_page=5):

    bob = Person.objects.create(first_name='Bob', last_name='Builder')
    eve = Person.objects.create(first_name='Eve', last_name='Dropper')

    for i in range(10):
        Player.objects.create(person=bob, score=randint(0, 200))
        Player.objects.create(person=eve, score=randint(200, 400))
        Player.objects.create(person=bob, score=5)
        Player.objects.create(person=eve, score=5)

    class UserPlayerTable(tables.Table):
        class Meta:
            model = Player
            fields = ('person.name', 'score',)
            order_by = ['-score']
            orderable = False

    queryset = Player.objects.filter(score=5)

    table = UserPlayerTable(queryset)
    RequestConfig(request, paginate={'per_page': per_page}).configure(table)
    html = table.as_html(request)

    # count the number of rows, subtract one for the header
    assert (html.count('<tr') - 1) == per_page

لكن هذا لا ينتج عنه صفوف مكررة ...

واجهت نفس المشكلة اليوم. أنا أستخدم django-table2 == 1.2.9 في مشروع Django == 1.10 ، حيث أستخدم أيضًا مرشحات django == 1.0.1.

ومن المثير للاهتمام أن مضاعفة الصفوف في الجدول الخاص بي تحدث فقط إذا

  1. هناك العديد من المداخل لعرضها
    (لذلك إذا قمت بتمكين ترقيم الصفحات مع 25 سجلًا لكل صفحة ، فسيكون كل شيء على ما يرام ، ولكن إذا عرضت مجموعة البيانات الكاملة ، فسأحصل على عدة إدخالات متطابقة)

  2. يتم فرز الجدول حسب عمود يحتوي على غير سلاسل
    (كل شيء على ما يرام إذا قمت بالفرز حسب عمود يحتوي على سبيل المثال أسماء ، ولكن الفرز حسب الأعمدة التي تحتوي على التواريخ أو ints أو bools ينتج عنه مشكلة)

يؤدي الرجوع إلى الإصدار 1.2.1 إلى حل المشكلة ، ولكن هذا ليس خيارًا حقًا.
علاوة على ذلك ، يبدو أن المغفلين يظهرون بدلاً من الإدخالات الحقيقية وليس بالإضافة إليها ، لأن العدد {{filter.qs.count}} كما ينبغي.

آمل أن يساعد هذا قليلاً في الوصول إلى جوهر المشكلة ، لأنني بخلاف ذلك أستمتع حقًا بالعمل مع جداول django 2.

شكرا لكل ماقمت به من عمل.

@ n0ctua شكرا!

هل يمكنك إلقاء نظرة على الاستعلامات الدقيقة المنفذة وربما مشاركتها هنا؟

لقد واجهت هذه المشكلة أيضًا وفهمت سبب حدوثها بالنسبة لي ، لذلك اعتقدت أنني سأقوم بالنشر كما أظن أن الآخرين لديهم نفس السبب. _ (على الرغم من أنني لم أجرب إصدارات أخرى من جداول django 2 ، لذلك قد أكون مخطئًا لأنني لا أفهم سبب توقف هذا عن الحدوث ... على الرغم من ... التفكير في الأمر فعليًا ، سأفترض أن هذا ذلك لأنه في الإصدارات الأقدم ، قامت الجداول غير المرقمة بتشغيل استعلام واحد مقابل db بدلاً من استعلام لكل صف - مزيد من التفاصيل حول هذا أدناه ...) _

هذا لأن _SQL order by في الحقول غير الفريدة ليس حتميًا_ لذلك عند الجمع بينه وبين top n تحصل على نفس الصفوف n مرة تلو الأخرى. (أيضًا ، لسبب ما عندما أقوم بإنشاء Table بدون ترقيم صفحات ، فإنه ينشئ استعلامًا لكل صف _. IE top 1 ).

لست متأكدا ما هو الحل الأفضل هنا؟ أعتقد أن الطريقة الوحيدة لضمان نجاح ذلك هي أن يكون لديك دائمًا order by الأخير في حقل فريد. من الناحية المثالية المفتاح الأساسي؟ أيضا ، قد يكون من المفيد إضافة بعض الملاحظات لتحذير المستندات حول هذا؟

كمشكلة منفصلة ولكنها ستقلل حقًا من عدد مرات حدوث ذلك (وتسريع الاستعلامات للجداول غير المرقمة) إذا كان سيتم تشغيل استعلام واحد بدلاً من تشغيل استعلام top 1 لكل صف في الجدول الاستعلام الذي يجلب جميع النتائج.

intiocean هذا العدد من الاستعلامات للجداول غير

def test_single_query_for_non_paginated_table(settings):
    '''
    A non-paginated table should not generate a query for each row, but only
    one query to count the rows and one to fetch the rows.
    '''
    from django.db import connection
    settings.DEBUG = True

    for i in range(10):
        Person.objects.create(first_name='Bob %d' % randint(0, 200), last_name='Builder')

    num_queries_before = len(connection.queries)

    class PersonTable(tables.Table):
        class Meta:
            model = Person
            fields = ('first_name', 'last_name')

    table = PersonTable(Person.objects.all())
    request = build_request('/')
    RequestConfig(request, paginate=False).configure(table)
    table.as_html(request)

    # print '\n'.join(q['sql'] for q in connection.queries)
    assert len(connection.queries) - num_queries_before == 2

لقد حاولت ، ولكن دون جدوى ، إنشاء اختبار للحالة المرقمة التي فشلت. لا أفهم السبب ولكن يبدو أن كل شيء يعمل كالمعتاد في الحالة المرقمة ... اعتقدت أنني سأحصل على صفوف تظهر كما لو كانت مكررة على صفحات متعددة إذا تم الفرز حسب حقل غير فريد.

intiocean أعتقد أنني أصلحته مع 10f5e968bc10552be0ad02ee566513b5d274d5c5

@ jieter عظيم! يمكنني معرفة سبب حل المشكلة مع الجداول غير المرقمة ولكن ما زلت أعتقد أن الترتيب حسب عمود غير فريد عندما تنتشر البيانات عبر صفحات مختلفة قد يؤدي إلى ظهور نفس الصف على صفحات متعددة بسبب top n ... limit x offset y

ماذا تعتقد؟

مشابه لـ: http://stackoverflow.com/questions/31736700/duplicate-elements-in-django-paginate-after-order-by-call

wtfrank،intiocean @ n0ctua @ مرجع أليكس ريدfliphess أنا فقط دفعت بعض تلتزم الرئيسي الذي قد إصلاح هذا. هل يمكنك التحقق؟

intiocean إذا كان هذا هو مصدر هذه المشكلة ، أعتقد أنه لا يمكننا حل هذه المشكلة إلا جزئيًا من خلال توثيق هذا السلوك.

يمكنني أن أؤكد أن هذا يعمل على إصلاح الجداول غير المرقمة @ jieter. يؤدي هذا أيضًا إلى تحسين أداء الجداول غير المرقمة حيث يوجد الآن استعلام واحد فقط بدلاً من استعلام واحد لكل صف.

التحقق من:
مع 962f502 والفرز حسب عمود "الملاحظات" -> تكرار
image

باستخدام f853078 والفرز حسب عمود "الملاحظات" -> بدون تكرار 🎉
image

هل هناك أي فرصة للقيام بإصدار @ jieter؟

wohoo ، تم إصلاحه أخيرًا!

نعم ، سأطلق سراحه في غضون ساعة.

صدر 1.4.0

رائع ، شكرًا @ jieter!

@ jieter و intiocean شكرًا جزيلاً

مرحبًا ، لقد واجهت هذه المشكلة للتو في إصدار 1.21.2 و Django == 2.0.6. بفضل intiocean الصورة تعليق ، ثابتة مع وضع ترتيب إضافي من قبل "كيه".

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات