سؤال

أقوم بتطوير موقع متوسط ​​لشركتي، يحتوي على كميات كبيرة من البيانات (المنشورات البحثية، ومئات الموظفين، وما إلى ذلك) والقيود الأمنية التي جعلتني أفكر في استخدام Django-guardian للتعامل مع أذونات الكائنات.لكنني أدرك الآن أن هذا قد يكون بطيئًا داخل المشرف.

لقد قمنا بالفعل بتنفيذ ذاكرة تخزين مؤقت لـ redis والتي يبدو أنها تعمل بشكل جيد إلى حد ما، ولكن لا يزال تحميل عروض القائمة الكبيرة (مئات العناصر) يستغرق وقتًا طويلاً.

نحن نستخدم حتى الآن الإعداد التالي:

django             1.5.5
django-cms         2.4.3
django-redis-cache 0.10.2
django-guardian    1.1.1
hiredis            0.1.2
redis              2.9.1

python             2.7.5
postgresql
centos

على سبيل المثال، هذه هي وحدة الشخص، والتي يستغرق عرض القائمة وقتًا طويلاً ليتم تحميلها (ليس كمستخدم متميز، ففي هذه الحالة يكون الأمر سريعًا جدًا:هذا هو السبب الذي يجعلني أعتقد أن المشكلة تكمن في العلاقات المتعددة بين Django-Guardian):

class Person(models.Model):
    TYPE_CHOICES = (
        ('S', _('Student')),
        ('E', _('Researcher')),
    )

    class Meta:
        permissions = (
            ('view_person', _('View person')),
        )
        index_together = (
            ('last_name', 'first_name'),
        )

    # Relations with other entities
    topics = models.ManyToManyField('topics.Topic', blank=True, related_name='people')
    competences = models.ManyToManyField('staff.Competence', blank=True, related_name='people', db_index=True)

    # Person properties
    cmsuser = models.OneToOneField(User, blank=True, related_name='person', null=True, db_index=True)
    sebra_username = models.CharField(max_length=20, blank=True, db_index=True)
    first_name = models.CharField(_('first name'), max_length=30, blank=True, db_index=True)
    last_name = models.CharField(_('last name'), max_length=30, blank=True, db_index=True)
    email = models.EmailField(_('email address'), blank=True, db_index=True)
    username = models.CharField(_('username'), max_length=30, unique=True, db_index=True)
    avatar = models.ImageField(upload_to='img/avatar/', blank=True)
    web = models.URLField(_("web site"), blank=True)
    cristin_profile = models.URLField(_('link to cristin profile'), blank=True)
    twitter = models.CharField(_("twitter username"), max_length=20, blank=True)
    telephone = models.CharField(
        blank=True,
        max_length=validators.MAX_LENGTH_PHONE,
        validators=[validators.validate_phone_format]
    )
    telephone_country_code = models.ForeignKey(Country, null=True, blank=True, related_name='phone_person')
    mobile = models.CharField(
        blank=True,
        max_length=validators.MAX_LENGTH_PHONE,
        validators=[validators.validate_phone_format]
    )
    mobile_country_code = models.ForeignKey(Country, null=True, blank=True, related_name='mobile_person')
    address = models.TextField(max_length=255, blank=True)
    cv = models.FileField(_('Curriculum Vitae'), upload_to='attachments/cv/', blank=True)
    vcard = models.FileField(_('Vcard'), upload_to='attachments/vcard/', blank=True)
    person_type = models.CharField(choices=TYPE_CHOICES, max_length=1, blank=True)
    extract = RichTextField(_('person extract'), blank=True, default='')
    slug = AutoSlugField(populate_from=('first_name', 'last_name'))

def __unicode__(self):
    if len(self.first_name) + len(self.last_name):
        return '%s %s' % (self.first_name, self.last_name)
    return self.username

def clean(self):
    super(Person, self).clean()
    if self.sebra_username.strip():
        # here goes validation and checks on the related objects

    def get_absolute_url(self):
        if PersonDepartmentMembership.objects.filter(active__exact=True, person__exact=self):
            return reverse('staff:profile_slug', kwargs={'slug': self.slug})
        return ''

أدرك أن عنق الزجاجة قد يكون موجودًا أيضًا داخل صف الإدارة الخاص بي.هذا هو الذي نستخدمه:

class PersonAdmin(ModelAdmin):
    fields = (
        'sebra_username', 'first_name', 'last_name', 'avatar', 'email', 'person_type', 'extract',
        'topics', 'competences', 'web', 'cristin_profile', 'twitter', 'telephone_country_code',
        'telephone', 'address', 'mobile_country_code', 'mobile', 'cv', 'vcard'
    )
    search_fields = ('sebra_username', 'first_name', 'last_name', 'email', 'departments__name')
    list_filter = ('departments__name', 'research_groups__group_name', 'projects__project_name')

    inlines = (SomeInline,)

    class Media:
        js = (
            settings.STATIC_URL + 'js/jquery-1.9.0.min.js',
            settings.STATIC_URL + 'js/jquery-ui-1.9.2.custom.min.js',
            'modeltranslation/js/tabbed_translation_fields.js',
        )
        css = {
            'screen': ('modeltranslation/css/tabbed_translation_fields.css',),
        }

    def formfield_for_manytomany(self, db_field, request=None, **kwargs):
        if db_field.name == 'topics':
            kwargs['queryset'] = get_objects_for_user(user=request.user, perms=('topics.view_topic',))
        elif db_field.name == 'competences':
            kwargs['queryset'] = get_objects_for_user(user=request.user, perms=('staff.view_competence',))
        return super(PersonAdmin, self).formfield_for_manytomany(db_field, request, **kwargs)

    def queryset(self, request):
        if request.user.is_superuser:
            return super(PersonAdmin, self).queryset(request)
        return get_objects_for_user(user=request.user, perms=('staff.change_person',)).order_by('last_name')

    def has_add_permission(self, request):
        return request.user.has_perm('staff.add_person')

    def has_delete_permission(self, request, obj=None):
        return request.user.has_perm('staff.delete_person', obj)

    def has_change_permission(self, request, obj=None):
        return request.user.has_perm('staff.change_person', obj)

هل يمكن أن تقدم لي أي نصيحة أو تقترح علي أي حل ممكن يمكننا دمجه في واجهة الإدارة؟:-)

شكرا لك مقدما!

يحرر:

باستخدام شريط أدوات Django-debug-toolbar، أستطيع أن أرى أن هناك عددًا قليلاً جدًا من الاستعلامات إلى Django-guardian، وسريعة جدًا (جميعها أقل من 6 مللي ثانية).من ناحية أخرى، لدي أكثر من 7500 استعلام لعرض قائمة مكون من 263، مما يؤدي إلى إبطاء العرض لمدة تصل إلى 46 ثانية.جميعها تقريبًا موجودة ضمن النموذج المحدد الخاص بي، لتحميل (على ما أعتقد) بيانات غير مفيدة:أفترض أن هناك حاجة فقط إلى الاسم ومعرف الكائن.

كيف يمكنني تحديد كمية البيانات المحملة ضمن طريقة queryset()؟شكرًا.

هل كانت مفيدة؟

المحلول

إذا كنت تنفذ 7500 استعلام، فمن المحتمل أن تكون مشكلتك هي أنك لا تقوم بتحميل الكائنات ذات الصلة التي تحتاجها - وإليك ما سألقي نظرة عليه:

  1. هل لديك طرق في النموذج الخاص بك يمكنها الوصول إلى الكائنات ذات الصلة؟
  2. هل لديك عناصر في الخاص بك list_display الإعداد الذي الوصول إلى الكائنات ذات الصلة؟

إما القضاء على المكالمات إلى تلك الأشياء، أو إلقاء نظرة عليها select_related.

وأيضاً - حاول تغيير ترقيم الصفحات لمشاهدات المشرف الخاصة بك - إذا قمت بتقليل عدد السجلات المعروضة - ما عدد الاستعلامات الأقل الموجودة؟سيعطيك ذلك فكرة عن عدد هذه المشكلات التي تواجهك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top