জ্যাঙ্গো - Model.create () পদ্ধতিটি ওভাররাইড করছে?


89

জ্যাঙ্গো ডক্স শুধুমাত্র অগ্রাহ্য জন্য উদাহরণ তালিকাবদ্ধ save()এবং delete()। তবে আমি কেবলমাত্র আমার মডেলগুলি তৈরি হওয়ার পরে কিছু অতিরিক্ত প্রসেসিং সংজ্ঞায়িত করতে চাই । রেলের সাথে পরিচিত প্রত্যেকের জন্যই এটি :before_createফিল্টার তৈরির সমতুল্য । এটা কি সম্ভব?

উত্তর:


164

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

def save(self, *args, **kwargs):
    if not self.pk:
        # This code only happens if the objects is
        # not in the database yet. Otherwise it would
        # have pk
    super(MyModel, self).save(*args, **kwargs)

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

4
আমি ধরে নিচ্ছি আপনি ম্যানেজার পদ্ধতিটি ওভাররাইডিং বলতে চাইছেন create? এটি একটি আকর্ষণীয় সমাধান, তবে যখন বস্তুটি তৈরি করা হচ্ছে Object(**kwargs).save()বা তার উপর অন্য কোনও প্রকারের ক্ষেত্রে এটি কার্যকর হবে না ।
জাচ

4
আমি মনে করি না এটি হ্যাক। এটি সরকারী সমাধানগুলির মধ্যে একটি।
লেস

6
এটা করা উচিত নয় super(MyModel, self).save(*args, **kwargs)?
মার্ক চ্যাকেরিয়ান

4
self.pkঅবজেক্টটি নতুনভাবে তৈরি হচ্ছে বা সবেমাত্র আপডেট হচ্ছে কিনা তা যাচাই করার জন্য অনুসন্ধান করা সেরা বিকল্প নয়। কখনও কখনও আপনি তৈরির সময় অবজেক্ট আইডি সরবরাহ করেন (একটি কাস্টমাইজড নন-ডাটাবেস উত্পন্ন মানের মতো KSUID), এবং এর ফলে এই ধারাটি কখনই কার্যকর হবে না ... self._state.addingএটি নিশ্চিত করার মান রয়েছে যে এটি প্রথমবারের জন্য সংরক্ষণ করছে বা কেবল আপডেট হচ্ছে, যা কোন এই ক্ষেত্রে সাহায্য করে।
শাহিনিজম

22

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

from django.db.models.signals import post_save

class MyModel(models.Model):
    # ...
    @classmethod
    def post_create(cls, sender, instance, created, *args, **kwargs):
        if not created:
            return
        # ...what needs to happen on create

post_save.connect(MyModel.post_create, sender=MyModel)

কথাটি হ'ল:

  1. সিগন্যাল ব্যবহার করুন ( সরকারী ডক্সে আরও এখানে পড়ুন )
  2. সুন্দর নেমস্পেসিংয়ের জন্য একটি পদ্ধতি ব্যবহার করুন (যদি এটি বোধগম্য হয়) ... এবং আমি এটির @classmethodপরিবর্তে চিহ্নিত করেছি @staticmethodকারণ সম্ভবত আপনি কোডটিতে স্থির শ্রেণীর সদস্যদের রেফার করার প্রয়োজন শেষ করবেন likely

এমনকি ক্লিনার যদি জ্যাঙ্গোতে একটি আসল post_createসংকেত পাওয়া যায়। (ইমো যদি কোনও পদ্ধতির আচরণ পরিবর্তন করতে আপনার বুলিয়ান আর্গ পাস করতে হয় তবে এটি 2 পদ্ধতি হওয়া উচিত))


22

পোস্ট_সেভ সিগন্যাল কীভাবে তৈরি করবেন তার একটি উদাহরণ ( http://djangosnippets.org/snippets/500/ থেকে )

from django.db.models.signals import post_save
from django.dispatch import receiver

@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
    """Create a matching profile whenever a user object is created."""
    if created: 
        profile, new = UserProfile.objects.get_or_create(user=instance)

এখানে সিগন্যাল বা কাস্টম সেভ পদ্ধতি ব্যবহার করা ভাল কিনা তা নিয়ে এখানে একটি চিন্তাশীল আলোচনা রয়েছে https://web.archive.org/web/20120815022107/http://www.martin-geber.com/thought/2007/10/29/ জ্যাঙ্গো-সিগন্যালস-বনাম কাস্টম-সেভ-পদ্ধতি /

আমার মতে এই কাজের জন্য সংকেত ব্যবহার করা আরও মজবুত, পড়ার পক্ষে সহজ তবে দীর্ঘতর।


এটি অবজেক্ট ইন্টার্নালের সাথে গোলযোগের পরিবর্তে পছন্দসই উপায়, তবে, আপনি যদি প্রশ্নে মডেলটিতে পরিবর্তন করেন এবং উপরের উদাহরণে কেবল অন্যটি তৈরি না করেন, কল করতে ভুলবেন নাinstance.save() । সুতরাং এই ক্ষেত্রে, একটি কার্যকারিতা জরিমানাও রয়েছে যেহেতু ডাটাবেসে একটি INSERT এবং একটি আপডেটের কোয়েরি থাকবে।
মাইক শাল্টজ

সংকেত বনাম কাস্টম সংরক্ষণের পদ্ধতিগুলির লিঙ্কটি নষ্ট হয়ে গেছে।
Sander Vanden Hautte

18

প্রশ্নের আক্ষরিক উত্তর দেওয়ার জন্য, createকোনও মডেলের ম্যানেজারের পদ্ধতিটি জ্যাঙ্গোতে নতুন অবজেক্ট তৈরি করার একটি মানক উপায়। ওভাররাইড করতে, এমন কিছু করুন

from django.db import models

class MyModelManager(models.Manager):
    def create(self, **obj_data):
        # Do some extra stuff here on the submitted data before saving...
        # For example...
        obj_data['my_field'] = my_computed_value(obj_data['my_other_field'])

        # Now call the super method which does the actual creation
        return super().create(**obj_data) # Python 3 syntax!!

class MyModel(models.model):
    # An example model
    my_field = models.CharField(max_length=250)
    my_other_field = models.CharField(max_length=250)

    objects = MyModelManager()

এই উদাহরণে, উদাহরণটি createতৈরি হওয়ার আগে আমি কিছু অতিরিক্ত প্রক্রিয়াকরণ করার জন্য ম্যানেজারের পদ্ধতি পদ্ধতিটিকে ওভাররাইড করছি ।

নোট: কোড মত

my_new_instance = MyModel.objects.create(my_field='my_field value')

এই পরিবর্তিত createপদ্ধতিটি কার্যকর করে তবে কোডটি পছন্দ করে

my_new_unsaved_instance = MyModel(my_field='my_field value')

হবে না.


3

__init__()যখন মডেলটি তাত্ক্ষণিক হয় তখন ওভাররাইডিং আপনাকে কোড সম্পাদন করতে দেয়। বাবা-মার সাথে যোগাযোগ করতে ভুলবেন না __init__()


আহ হ্যাঁ এই উত্তর ছিল। আমি কীভাবে এটিকে উপেক্ষা করেছি জানি না। ধন্যবাদ Ignacio।
গ্রাউন্ডফার্ক


1

পছন্দসই উত্তরটি সঠিক তবে যদি আপনার মডেলটি ইউইউডি মডেল থেকে প্রাপ্ত হয় তবে অবজেক্টটি তৈরি হচ্ছে কিনা তা পরীক্ষা করে দেখার জন্য। পিকে ক্ষেত্রে ইতিমধ্যে একটি মান থাকবে।

এই ক্ষেত্রে, আপনি এটি করতে পারেন:

already_created = MyModel.objects.filter(pk=self.pk).exists()

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