मैं कुछ इसी तरह का सुझाव दूंगा जो e4c5 सुझाए गए के समान है। , लेकिन मैं यह भी करूंगा:
-
रैंक की तारीख पर एक इंडेक्स जेनरेट करें ताकि किसी एक दिन में सभी रैंक प्राप्त करने के लिए अनुकूलित किया जा सके।
-
दिनांक और छात्र को
unique_together
as के रूप में चिह्नित करें . यह एक ही छात्र के लिए एक ही तिथि पर दो रैंक दर्ज करने की संभावना को रोकता है।
मॉडल इस तरह दिखाई देंगे:
from django.db import models
class Grade(models.Model):
pass # Whatever you need here...
class Student(models.Model):
name = models.CharField(max_length=20)
grade = models.ForeignKey(Grade)
class Rank(models.Model):
class Meta(object):
unique_together = (("date", "student"), )
date = models.DateField(db_index=True)
student = models.ForeignKey(Student)
value = models.IntegerField()
एक पूर्ण आवेदन में मैं Grade
पर कुछ विशिष्टता बाधाओं की भी अपेक्षा करता हूं और Student
लेकिन प्रश्न में प्रस्तुत समस्या इन मॉडलों के बारे में पर्याप्त विवरण प्रदान नहीं करती है।
फिर आप हर दिन cron
. के साथ एक कार्य चला सकते हैं या जो भी कार्य प्रबंधक आप उपयोग करना चाहते हैं (अजवाइन भी एक विकल्प है), निम्न की तरह एक कमांड चलाने के लिए जो कुछ गणना के अनुसार रैंक को अपडेट करेगा और पुराने रिकॉर्ड को शुद्ध करेगा। निम्नलिखित कोड एक चित्रण है यह कैसे किया जा सकता है। वास्तविक कोड को आम तौर पर निष्क्रिय होने के लिए डिज़ाइन किया जाना चाहिए (निम्न कोड इसलिए नहीं है क्योंकि रैंक गणना यादृच्छिक है) ताकि यदि सर्वर को अपडेट के बीच में रिबूट किया जाता है, तो कमांड को फिर से चलाया जा सकता है। यह रहा कोड:
import random
import datetime
from optparse import make_option
from django.utils.timezone import utc
from django.core.management.base import BaseCommand
from school.models import Rank, Student
def utcnow():
return datetime.datetime.utcnow().replace(tzinfo=utc)
class Command(BaseCommand):
help = "Compute ranks and cull the old ones"
option_list = BaseCommand.option_list + (
make_option('--fake-now',
default=None,
help='Fake the now value to X days ago.'),
)
def handle(self, *args, **options):
now = utcnow()
fake_now = options["fake_now"]
if fake_now is not None:
now -= datetime.timedelta(days=int(fake_now))
print "Setting now to: ", now
for student in Student.objects.all():
# This simulates a rank computation for the purpose of
# illustration.
rank_value = random.randint(1, 1000)
try:
rank = Rank.objects.get(student=student, date=now)
except Rank.DoesNotExist:
rank = Rank(
student=student, date=now)
rank.value = rank_value
rank.save()
# Delete all ranks older than 180 days.
Rank.objects.filter(
date__lt=now - datetime.timedelta(days=180)).delete()
अचार क्यों नहीं?
कई कारण:
-
यह एक समयपूर्व अनुकूलन है, और कुल मिलाकर शायद अनुकूलन बिल्कुल नहीं है। कुछ ऑपरेशन तेज हो सकते हैं, लेकिन अन्य ऑपरेशन धीमा होगा। यदि रैंकों को
Student
. पर किसी फ़ील्ड में चुना जाता है फिर, किसी विशिष्ट छात्र को स्मृति में लोड करने का अर्थ है उस छात्र के साथ सभी रैंक जानकारी को स्मृति में लोड करना। इसे.values()
. का उपयोग करके कम किया जा सकता है या.values_list()
लेकिन फिर आपकोStudent
नहीं मिल रहा है डेटाबेस से उदाहरण। क्यों हैStudent
उदाहरण पहली जगह में और न केवल कच्चे डेटाबेस तक पहुंचें? -
अगर मैं
Rank
में फ़ील्ड बदलता हूं , जब मैं अपने एप्लिकेशन का नया संस्करण परिनियोजित करता हूं, तो Django की माइग्रेशन सुविधाएं आसानी से आवश्यक परिवर्तन करने की अनुमति देती हैं। यदि किसी क्षेत्र में रैंक की जानकारी चुनी जाती है, तो मुझे कस्टम कोड लिखकर किसी भी संरचना परिवर्तन का प्रबंधन करना होगा। -
डेटाबेस सॉफ्टवेयर अचार में मूल्यों तक नहीं पहुंच सकता है और इसलिए आपको उन तक पहुंचने के लिए कस्टम कोड लिखना होगा। उपरोक्त मॉडल के साथ, यदि आप छात्रों को आज रैंक के आधार पर सूचीबद्ध करना चाहते हैं (और आज के लिए रैंक की गणना पहले ही की जा चुकी है), तो आप यह कर सकते हैं:
for r in Rank.objects.filter(date=utcnow()).order_by("value")\ .prefetch_related(): print r.student.name
यदि आप अचार का उपयोग करते हैं, तो आपको सभी
Students
को स्कैन करना होगा और जिस दिन आप चाहते हैं, उसके लिए रैंक निकालने के लिए रैंक को अनपिक करें, और फिर रैंक के आधार पर छात्रों को ऑर्डर करने के लिए पायथन डेटा संरचना का उपयोग करें। एक बार यह हो जाने के बाद, आपको नामों को क्रम में लाने के लिए इस संरचना पर पुनरावृति करनी होगी।