জাজানোতে ব্যবসায়ের যুক্তি এবং ডেটা অ্যাক্সেসের বিভাজন


484

আমি জাজানোতে একটি প্রকল্প লিখছি এবং আমি দেখতে পাচ্ছি যে 80% কোড ফাইলটিতে রয়েছে models.py। এই কোডটি বিভ্রান্তিকর এবং একটি নির্দিষ্ট সময়ের পরে, আমি সত্যিই কী ঘটছে তা বুঝতে থামি।

আমাকে বিরক্ত করার বিষয়টি এখানে:

  1. আমি এটি দেখতে কুৎসিত দেখতে পাই যে আমার মডেল স্তরটি (যা কেবলমাত্র একটি ডাটাবেস থেকে ডেটা নিয়ে কাজ করার জন্য দায়বদ্ধ বলে মনে করা হয়েছিল) এছাড়াও ইমেল প্রেরণ করছে, অন্যান্য পরিষেবাগুলিতে এপিআই চালনা ইত্যাদি is
  2. এছাড়াও, আমি ব্যবসার যুক্তিটিকে দৃষ্টিতে স্থাপন করা অগ্রহণযোগ্য বলে মনে করি, কারণ এইভাবে এটি নিয়ন্ত্রণ করা কঠিন হয়ে পড়ে। উদাহরণস্বরূপ, আমার অ্যাপ্লিকেশনটিতে কমপক্ষে তিনটি নতুন উপায় তৈরির উপায় রয়েছে Userতবে প্রযুক্তিগতভাবে এটি তাদের অভিন্ন তৈরি করা উচিত।
  3. আমি কখনই আমার মডেলগুলির পদ্ধতি এবং বৈশিষ্ট্যগুলি অ-সংযোজনাত্মক হয়ে ওঠে এবং কখন তাদের পার্শ্ব প্রতিক্রিয়া বিকাশ করে তা লক্ষ্য করি না।

এখানে একটি সহজ উদাহরণ। প্রথমে, Userমডেলটি এরকম ছিল:

class User(db.Models):

    def get_present_name(self):
        return self.name or 'Anonymous'

    def activate(self):
        self.status = 'activated'
        self.save()

সময়ের সাথে সাথে, এটি এতে রূপান্তরিত হয়েছিল:

class User(db.Models):

    def get_present_name(self): 
        # property became non-deterministic in terms of database
        # data is taken from another service by api
        return remote_api.request_user_name(self.uid) or 'Anonymous' 

    def activate(self):
        # method now has a side effect (send message to user)
        self.status = 'activated'
        self.save()
        send_mail('Your account is activated!', '…', [self.email])

আমি যা চাই তা হল আমার কোডে সত্তা পৃথক করা:

  1. আমার ডাটাবেস, ডাটাবেস স্তরের সত্তা: আমার অ্যাপ্লিকেশনটিতে কী রয়েছে?
  2. আমার প্রয়োগের সত্ত্বা, ব্যবসায়িক যুক্তি স্তর: আমার অ্যাপ্লিকেশনটি কী করতে পারে?

জ্যাঙ্গোতে প্রয়োগ করা যেতে পারে এমন পদ্ধতির বাস্তবায়নের জন্য ভাল অভ্যাসগুলি কী কী?


14
সংকেত সম্পর্কে পড়ুন
কনস্ট্যান্ট

1
ঠিক আছে আপনি ট্যাগটি মুছে ফেলেছেন তবে আপনি সিস্টেমটি কী করে (কার্যকারিতা) এবং সিস্টেমটি কী কী (ডেটা / ডোমেন মডেল) এর বিভাজনকে প্রশমিত করতে আপনি DCI ব্যবহার করতে পারেন
রুন এফএস

2
আপনি সিগন্যাল কলব্যাকগুলিতে সমস্ত ব্যবসায়ের যুক্তি বাস্তবায়নের প্রস্তাব দিচ্ছেন? দুর্ভাগ্যক্রমে, আমার সমস্ত অ্যাপ্লিকেশন ডেটাবেসের ইভেন্টের সাথে লিঙ্ক করা যায় না।
Defuz

রুন এফএস, আমি ডিসিআই ব্যবহার করার চেষ্টা করেছি, তবে আমার কাছে মনে হয়েছিল যে এটির জন্য আমার প্রকল্পের খুব বেশি দরকার নেই: প্রসঙ্গ, পদার্থের সাথে মিশ্রণের ভূমিকাগুলির সংজ্ঞা ইত্যাদি আলাদা করার সহজ উপায় আছে "কর" এবং " "হয়? আপনি একটি ন্যূনতম উদাহরণ দিতে পারেন?
Defuz

উত্তর:


634

দেখে মনে হচ্ছে আপনি ডেটা মডেল এবং ডোমেন মডেলের মধ্যে পার্থক্য সম্পর্কে জিজ্ঞাসা করছেন - পরেরটি হ'ল আপনি যেখানে আপনার শেষ ব্যবহারকারীর দ্বারা উপলব্ধ ব্যবসায়িক যুক্তি এবং সত্ত্বাগুলি খুঁজে পেতে পারেন, পূর্ববর্তীটি যেখানে আপনি আসলে আপনার ডেটা সঞ্চয় করেন।

তদুপরি, আমি আপনার প্রশ্নের তৃতীয় অংশটি ব্যাখ্যা করেছি: এই মডেলগুলিকে আলাদা রাখতে কীভাবে ব্যর্থতা লক্ষ্য করা যায়।

এগুলি দুটি খুব আলাদা ধারণা এবং এগুলি পৃথক রাখা সবসময় শক্ত। তবে, কিছু সাধারণ নিদর্শন এবং সরঞ্জাম রয়েছে যা এই উদ্দেশ্যে ব্যবহার করা যেতে পারে।

ডোমেন মডেল সম্পর্কে

আপনাকে প্রথমে যে জিনিসটি সনাক্ত করতে হবে তা হ'ল আপনার ডোমেন মডেলটি আসলে ডেটা সম্পর্কে নয়; এটি "এই ব্যবহারকারীকে সক্রিয় করুন", "এই ব্যবহারকারীকে নিষ্ক্রিয় করুন", "বর্তমানে ব্যবহারকারীরা সক্রিয় রয়েছে?", এবং "এই ব্যবহারকারীর নাম কী?" এর মতো ক্রিয়া এবং প্রশ্নগুলির বিষয়ে । ক্লাসিকাল ভাষায়: এটি প্রশ্ন এবং কমান্ড সম্পর্কে ।

কমান্ডে চিন্তা করা

আসুন আপনার উদাহরণে কমান্ডগুলি দেখে শুরু করুন: "এই ব্যবহারকারীকে সক্রিয় করুন" এবং "এই ব্যবহারকারীকে নিষ্ক্রিয় করুন"। কমান্ডগুলি সম্পর্কে দুর্দান্ত জিনিসটি হ'ল যখন সেগুলি তখনকার দৃশ্যের দ্বারা ছোট্ট দ্বারা সহজেই প্রকাশ করা যায়:

নিষ্ক্রিয় ব্যবহারকারীর দেওয়া
যখন প্রশাসক এই ব্যবহারকারীকে সক্রিয় করে
তখন ব্যবহারকারী সক্রিয় হয়ে যায়
এবং ব্যবহারকারীর কাছে একটি নিশ্চিতকরণ ই-মেল প্রেরণ করা হয়
এবং সিস্টেম লগ
(ইত্যাদি ইত্যাদি) এ একটি এন্ট্রি যুক্ত করা হয়

আপনার অবকাঠামোর বিভিন্ন অংশ কীভাবে একক কমান্ড দ্বারা প্রভাবিত হতে পারে তা দেখার জন্য এই জাতীয় দৃশ্যাবলী কার্যকর - এই ক্ষেত্রে আপনার ডাটাবেস (কিছু ধরণের 'সক্রিয়' পতাকা), আপনার মেল সার্ভার, আপনার সিস্টেম লগ ইত্যাদি etc.

এই জাতীয় পরিস্থিতি আপনাকে একটি পরীক্ষা চালিত বিকাশের পরিবেশ স্থাপনে সত্যই সহায়তা করে।

এবং শেষ অবধি, আদেশগুলিতে চিন্তা করা আপনাকে কার্য-ভিত্তিক অ্যাপ্লিকেশন তৈরি করতে সহায়তা করে। আপনার ব্যবহারকারীরা এটি প্রশংসা করবে :-)

কমান্ড প্রকাশ করা

জাজানো কমান্ড প্রকাশের দুটি সহজ উপায় সরবরাহ করে; এগুলি উভয়ই বৈধ বিকল্প এবং দুটি পদ্ধতির মিশ্রণটি অস্বাভাবিক কিছু নয়।

পরিষেবা স্তর

সেবা মডিউল ইতিমধ্যে হয়েছে @Hedde দ্বারা বর্ণিত । এখানে আপনি একটি পৃথক মডিউল নির্ধারণ করেন এবং প্রতিটি কমান্ড একটি ফাংশন হিসাবে উপস্থাপিত হয়।

services.py

def activate_user(user_id):
    user = User.objects.get(pk=user_id)

    # set active flag
    user.active = True
    user.save()

    # mail user
    send_mail(...)

    # etc etc

ফর্ম ব্যবহার করে

অন্য উপায়টি হ'ল প্রতিটি কমান্ডের জন্য জ্যাঙ্গো ফর্ম ব্যবহার করা। আমি এই পদ্ধতির পছন্দ করি, কারণ এটি একাধিক ঘনিষ্ঠভাবে সম্পর্কিত দিকগুলি একত্রিত করে:

  • কমান্ড কার্যকর (এটি কি করে?)
  • কমান্ড প্যারামিটারগুলির বৈধতা (এটি কি এটি করতে পারে?)
  • কমান্ডের উপস্থাপনা (আমি এটি কীভাবে করব?)

forms.py

class ActivateUserForm(forms.Form):

    user_id = IntegerField(widget = UsernameSelectWidget, verbose_name="Select a user to activate")
    # the username select widget is not a standard Django widget, I just made it up

    def clean_user_id(self):
        user_id = self.cleaned_data['user_id']
        if User.objects.get(pk=user_id).active:
            raise ValidationError("This user cannot be activated")
        # you can also check authorizations etc. 
        return user_id

    def execute(self):
        """
        This is not a standard method in the forms API; it is intended to replace the 
        'extract-data-from-form-in-view-and-do-stuff' pattern by a more testable pattern. 
        """
        user_id = self.cleaned_data['user_id']

        user = User.objects.get(pk=user_id)

        # set active flag
        user.active = True
        user.save()

        # mail user
        send_mail(...)

        # etc etc

প্রশ্নে চিন্তা করছেন

আপনার উদাহরণে কোনও প্রশ্ন নেই, তাই আমি কয়েকটি দরকারী প্রশ্ন তৈরির স্বাধীনতা নিয়েছি। আমি "প্রশ্ন" শব্দটি ব্যবহার করতে পছন্দ করি তবে প্রশ্নগুলি হল ধ্রুপদী পরিভাষা। আকর্ষণীয় প্রশ্নগুলি হ'ল: "এই ব্যবহারকারীর নাম কী?", "এই ব্যবহারকারী কি লগ ইন করতে পারবেন?", "আমাকে নিষ্ক্রিয় ব্যবহারকারীদের একটি তালিকা দেখান", এবং "নিষ্ক্রিয় ব্যবহারকারীদের ভৌগলিক বিতরণ কী?"

এই প্রশ্নের উত্তর দেওয়ার আগে, আপনার সর্বদা নিজেকে দুটি প্রশ্ন জিজ্ঞাসা করা উচিত: এটি কি কেবলমাত্র আমার টেম্পলেটগুলির জন্য একটি উপস্থাপিত ক্যোয়ারী এবং / অথবা আমার কমান্ডগুলি কার্যকর করার সাথে যুক্ত একটি ব্যবসায়িক লজিক কোয়েরি, এবং / অথবা একটি রিপোর্টিং কোয়েরি।

উপস্থাপনা সম্পর্কিত প্রশ্নগুলি কেবলমাত্র ব্যবহারকারী ইন্টারফেসের উন্নতির জন্য করা হয়। ব্যবসায়ের যুক্তিযুক্ত প্রশ্নের প্রশ্নের উত্তরগুলি আপনার আদেশগুলি কার্যকর করতে সরাসরি প্রভাবিত করে। রিপোর্টিং ক্যোয়ারী নিছক বিশ্লেষণাত্মক উদ্দেশ্যে এবং দীর্ঘ সময়সীমাবদ্ধতা রয়েছে। এই বিভাগগুলি পারস্পরিক একচেটিয়া নয়।

অন্য প্রশ্নটি হ'ল: "উত্তরগুলির কি আমার সম্পূর্ণ নিয়ন্ত্রণ আছে?" উদাহরণস্বরূপ, ব্যবহারকারীর নাম জিজ্ঞাসা করার সময় (এই প্রসঙ্গে) ফলাফলের উপর আমাদের কোনও নিয়ন্ত্রণ নেই, কারণ আমরা একটি বাহ্যিক এপিআইয়ের উপর নির্ভর করি।

প্রশ্ন করা

জাজানোতে সর্বাধিক প্রাথমিক ক্যোয়ারী হ'ল ম্যানেজার অবজেক্টের ব্যবহার:

User.objects.filter(active=True)

অবশ্যই, এটি কেবল তখনই কাজ করে যদি ডেটা আপনার ডেটা মডেলটিতে প্রকৃতপক্ষে উপস্থাপন করা হয়। এই সবসময় তা হয় না। এই ক্ষেত্রে, আপনি নীচের বিকল্পগুলি বিবেচনা করতে পারেন।

কাস্টম ট্যাগ এবং ফিল্টার

প্রথম বিকল্পটি কেবলমাত্র উপস্থাপনামূলক প্রশ্নের জন্য দরকারী: কাস্টম ট্যাগ এবং টেম্পলেট ফিল্টার।

template.html

<h1>Welcome, {{ user|friendly_name }}</h1>

template_tags.py

@register.filter
def friendly_name(user):
    return remote_api.get_cached_name(user.id)

অনুসন্ধান পদ্ধতি

যদি আপনার প্রশ্নের নিছক প্রেজেন্টেশন না হয় তবে আপনি আপনার টু প্রশ্নের যোগ করতে পারিনি services.py (যদি আপনি যে ব্যবহার করছেন), অথবা পরিচয় করিয়ে queries.py মডিউল:

queries.py

def inactive_users():
    return User.objects.filter(active=False)


def users_called_publysher():
    for user in User.objects.all():
        if remote_api.get_cached_name(user.id) == "publysher":
            yield user 

প্রক্সি মডেল

প্রক্সি মডেলগুলি ব্যবসায়ের যুক্তি এবং প্রতিবেদনের প্রসঙ্গে খুব কার্যকর। আপনি মূলত আপনার মডেলের একটি বর্ধিত উপসেট সংজ্ঞায়িত করেন। Manager.get_queryset()পদ্ধতিটি ওভাররাইড করে আপনি কোনও পরিচালকের বেস ক্যোয়ারীসেটকে ওভাররাইড করতে পারেন ।

models.py

class InactiveUserManager(models.Manager):
    def get_queryset(self):
        query_set = super(InactiveUserManager, self).get_queryset()
        return query_set.filter(active=False)

class InactiveUser(User):
    """
    >>> for user in InactiveUser.objects.all():
    …        assert user.active is False 
    """

    objects = InactiveUserManager()
    class Meta:
        proxy = True

অনুসন্ধান মডেল

অন্তর্নিহিত জটিল, কিন্তু বেশিরভাগ ক্ষেত্রে কার্যকর করা হয় এমন প্রশ্নের জন্য, কোয়েরি মডেলগুলির সম্ভাবনা রয়েছে। একটি ক্যোয়ারী মডেল হ'ল ডেনারালাইমাইজেশনের একটি ফর্ম যেখানে একক ক্যোয়ারীর জন্য প্রাসঙ্গিক ডেটা আলাদা মডেলে সংরক্ষণ করা হয়। অবশ্যই কৌশলটি হ'ল ডেনারমালাইজড মডেলটিকে প্রাথমিক মডেলের সাথে সুসংগত করে রাখা। পরিবর্তনগুলি পুরোপুরি আপনার নিয়ন্ত্রণে থাকলেই ক্যোয়ারী মডেলগুলি ব্যবহার করা যেতে পারে।

models.py

class InactiveUserDistribution(models.Model):
    country = CharField(max_length=200)
    inactive_user_count = IntegerField(default=0)

প্রথম বিকল্পটি হ'ল আপনার আদেশগুলিতে এই মডেলগুলি আপডেট করা update এই মডেলগুলি কেবল এক বা দুটি কমান্ড দ্বারা পরিবর্তিত হলে এটি খুব কার্যকর।

forms.py

class ActivateUserForm(forms.Form):
    # see above

    def execute(self):
        # see above
        query_model = InactiveUserDistribution.objects.get_or_create(country=user.country)
        query_model.inactive_user_count -= 1
        query_model.save()

একটি ভাল বিকল্প কাস্টম সংকেত ব্যবহার করা হবে। এই সংকেত অবশ্যই আপনার আদেশ দ্বারা নির্গত হয়। সংকেতগুলির সুবিধা রয়েছে যে আপনি একাধিক ক্যোয়ারী মডেলগুলি আপনার মূল মডেলের সাথে সিঙ্ক করে রাখতে পারেন। তদুপরি, সিলারি বা অনুরূপ ফ্রেমওয়ার্ক ব্যবহার করে সংকেত প্রক্রিয়াকরণ ব্যাকগ্রাউন্ড কার্যগুলিতে অফলোড করা যায়।

signals.py

user_activated = Signal(providing_args = ['user'])
user_deactivated = Signal(providing_args = ['user'])

forms.py

class ActivateUserForm(forms.Form):
    # see above

    def execute(self):
        # see above
        user_activated.send_robust(sender=self, user=user)

models.py

class InactiveUserDistribution(models.Model):
    # see above

@receiver(user_activated)
def on_user_activated(sender, **kwargs):
        user = kwargs['user']
        query_model = InactiveUserDistribution.objects.get_or_create(country=user.country)
        query_model.inactive_user_count -= 1
        query_model.save()

এটি পরিষ্কার রাখা

এই পদ্ধতির ব্যবহার করার সময়, আপনার কোডটি পরিষ্কার থাকে কিনা তা নির্ধারণ করা হাস্যকরভাবে সহজ হয়ে যায়। কেবল এই নির্দেশিকাগুলি অনুসরণ করুন:

  • আমার মডেলটিতে এমন পদ্ধতি রয়েছে যা ডেটাবেস স্থিতি পরিচালনার চেয়ে আরও বেশি করে? আপনার একটি আদেশ বের করা উচিত।
  • আমার মডেলটিতে এমন বৈশিষ্ট্য রয়েছে যা ডেটাবেস ক্ষেত্রগুলিতে ম্যাপ করে না? আপনার একটি কোয়েরি বের করা উচিত।
  • আমার মডেল রেফারেন্স অবকাঠামো যা আমার ডাটাবেস নয় (যেমন মেল)? আপনার একটি আদেশ বের করা উচিত।

একই মতামতের জন্য যায় (কারণ দেখা প্রায়শই একই সমস্যায় ভোগে)।

  • আমার দর্শন কি সক্রিয়ভাবে ডাটাবেস মডেলগুলি পরিচালনা করে? আপনার একটি আদেশ বের করা উচিত।

কিছু তথ্যসূত্র

জাজানো ডকুমেন্টেশন: প্রক্সি মডেল

জ্যাঙ্গো ডকুমেন্টেশন: সিগন্যাল

আর্কিটেকচার: ডোমেন ড্রাইভড ডিজাইন


11
জ্যাঙ্গো সম্পর্কিত প্রশ্নের সাথে একটি উত্তর ডিডিডি সংযুক্ত করে দেখতে ভাল লাগল। জেঙ্গো অধ্যবসায়ের জন্য অ্যাক্টিভেকর্ডকে নিযুক্ত করার কারণে উদ্বেগের বিচ্ছিন্নতাটি উইন্ডোটির বাইরে যাওয়া উচিত নয়। দুর্দান্ত উত্তর।
স্কট কোয়েটস

6
যদি আমি যাচাই করতে চাই যে লুজযুক্ত ব্যবহারকারী সেই অবজেক্টটি মোছার আগে কোনও জিনিসের মালিক, তবে আমি কি তা ভিউতে বা পরিষেবা / পরিষেবা মডিউলে পরীক্ষা করে দেখতে পারি?
ইভান

6
@ ইভান: উভয়ই। এটি অবশ্যই ফর্ম / পরিষেবা মডিউলে থাকতে হবে কারণ এটি আপনার ব্যবসায়ের সীমাবদ্ধতার অংশ। এটি দৃশ্যতেও হওয়া উচিত কারণ আপনার কেবলমাত্র এমন ক্রিয়াগুলি উপস্থাপন করা উচিত যা ব্যবহারকারীরা বাস্তবে সম্পাদন করতে পারে।
পাবলিশার

4
কাস্টম ব্যবস্থাপক পদ্ধতি প্রশ্নের বাস্তবায়ন একটি ভালো উপায় হল: User.objects.inactive_users()। তবে এখানে প্রক্সি মডেলের উদাহরণ আইএমও ভুল শব্দার্থকে বাড়ে: u = InactiveUser.objects.all()[0]; u.active = True; u.save()এবং এখনও isinstance(u, InactiveUser) == True। এছাড়াও আমি ডিবি ভিউ সহ অনেক ক্ষেত্রে কোয়েরি মডেল বজায় রাখার একটি কার্যকর উপায় উল্লেখ করব।
আরেহ লেইব বৃষ

1
নিবন্ধন করুন মনে রাখবেন যে উত্তরটি কেবলমাত্র "ডোমেন মডেল" শব্দটি ব্যবহার করে। আমি ডিডিডি-র লিঙ্কটি অন্তর্ভুক্ত করেছি কারণ আমার উত্তরটি ডিডিডি নয়, তবে সেই বইটি আপনাকে ডোমেন মডেলগুলি সম্পর্কে ভাবতে সহায়তা করার ক্ষেত্রে দুর্দান্ত কাজ করে।
পাবলিশার

148

আমি সাধারণত ভিউ এবং মডেলগুলির মধ্যে একটি পরিষেবা স্তর প্রয়োগ করি। এটি আপনার প্রকল্পের API এর মতো কাজ করে এবং যা চলছে তার একটি ভাল হেলিকপ্টার ভিউ দেয়। আমি আমার এক সহকর্মীর কাছ থেকে এই অনুশীলনটি উত্তরাধিকার সূত্রে পেয়েছি যা জাভা প্রকল্পগুলির (জেএসএফ) দিয়ে এই লেয়ারিং কৌশলটি প্রচুর পরিমাণে ব্যবহার করে, যেমন:

models.py

class Book:
   author = models.ForeignKey(User)
   title = models.CharField(max_length=125)

   class Meta:
       app_label = "library"

services.py

from library.models import Book

def get_books(limit=None, **filters):
    """ simple service function for retrieving books can be widely extended """
    return Book.objects.filter(**filters)[:limit]  # list[:None] will return the entire list

views.py

from library.services import get_books

class BookListView(ListView):
    """ simple view, e.g. implement a _build and _apply filters function """
    queryset = get_books()

মনে মনে, আমি সাধারণত মডেল, ভিউ এবং পরিষেবাদিগুলিকে মডিউল স্তরে নিয়ে যাই এবং প্রকল্পের আকারের উপর নির্ভর করে আরও আলাদা করি


8
আমি সাধারণ পদ্ধতিটি পছন্দ করি যদিও আমার নির্দিষ্ট ধারণাটি বুঝতে পেরে সাধারণত পরিচালক হিসাবে প্রয়োগ করা হবে ।
এরি

9
@ অপরিহার্যভাবে, সম্ভবত এটির চেয়ে ভাল উদাহরণ, কোনও ওয়েবশপ পরিষেবাদিতে কার্ট সেশন তৈরি করা, পণ্য রেটিং গণনার মতো অ্যাসিঙ্ক্রোনাস টাস্ক, ইমেল তৈরি এবং প্রেরণের মতো বিষয় অন্তর্ভুক্ত থাকবে
Hedde van der Heide

4
আমিও এই পদ্ধতির পছন্দ করি, জাভাও এসেছি। আমি অজগর থেকে নতুন, আপনি কীভাবে ভিউপিপি পরীক্ষা করবেন? আপনি কীভাবে পরিষেবা স্তরটিকে উপহাস করবেন (উদাহরণস্বরূপ, পরিষেবাটি কিছু রিমোট এপি কল করে)?
তৈমুরাজ

71

প্রথমত, নিজেকে পুনরাবৃত্তি করবেন না

তারপরে, দয়া করে খুব বেশি পরিমাণে নজর না দেওয়া সম্পর্কে সতর্ক থাকুন, কখনও কখনও এটি কেবল সময়ের অপচয় হয় এবং কাউকে গুরুত্বপূর্ণ বিষয়গুলির দিকে ফোকাস হারাতে বাধ্য করে। সময়ে সময়ে অজগরটির জেন পর্যালোচনা করুন ।

সক্রিয় প্রকল্পগুলি একবার দেখুন

  • আরও বেশি লোক = আরও সঠিকভাবে সংগঠিত করা প্রয়োজন
  • জ্যাঙ্গো সংগ্রহস্থলের তারা একটি সহজবোধ্য গঠন আছে।
  • পিপ সংগ্রহস্থলের তারা একটি straigtforward ডিরেক্টরি গঠন আছে।
  • ফ্যাব্রিক সংগ্রহস্থলের একটি ভালো তাকান হয়।

    • আপনি আপনার সমস্ত মডেল এর অধীনে রাখতে পারেন yourapp/models/logicalgroup.py
  • উদাহরণস্বরূপ User, Groupএবং সম্পর্কিত মডেলগুলি এর অধীনে যেতে পারেyourapp/models/users.py
  • যেমন Poll, Question, Answer... অধীনে যেতে পারেyourapp/models/polls.py
  • আপনার __all__ভিতরে যা প্রয়োজন তা লোড করুনyourapp/models/__init__.py

এমভিসি সম্পর্কে আরও

  • মডেল আপনার ডেটা
    • এটিতে আপনার আসল তথ্য অন্তর্ভুক্ত রয়েছে
    • এটিতে আপনার সেশন / কুকি / ক্যাশে / এফএস / সূচক ডেটাও অন্তর্ভুক্ত রয়েছে
  • মডেলটি পরিচালনা করতে ব্যবহারকারী নিয়ামকের সাথে যোগাযোগ করে
    • এটি একটি এপিআই, বা এমন কোনও দৃশ্য হতে পারে যা আপনার ডেটা সংরক্ষণ করে / আপডেট করে
    • এটি request.GET/ request.POST... ইত্যাদি দিয়ে সুর করা যায়
    • পেজিং বা ফিল্টারিংও ভাবুন ।
  • তথ্য ভিউ আপডেট করে
    • টেমপ্লেটগুলি ডেটা নেয় এবং সেই অনুসারে এটি ফর্ম্যাট করে
    • API গুলি এমনকি ডাব্লু / ও টেমপ্লেটগুলি দেখার অংশ; যেমন tastypieবাpiston
    • এটি মিডওয়্যারের জন্য অ্যাকাউন্ট করা উচিত।

মিডলওয়্যার / টেমপ্লেট ট্যাগগুলির সুবিধা নিন

  • প্রতিটি অনুরোধের জন্য যদি আপনার কিছু কাজ করা প্রয়োজন হয় তবে মিডলওয়্যারগুলি এক উপায়।
    • যেমন টাইমস্ট্যাম্প যুক্ত
    • যেমন পৃষ্ঠা হিট সম্পর্কে মেট্রিক আপডেট করা
    • যেমন একটি ক্যাশে পপুলেট করা
  • আপনার যদি কোডের স্নিপেট থাকে যা সর্বদা বিন্যাস করার উদ্দেশ্যে পুনরায় পুনরায় লাগায়, টেমপ্লেট ট্যাগগুলি ভাল।
    • যেমন সক্রিয় ট্যাব / ইউআরএল ব্রেডক্র্যাম্বস bs

মডেল পরিচালকদের সুবিধা নিন

  • তৈরি করা Userযেতে পারে UserManager(models.Manager)
  • দৃষ্টান্তগুলির জন্য দুর্যোগপূর্ণ বিবরণটি চলতে হবে models.Model
  • querysetএকটি মধ্যে যেতে পারে জন্য gory বিবরণ models.Manager
  • আপনি Userএকবারে একটি তৈরি করতে চাইতে পারেন , তাই আপনি ভাবতে পারেন এটি নিজেই মডেলটিতে বাস করা উচিত, তবে অবজেক্টটি তৈরি করার সময় আপনার কাছে সম্ভবত সমস্ত বিবরণ নেই:

উদাহরণ:

class UserManager(models.Manager):
   def create_user(self, username, ...):
      # plain create
   def create_superuser(self, username, ...):
      # may set is_superuser field.
   def activate(self, username):
      # may use save() and send_mail()
   def activate_in_bulk(self, queryset):
      # may use queryset.update() instead of save()
      # may use send_mass_mail() instead of send_mail()

যেখানে সম্ভব ফর্মগুলি ব্যবহার করুন

আপনার যদি কোনও মডেলটিতে সেই মানচিত্র থাকে তবে প্রচুর বয়লারপ্লেট কোডটি মুছে ফেলা যায়। ModelForm documentationবেশ ভাল। ফর্মগুলির জন্য মডেল কোড থেকে আলাদা করার কোডটি ভাল হতে পারে যদি আপনার অনেকগুলি কাস্টমাইজেশন থাকে (বা কখনও কখনও আরও উন্নত ব্যবহারের জন্য চক্রীয় আমদানি ত্রুটিগুলি এড়ানো হয়)।

সম্ভব হলে পরিচালনার আদেশগুলি ব্যবহার করুন

  • যেমন yourapp/management/commands/createsuperuser.py
  • যেমন yourapp/management/commands/activateinbulk.py

আপনার যদি ব্যবসায়িক যুক্তি থাকে তবে আপনি এটি আলাদা করতে পারেন

  • django.contrib.auth ডিবি যেমন একটি ব্যাকএন্ড থাকে ... ঠিক তেমনই ব্যাকএন্ড ব্যবহার করে।
  • settingআপনার ব্যবসায়ের যুক্তির জন্য একটি যুক্ত করুন (উদাঃ AUTHENTICATION_BACKENDS)
  • আপনি ব্যবহার করতে পারেন django.contrib.auth.backends.RemoteUserBackend
  • আপনি ব্যবহার করতে পারেন yourapp.backends.remote_api.RemoteUserBackend
  • আপনি ব্যবহার করতে পারেন yourapp.backends.memcached.RemoteUserBackend
  • ব্যাকএন্ডে কঠিন ব্যবসায় যুক্তি যুক্ত করুন
  • প্রত্যাশাটি সঠিকভাবে ইনপুট / আউটপুটে সেট করা নিশ্চিত করুন।
  • ব্যবসায়ের যুক্তি পরিবর্তন করা কোনও সেটিংস পরিবর্তন করার মতোই সহজ :)

ব্যাকএন্ড উদাহরণ:

class User(db.Models):
    def get_present_name(self): 
        # property became not deterministic in terms of database
        # data is taken from another service by api
        return remote_api.request_user_name(self.uid) or 'Anonymous' 

হতে পারত:

class User(db.Models):
   def get_present_name(self):
      for backend in get_backends():
         try:
            return backend.get_present_name(self)
         except: # make pylint happy.
            pass
      return None

নকশা নিদর্শন সম্পর্কে আরও

ইন্টারফেস সীমানা সম্পর্কে আরও

  • আপনি যে কোডটি ব্যবহার করতে চান তা কি মডেলগুলির অংশ? ->yourapp.models
  • কোডটি কি যুক্তি যুক্তির অংশ? ->yourapp.vendor
  • কোডটি কি জেনেরিক সরঞ্জাম / লিবসের অংশ? ->yourapp.libs
  • কোডটি কি যুক্তিযুক্ত লিবির অংশ? -> yourapp.libs.vendorবাyourapp.vendor.libs
  • এখানে একটি ভাল: আপনি কি নিজের কোডটি স্বাধীনভাবে পরীক্ষা করতে পারবেন?
    • হ্যা, ভালো :)
    • না, আপনার ইন্টারফেসের সমস্যা হতে পারে
    • যখন স্পষ্ট বিচ্ছিন্নতা থাকে, তখন বিদ্রূপের ব্যবহারের সাথে ইউনিটেস্ট বাতাস হওয়া উচিত
  • বিচ্ছেদ কি যৌক্তিক?
    • হ্যা, ভালো :)
    • না, এই যৌক্তিক ধারণাটি আলাদাভাবে পরীক্ষা করতে আপনার সমস্যা হতে পারে।
  • আপনি কি মনে করেন যে আপনি যখন আরও 10x কোড পেয়েছেন তখন আপনাকে রিফ্যাক্টর লাগবে?
    • হ্যাঁ, কোনও ভাল, কোনও বুয়েনো, রিফ্যাক্টর অনেক কাজ হতে পারে
    • না, এটা দুর্দান্ত!

সংক্ষেপে, আপনি থাকতে পারে

  • yourapp/core/backends.py
  • yourapp/core/models/__init__.py
  • yourapp/core/models/users.py
  • yourapp/core/models/questions.py
  • yourapp/core/backends.py
  • yourapp/core/forms.py
  • yourapp/core/handlers.py
  • yourapp/core/management/commands/__init__.py
  • yourapp/core/management/commands/closepolls.py
  • yourapp/core/management/commands/removeduplicates.py
  • yourapp/core/middleware.py
  • yourapp/core/signals.py
  • yourapp/core/templatetags/__init__.py
  • yourapp/core/templatetags/polls_extras.py
  • yourapp/core/views/__init__.py
  • yourapp/core/views/users.py
  • yourapp/core/views/questions.py
  • yourapp/core/signals.py
  • yourapp/lib/utils.py
  • yourapp/lib/textanalysis.py
  • yourapp/lib/ratings.py
  • yourapp/vendor/backends.py
  • yourapp/vendor/morebusinesslogic.py
  • yourapp/vendor/handlers.py
  • yourapp/vendor/middleware.py
  • yourapp/vendor/signals.py
  • yourapp/tests/test_polls.py
  • yourapp/tests/test_questions.py
  • yourapp/tests/test_duplicates.py
  • yourapp/tests/test_ratings.py

বা অন্য কিছু যা আপনাকে সহায়তা করে; খোঁজার ইন্টারফেসগুলি আপনার যা দরকার এবং সীমানা আপনাকে সাহায্য করবে।


27

জাজানো সামান্য পরিবর্তিত ধরণের এমভিসি নিয়োগ করে। জ্যাঙ্গোতে কোনও "নিয়ামক" এর ধারণা নেই। নিকটতম প্রক্সিটি একটি "ভিউ", যা এমভিসি রূপান্তরকারীদের সাথে বিভ্রান্তির কারণ হয়ে থাকে কারণ এমভিসিতে একটি ভিউ জ্যাঙ্গোর "টেম্পলেট" এর মতোই।

জ্যাঙ্গোতে, একটি "মডেল" কেবল একটি ডাটাবেস বিমূর্ততা নয়। কিছু ক্ষেত্রে, এটি এমভিসির নিয়ামক হিসাবে জ্যাঙ্গোর "ভিউ" এর সাথে শুল্ক ভাগ করে দেয়। এটি উদাহরণের সাথে যুক্ত আচরণের সম্পূর্ণতা ধারণ করে। যদি সেই উদাহরণটির কোনও বাহ্যিক এপিআই এর আচরণের অংশ হিসাবে ইন্টারঅ্যাক্ট করতে হয় তবে এটি এখনও মডেল কোড। প্রকৃতপক্ষে, মডেলগুলি একেবারে ডাটাবেসের সাথে ইন্টারঅ্যাক্ট করার প্রয়োজন হয় না, সুতরাং আপনার কাছে এমন কোনও মডেল থাকতে পারে যা সম্পূর্ণরূপে একটি বাহ্যিক API এ ইন্টারেক্টিভ স্তর হিসাবে উপস্থিত থাকে। এটি একটি "মডেল" এর আরও অনেক বিনামূল্যে ধারণা।


7

জাজানোতে এমভিসি কাঠামোটি ক্রিস প্র্যাট যেমন বলেছিলেন, অন্যান্য ফ্রেমওয়ার্কগুলিতে ব্যবহৃত ক্লাসিকাল এমভিসি মডেল থেকে আলাদা, আমি মনে করি এটি করার মূল কারণটি খুব কঠোর অ্যাপ্লিকেশন কাঠামো এড়ানো, যেমন অন্যদের মধ্যে ঘটে কেকেপিএইচপির মতো এমভিসি ফ্রেমওয়ার্কগুলি।

জ্যাঙ্গোতে এমভিসি নিম্নলিখিত পদ্ধতিতে প্রয়োগ করা হয়েছিল:

ভিউ স্তরটি দুটি ভাগে বিভক্ত। ভিউগুলি কেবল এইচটিটিপি অনুরোধগুলি পরিচালনা করতে ব্যবহার করা উচিত, তাদের ডাকা হয় এবং তাদের প্রতিক্রিয়া জানানো হয়। দৃশ্যগুলি আপনার বাকী অ্যাপ্লিকেশনটির সাথে যোগাযোগ করে (ফর্ম, মডেলফর্ম, কাস্টম ক্লাস, সাধারণ ক্ষেত্রে সরাসরি মডেলগুলির সাথে)। ইন্টারফেস তৈরি করতে আমরা টেমপ্লেট ব্যবহার করি। টেমপ্লেটগুলি জ্যাঙ্গোর মতো স্ট্রিংয়ের মতো, এটি তাদের মধ্যে একটি প্রসঙ্গ ম্যাপ করে এবং এই প্রসঙ্গটি অ্যাপ্লিকেশনটির মাধ্যমে দর্শনে জানানো হয়েছিল (যখন ভিউ জিজ্ঞাসা করবে)।

মডেল স্তরটি এনক্যাপসুলেশন, বিমূর্ততা, বৈধতা, বুদ্ধি দেয় এবং আপনার ডেটা অবজেক্ট-ওরিয়েন্টেড করে তোলে (তারা বলে যে কোনও দিন ডিবিএমএসও করবে)। এর অর্থ এই নয় যে আপনার বিশাল মডেল.পি ফাইল তৈরি করা উচিত (আসলে খুব ভাল পরামর্শ হ'ল আপনার মডেলগুলি বিভিন্ন ফাইলে বিভক্ত করা, সেগুলিকে 'মডেল' নামে একটি ফোল্ডারে রাখুন, এতে একটি '__init__.py' ফাইল তৈরি করা উচিত) ফোল্ডার যেখানে আপনি আপনার সমস্ত মডেল আমদানি করেন এবং শেষ পর্যন্ত মডেলগুলির 'app_label' বৈশিষ্ট্যটি ব্যবহার করুন od মডেল বর্গ)। মডেল আপনাকে ডেটা দিয়ে পরিচালনা করা থেকে বিমূর্ত করা উচিত, এটি আপনার অ্যাপ্লিকেশনটিকে আরও সহজ করে তুলবে। আপনার প্রয়োজন অনুসারে, আপনার মডেলগুলির জন্য "সরঞ্জামগুলি" এর মতো বাহ্যিক ক্লাসও তৈরি করা উচিত You আপনি মডেলগুলিতে heritageতিহ্যও ব্যবহার করতে পারেন, আপনার মডেলের মেটা বর্গের 'বিমূর্ত' বৈশিষ্ট্যটিকে 'সত্য' তে সেট করে।

বাকিটা কোথায়? ভাল, ছোট ওয়েব অ্যাপ্লিকেশনগুলি সাধারণত ডেটাতে একটি ইন্টারফেস হয়, কিছু ছোট প্রোগ্রামের ক্ষেত্রে ডেটা জিজ্ঞাসা করতে বা সন্নিবেশ করার জন্য ভিউগুলি ব্যবহার করা যথেষ্ট। আরও সাধারণ ক্ষেত্রে ফর্ম বা মডেলফর্মগুলি ব্যবহার করা হবে যা আসলে "নিয়ামক"। এটি একটি সাধারণ সমস্যার ব্যবহারিক সমাধান এবং খুব দ্রুত সমাধান ছাড়া অন্য নয়। এটি একটি ওয়েবসাইট যা করতে ব্যবহার করে।

যদি ফর্মগুলি আপনার পক্ষে না জাগে, তবে যাদু করার জন্য আপনার নিজের ক্লাস তৈরি করা উচিত, এর একটি খুব ভাল উদাহরণ অ্যাডমিন অ্যাপ্লিকেশন: আপনি মডেলআমিন কোডটি পড়তে পারেন, এটি আসলে একটি নিয়ামক হিসাবে কাজ করে। কোনও মানক কাঠামো নেই, আমি আপনাকে বিদ্যমান জাজানো অ্যাপ্লিকেশনগুলি পরীক্ষা করার পরামর্শ দিচ্ছি, এটি প্রতিটি ক্ষেত্রে নির্ভর করে। এটিই জ্যাঙ্গো বিকাশকারীদের উদ্দেশ্য, আপনি এক্সএমএল পার্সার শ্রেণি, একটি এপিআই সংযোগকারী শ্রেণি যুক্ত করতে পারেন, কার্য সম্পাদন করার জন্য সেলারি যুক্ত করতে পারেন, চুল্লি-ভিত্তিক অ্যাপ্লিকেশনটির জন্য মোচড় করতে পারেন, কেবল ওআরএম ব্যবহার করতে পারেন, একটি ওয়েব পরিষেবা করতে পারেন, অ্যাডমিন অ্যাপ্লিকেশনটি পরিবর্তন করতে পারেন এবং আরও অনেক কিছু। .. ভাল মানের কোড তৈরি করা, এমভিসি দর্শনের প্রতি শ্রদ্ধা জানানো বা না করা, এটি মডিউল ভিত্তিক করা এবং আপনার নিজস্ব বিমূর্ত স্তর তৈরি করা আপনার দায়বদ্ধতা। এটা খুব নমনীয়।

আমার পরামর্শ: যতটা কোড আপনি পারেন পড়ুন, চারপাশে প্রচুর জ্যাঙ্গো অ্যাপ্লিকেশন রয়েছে তবে এগুলি এত গুরুত্বের সাথে নেবেন না। প্রতিটি কেস আলাদা, নিদর্শন এবং তত্ত্ব সাহায্য করে, কিন্তু সর্বদা নয়, এটি একটি অনর্থক মনোভাব, জ্যাঙ্গো কেবল আপনাকে এমন ভাল সরঞ্জাম সরবরাহ করে যা আপনি কিছু ব্যথা উপশম করতে ব্যবহার করতে পারেন (যেমন অ্যাডমিন ইন্টারফেস, ওয়েব ফর্ম যাচাইকরণ, আই 18 এন, পর্যবেক্ষক প্যাটার্ন বাস্তবায়ন, সমস্ত পূর্বে উল্লিখিত এবং অন্যান্য), তবে ভাল ডিজাইনগুলি অভিজ্ঞ ডিজাইনারদের কাছ থেকে আসে।

পিএস .: লেখক অ্যাপ্লিকেশন (স্ট্যান্ডার্ড জ্যাঙ্গো থেকে) থেকে 'ব্যবহারকারীর' বর্গ ব্যবহার করুন, আপনি উদাহরণস্বরূপ ব্যবহারকারীর প্রোফাইল তৈরি করতে পারেন বা কমপক্ষে এর কোডটি পড়তে পারেন, এটি আপনার ক্ষেত্রে কার্যকর হবে।


1

একটি পুরানো প্রশ্ন, তবে আমি যাই হোক না কেন আমার সমাধানটি দিতে চাই। এটা তোলে গ্রহণযোগ্যতা মডেলটির খুব কিছু অতিরিক্ত কার্যকারিতা প্রয়োজন বস্তু যখন এটি মধ্যে এটি স্থাপন করতে বিশ্রী এর উপর ভিত্তি করে এর models.py । ভারী ব্যবসায়ের যুক্তি ব্যক্তিগত স্বাদের উপর নির্ভর করে আলাদাভাবে লেখা যেতে পারে তবে আমি অন্তত নিজেকে সম্পর্কিত সমস্ত কাজ করতে মডেলটিকে পছন্দ করি। এই সমাধানটি তাদের সমর্থন করে যাঁরা সমস্ত যুক্তি নিজেরাই মডেলগুলির মধ্যে রাখতে চান।

এর মতো, আমি একটি হ্যাক তৈরি করেছি যা আমাকে মডেল সংজ্ঞাগুলি থেকে লজিককে আলাদা করতে দেয় এবং এখনও আমার আইডিই থেকে সমস্ত ইঙ্গিত পেতে পারে।

সুবিধাগুলি সুস্পষ্ট হওয়া উচিত, তবে এটি কয়েকটি পর্যালোচনা করেছে যা আমি পর্যবেক্ষণ করেছি:

  • ডিবি সংজ্ঞা কেবল ততটাই রয়ে গেছে - কোনও যুক্তি "আবর্জনা" সংযুক্ত নেই
  • মডেল সম্পর্কিত যুক্তিগুলি সমস্ত এক জায়গায় খুব সুন্দরভাবে স্থাপন করা হয়েছে
  • সমস্ত পরিষেবাদি (ফর্ম, আরইএসটি, দর্শন) যুক্তিতে একক অ্যাক্সেস পয়েন্ট রয়েছে
  • সর্বোপরি: আমি বুঝতে পারি যে আমার মডেল.পি খুব বিশৃঙ্খল হয়ে গেছে এবং যুক্তিটি দূরে সরিয়ে ফেলতে হবে তখন আমি কোনও কোড পুনরায় লিখতে হয়নি । বিভাজনটি মসৃণ এবং পুনরুক্তিযুক্ত: আমি কোনও সময় বা সম্পূর্ণ ক্লাসে বা পুরো মডেল.পিতে কোনও ফাংশন করতে পারি।

আমি পাইথন ৩.৪ এবং এর চেয়ে বেশি এবং জ্যাঙ্গো ১.৮ এবং এর থেকেও বেশি ব্যবহার করে চলেছি।

অ্যাপ্লিকেশন / models.py

....
from app.logic.user import UserLogic

class User(models.Model, UserLogic):
    field1 = models.AnyField(....)
    ... field definitions ...

অ্যাপ্লিকেশন / যুক্তিবিজ্ঞান / user.py

if False:
    # This allows the IDE to know about the User model and its member fields
    from main.models import User

class UserLogic(object):
    def logic_function(self: 'User'):
        ... code with hinting working normally ...

আমি যে জিনিসটি সনাক্ত করতে পারি না তা হ'ল কীভাবে আমার আইডিই (এই ক্ষেত্রে পাইচার্ম) তৈরি করতে হবে যে ইউজারলজিকটি আসলে ব্যবহারকারী মডেল। তবে যেহেতু এটি স্পষ্টতই একটি হ্যাক, আমি সর্বদা selfপ্যারামিটারের জন্য ধরণের নির্দিষ্টকরণের সামান্য উপদ্রব গ্রহণ করতে পেরে বেশ খুশি ।


আসলে আমি এটিকে ব্যবহার করার সহজ পদ্ধতির হিসাবে দেখছি। তবে আমি চূড়ান্ত মডেলটিকে অন্য একটি ফাইলে স্থানান্তরিত করব, এবং মডেল.পি-তে উত্তরাধিকারী হব না। এটা তোলে service.py মত হবে ছিলেন userlogic + + মডেল সংঘর্ষ
Maks

1

আমি আপনার সাথে একমত হতে হবে। সেখানে জ্যাঙ্গো সম্ভাবনার অনেক কিন্তু সবচেয়ে ভালো জায়গা থেকে শুরু পর্যালোচনা করছে হয় জ্যাঙ্গো এর নকশা দর্শনের

  1. কোনও মডেল সম্পত্তি থেকে একটি এপিআই কল করা আদর্শ হবে না, দেখে মনে হচ্ছে এটি এই জাতীয় দৃষ্টিভঙ্গিতে কিছু করা আরও ভাল হবে এবং সম্ভবত জিনিস শুকনো রাখতে একটি পরিষেবা স্তর তৈরি করা উচিত। যদি এপিআই-তে কল অ-ব্লক করা হয় এবং কলটি ব্যয়বহুল হয়, কোনও পরিষেবা কর্মীর কাছে (একটি সারি থেকে গ্রাসকারী কর্মী) অনুরোধটি প্রেরণ করা বোধগম্য হতে পারে।

  2. জ্যাঙ্গোর ডিজাইন অনুসারে দর্শনের মডেলগুলি একটি "অবজেক্ট" এর প্রতিটি দিককে আবদ্ধ করে। সুতরাং object অবজেক্টের সাথে সম্পর্কিত সমস্ত ব্যবসায়ের যুক্তি সেখানেই বাস করা উচিত:

সমস্ত প্রাসঙ্গিক ডোমেন যুক্তি অন্তর্ভুক্ত করুন

মডেলগুলিকে মার্টিন ফোলারের অ্যাক্টিভ রেকর্ড ডিজাইন নকশা অনুসরণ করে একটি "অবজেক্ট" এর প্রতিটি দিককে আবশ্যক করে তোলা উচিত।

  1. আপনি যে পার্শ্ব প্রতিক্রিয়াগুলি বর্ণনা করেছেন তা আপাত, এখানে যুক্তি আরও ভালভাবে ক্যুরিসেটস এবং পরিচালকদের মধ্যে বিভক্ত করা যেতে পারে। এখানে একটি উদাহরণ:

    models.py

    import datetime
    
    from djongo import models
    from django.db.models.query import QuerySet
    from django.contrib import admin
    from django.db import transaction
    
    
    class MyUser(models.Model):
    
        present_name = models.TextField(null=False, blank=True)
        status = models.TextField(null=False, blank=True)
        last_active = models.DateTimeField(auto_now=True, editable=False)
    
        # As mentioned you could put this in a template tag to pull it
        # from cache there. Depending on how it is used, it could be
        # retrieved from within the admin view or from a custom view
        # if that is the only place you will use it.
        #def get_present_name(self):
        #    # property became non-deterministic in terms of database
        #    # data is taken from another service by api
        #    return remote_api.request_user_name(self.uid) or 'Anonymous'
    
        # Moved to admin as an action
        # def activate(self):
        #     # method now has a side effect (send message to user)
        #     self.status = 'activated'
        #     self.save()
        #     # send email via email service
        #     #send_mail('Your account is activated!', '…', [self.email])
    
        class Meta:
            ordering = ['-id']  # Needed for DRF pagination
    
        def __unicode__(self):
            return '{}'.format(self.pk)
    
    
    class MyUserRegistrationQuerySet(QuerySet):
    
        def for_inactive_users(self):
            new_date = datetime.datetime.now() - datetime.timedelta(days=3*365)  # 3 Years ago
            return self.filter(last_active__lte=new_date.year)
    
        def by_user_id(self, user_ids):
            return self.filter(id__in=user_ids)
    
    
    class MyUserRegistrationManager(models.Manager):
    
        def get_query_set(self):
            return MyUserRegistrationQuerySet(self.model, using=self._db)
    
        def with_no_activity(self):
            return self.get_query_set().for_inactive_users()

    admin.py

    # Then in model admin
    
    class MyUserRegistrationAdmin(admin.ModelAdmin):
        actions = (
            'send_welcome_emails',
        )
    
        def send_activate_emails(self, request, queryset):
            rows_affected = 0
            for obj in queryset:
                with transaction.commit_on_success():
                    # send_email('welcome_email', request, obj) # send email via email service
                    obj.status = 'activated'
                    obj.save()
                    rows_affected += 1
    
            self.message_user(request, 'sent %d' % rows_affected)
    
    admin.site.register(MyUser, MyUserRegistrationAdmin)

0

আমি বেশিরভাগই নির্বাচিত উত্তরের ( https://stackoverflow.com/a/12857584/871392 ) সাথে একমত , তবে ক্যোয়ারী তৈরির বিভাগে বিকল্প যুক্ত করতে চাই।

ফিল্টার ক্যোয়ারী ইত্যাদি তৈরির জন্য কেউ মডেলগুলির জন্য ক্যোরিসেট ক্লাসগুলি সংজ্ঞায়িত করতে পারে। এর পরে আপনি মডেলটির পরিচালকের জন্য বিল্ড-ইন ম্যানেজার এবং ক্যোরিসেট ক্লাসগুলির মতো এই ক্যোরিসেট ক্লাসটি প্রক্সি করতে পারেন।

যদিও, একটি ডোমেন মডেল পেতে যদি আপনাকে বেশ কয়েকটি ডেটা মডেলকে জিজ্ঞাসা করতে হয়, তবে এটি আগে পরামর্শ মতো আলাদা মডিউলে রাখাই আমার পক্ষে আরও যুক্তিযুক্ত বলে মনে হয়।


0

বিভিন্ন উপকার ও কুফলের সাথে সর্বাধিক বিস্তৃত নিবন্ধ:

  1. আইডিয়া # 1: ফ্যাট মডেল
  2. আইডিয়া # 2: ভিউ / ফর্মগুলিতে ব্যবসায়িক যুক্তি রেখে
  3. আইডিয়া # 3: পরিষেবাদি
  4. আইডিয়া # 4: ক্যোয়ারীসেটস / ম্যানেজার
  5. উপসংহার

সূত্র: https://sunscrapers.com/blog/where-to-put-business-logic-django/


আপনার কিছু ব্যাখ্যা যুক্ত করা উচিত।
m02ph3u5

-6

জাজানো ওয়েব পৃষ্ঠাগুলি বিতরণ করার জন্য সহজেই ব্যবহার করার জন্য ডিজাইন করা হয়েছে। আপনি যদি এটির সাথে সন্দেহযোগ্য না হন তবে আপনার আর একটি সমাধান ব্যবহার করা উচিত।

আমি মডেলটিতে মূল বা সাধারণ অপারেশনগুলি লিখছি (একই ইন্টারফেসটি রাখতে) এবং অন্যদের মডেলটির নিয়ামকটিতে। যদি অন্য মডেল থেকে আমার অপারেশন দরকার হয় আমি এর নিয়ামকটি আমদানি করি।

এই পদ্ধতিটি আমার পক্ষে এবং আমার অ্যাপ্লিকেশনগুলির জটিলতার জন্য যথেষ্ট।

হেডের প্রতিক্রিয়া এমন একটি উদাহরণ যা জাঙ্গো এবং পাইথনের নিজেই নমনীয়তা দেখায়।

খুব মজার প্রশ্ন যাই হোক!


9
কীভাবে বলছেন যে এই প্রশ্নটি আমার বোঝার পক্ষে আপনার পক্ষে যথেষ্ট সহায়ক?
ক্রিস ওয়েসলিং

1
জাজানোতে django.db.models ছাড়াও আরও অনেক কিছু দেওয়ার রয়েছে তবে বাস্তুতন্ত্রের বেশিরভাগ অংশই জ্যাঙ্গো মডেলগুলি ব্যবহার করে আপনার মডেলের উপর নির্ভর করে।
andho

1
সফ্টওয়্যার বিকাশের জন্য ব্যবহৃত নকশার প্যাটার্ন। এবং ডিজাইন ডিজাইন করা সহজেই ওয়েব বা ওয়েবপেজ নয়, মাঝারি বা বড় আকারে সফ্টওয়্যার সরবরাহ করতে ব্যবহার করা যায়!
মোহাম্মদ তোর্কাশবন্দ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.