কীভাবে একটি ফাংশন কল / কলযোগ্য (যেমন মডেল অবজেক্ট তৈরির সময় সম্পর্কিত একটি তারিখ) এর সাথে জ্যাঙ্গো মডেল ফিল্ডের ডিফল্ট মান সেট করা যায়


103

সম্পাদিত:

আমি কীভাবে জঙ্গো ফিল্ডের ডিফল্টটিকে কোনও ফাংশনে সেট করতে পারি যা প্রতিবার একটি নতুন মডেল অবজেক্ট তৈরি হওয়ার পরে মূল্যায়ন হয়?

আমি নিম্নলিখিতগুলির মতো কিছু করতে চাই, এই কোডটি ব্যতীত কোডটি একবার মূল্যায়ন হয়ে যায় এবং প্রতিটি মডেল অবজেক্ট তৈরি হওয়ার সাথে সাথে কোডটি মূল্যায়ন না করে তৈরি প্রতিটি মডেল অবজেক্টের জন্য একই তারিখে ডিফল্ট সেট করে:

from datetime import datetime, timedelta
class MyModel(models.Model):
  # default to 1 day from now
  my_date = models.DateTimeField(default=datetime.now() + timedelta(days=1))



মূল:

আমি একটি ফাংশন প্যারামিটারের জন্য একটি ডিফল্ট মান তৈরি করতে চাই যে এটি গতিশীল এবং ফাংশনটি বলা হওয়ার সময় প্রতিটি সময় সেট হয়ে যায় set আমি এটা কিভাবে করবো? যেমন,

from datetime import datetime
def mydate(date=datetime.now()):
  print date

mydate() 
mydate() # prints the same thing as the previous call; but I want it to be a newer value

বিশেষত, আমি এটি জাঙ্গোতে করতে চাই, যেমন,

from datetime import datetime, timedelta
class MyModel(models.Model):
  # default to 1 day from now
  my_date = models.DateTimeField(default=datetime.now() + timedelta(days=1))

প্রশ্নটি ভুলভাবে লেখা হয়েছে: ফাংশন প্যারামিটার ডিফল্টগুলির সাথে এর কোনও সম্পর্ক নেই। আমার উত্তর দেখুন।
নেড ব্যাচেল্ডার

@ নেডব্যাচেল্ডারের মন্তব্য অনুসারে, আমি আমার প্রশ্নটি সম্পাদনা করেছি ("সম্পাদিত:" হিসাবে চিহ্নিত) এবং মূলটি ছেড়ে
চলেছি

উত্তর:


145

প্রশ্নটি বিপথগামী। জ্যাঙ্গোতে একটি মডেল ক্ষেত্র তৈরি করার সময়, আপনি কোনও ফাংশন সংজ্ঞায়িত করছেন না, সুতরাং ফাংশনের ডিফল্ট মানগুলি অপ্রাসঙ্গিক:

from datetime import datetime, timedelta
class MyModel(models.Model):
  # default to 1 day from now
  my_date = models.DateTimeField(default=datetime.now() + timedelta(days=1))

এই শেষ লাইনটি কোনও ফাংশন সংজ্ঞায়িত করছে না; এটি ক্লাসে একটি ক্ষেত্র তৈরি করার জন্য একটি ক্রিয়াকলাপকে অনুরোধ করছে।

পিআরআই জ্যাঙ্গো ১. 1.

জ্যাঙ্গো আপনাকে ডিফল্ট হিসাবে কলযোগ্য পাস করতে দেয় এবং এটি প্রতিটি সময় যেমন আপনি চান ঠিক তেমনভাবে আহবান করবে:

from datetime import datetime, timedelta
class MyModel(models.Model):
  # default to 1 day from now
  my_date = models.DateTimeField(default=lambda: datetime.now() + timedelta(days=1))

জাজানো 1.7+

দয়া করে মনে রাখবেন যে জাজানো ১.7 থেকে, লাম্বডা ডিফল্ট মান হিসাবে ব্যবহারের প্রস্তাব দেওয়া হয় না (সিএফ @ স্টাভনউ মন্তব্য)। এটি করার যথাযথ উপায় হল ক্ষেত্রের আগে একটি ক্রিয়া ডিক্লেয়ার করা এবং এটি ডিফল্ট_মূল্য নামযুক্ত আর্গ হিসাবে কলযোগ্য হিসাবে ব্যবহার করুন:

from datetime import datetime, timedelta

# default to 1 day from now
def get_default_my_date():
  return datetime.now() + timedelta(days=1)

class MyModel(models.Model):
  my_date = models.DateTimeField(default=get_default_my_date)

নীচে @simanas উত্তরে আরও তথ্য


4
ধন্যবাদ @ নেড ব্যাচেল্ডার আমি ঠিক এটিই খুঁজছিলাম। আমি বুঝতে পারি নি যে 'ডিফল্ট' কল করতে পারে। এবং এখন আমি দেখতে পাচ্ছি যে কীভাবে আমার প্রশ্নটি ফাংশন অনুরোধ বনাম ফাংশন সংজ্ঞা সম্পর্কিত ভুল পথে চালিত হয়েছিল।
রব বেদনার্ক

26
নোট করুন যে জাঙ্গো> = 1.7 এর জন্য মাঠের বিকল্পগুলির জন্য ল্যাম্বডাস ব্যবহারের প্রস্তাব দেওয়া হয়নি কারণ তারা মাইগ্রেশনের সাথে বেমানান। রেফ: ডক্স , টিকিট
StvnW

4
দয়া করে এই উত্তরটি আনচেক করুন, কারণ এটি ডিজনে> = 1.7 এর পক্ষে ভুল। @ সিমানাসের উত্তর একেবারে সঠিক এবং সেজন্য গ্রহণ করা উচিত।
অ্যাপ্লাসকিনাস

এই মাইগ্রেশন দিয়ে কিভাবে কাজ করে? সমস্ত পুরানো বস্তু কি স্থানান্তরের সময়ের ভিত্তিতে একটি তারিখ পায়? মাইগ্রেশনের সাথে ব্যবহার করার জন্য কি আলাদা ডিফল্ট সেট করা সম্ভব?
টিমথিলিয়ন

7
আমি যদি কিছু প্যারামিটার পাস করতে চাই তবে কী হবে get_default_my_date?
সদন এ।

60

এটি করলে default=datetime.now()+timedelta(days=1)একেবারে ভুল!

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

এটি করার সঠিক উপায় হ'ল ডিফল্ট আর্গুমেন্টে কলযোগ্য বস্তুটি পাস করা। এটি একটি ডেটটাইম.আজ আজকের ফাংশন বা আপনার কাস্টম ফাংশন হতে পারে। তারপরে আপনি যখন একটি নতুন ডিফল্ট মান অনুরোধ করবেন তখনই এটি মূল্যায়ন হয়।

def get_deadline():
    return datetime.today() + timedelta(days=20)

class Bill(models.Model):
    name = models.CharField(max_length=50)
    customer = models.ForeignKey(User, related_name='bills')
    date = models.DateField(default=datetime.today)
    deadline = models.DateField(default=get_deadline)

22
যদি আমার ডিফল্টটি মডেলের অন্য কোনও ক্ষেত্রের মানের উপর ভিত্তি করে থাকে তবে সেই ক্ষেত্রটি কোনও পরামিতি হিসাবে কোনও কিছুর মতো পাস করা সম্ভব get_deadline(my_parameter)?
ওয়াইপিক্রাম্বল

@ ওয়াইপি ক্রাম্বল এটি একটি নতুন প্রশ্ন হওয়া উচিত!
jsmedmar

4
নাহ। এটা সম্ভব না. এটি করার জন্য আপনাকে কিছু আলাদা পদ্ধতির ব্যবহার করতে হবে।
সিমানাস 4'16

ফাংশনটি deadlineমোছার সময় আপনি কীভাবে ক্ষেত্রটি আবার সরিয়ে ফেলবেন get_deadline? আমি একটি ডিফল্ট মানের জন্য একটি ফাংশন সহ একটি ক্ষেত্র সরিয়ে ফেলেছি, তবে এখন ফাংশনটি সরিয়ে দেওয়ার পরে জাজানো স্টার্টআপে ক্র্যাশ করে। আমি ম্যানুয়ালি মাইগ্রেশনটি সম্পাদনা করতে পারলাম, যা এই ক্ষেত্রে ঠিক হবে, তবে আপনি যদি কেবল ডিফল্ট ফাংশনটি পরিবর্তন করে এবং পুরানো ফাংশনটি সরাতে চান?
বেরু

8

নিম্নলিখিত দুটি ডেটটাইমফিল্ড নির্মাতাদের মধ্যে একটি গুরুত্বপূর্ণ পার্থক্য রয়েছে:

my_date = models.DateTimeField(auto_now=True)
my_date = models.DateTimeField(auto_now_add=True)

আপনি যদি auto_now_add=Trueকনস্ট্রাক্টর ব্যবহার করেন তবে মাই_ডেট দ্বারা উল্লিখিত তারিখের সময়টি "অপরিবর্তনীয়" (সারণীতে সারিটি সন্নিবেশ করা হলে কেবল একবার সেট করা হয়)।

auto_now=Trueতবে এর সাথে , প্রতি সময় অবজেক্টটি সংরক্ষণ করার পরে ডেটটাইম মান আপডেট করা হবে।

এটি অবশ্যই এক পর্যায়ে আমার জন্য গোটচা ছিল। রেফারেন্সের জন্য, দস্তাবেজগুলি এখানে রয়েছে:

https://docs.djangoproject.com/en/dev/ref/models/fields/#datetimefield


4
আপনার নিজের সংজ্ঞা অটো_নো এবং অটো_নো_মিশ্রিত হয়ে গেছে, এটি অন্যভাবে।
মাইকেল বেইস

@ মিশেলবাটস এখন আরও ভাল?
হেন্ডি ইরাওয়ান

4

কখনও কখনও নতুন ব্যবহারকারী মডেল তৈরি করার পরে আপনাকে মডেল ডেটা অ্যাক্সেস করতে হতে পারে।

এখানে আমি প্রত্যেকটি নতুন ব্যবহারকারী প্রোফাইলের জন্য তাদের ব্যবহারকারীর নামের প্রথম 4 টি অক্ষর ব্যবহার করে একটি টোকেন উত্পন্ন করছি:

from django.dispatch import receiver
class Profile(models.Model):
    auth_token = models.CharField(max_length=13, default=None, null=True, blank=True)


@receiver(post_save, sender=User) # this is called after a User model is saved.
def create_user_profile(sender, instance, created, **kwargs):
    if created: # only run the following if the profile is new
        new_profile = Profile.objects.create(user=instance)
        new_profile.create_auth_token()
        new_profile.save()

def create_auth_token(self):
    import random, string
    auth = self.user.username[:4] # get first 4 characters in user name
    self.auth_token =  auth + ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits + string.ascii_lowercase) for _ in range(random.randint(3, 5)))

3

আপনি সরাসরি এটি করতে পারবেন না; ফাংশন সংজ্ঞাটি যখন মূল্যায়ন করা হয় তখন ডিফল্ট মানটি মূল্যায়ন করা হয়। তবে এর চারপাশে দুটি উপায় রয়েছে।

প্রথমত, আপনি প্রতিবার একটি নতুন ফাংশন তৈরি করতে (এবং তারপরে কল করতে পারেন)।

অথবা, আরও সহজভাবে, কেবলমাত্র ডিফল্টটিকে চিহ্নিত করতে একটি বিশেষ মান ব্যবহার করুন। উদাহরণ স্বরূপ:

from datetime import datetime
def mydate(date=None):
  if date is None:
    date = datetime.now()
  print date

যদি Noneকোনও উপযুক্ত যুক্তিযুক্ত প্যারামিটার মান হয় এবং আপনি তার জায়গায় ব্যবহার করতে পারেন এমন কোনও যুক্তিসঙ্গত মান নেই, তবে আপনি কেবলমাত্র একটি নতুন মান তৈরি করতে পারেন যা অবশ্যই আপনার ফাংশনের ডোমেনের বাইরে রয়েছে:

from datetime import datetime
class _MyDateDummyDefault(object):
  pass
def mydate(date=_MyDateDummyDefault):
  if date is _MyDateDummyDefault:
    date = datetime.now()
  print date
del _MyDateDummyDefault

কিছু বিরল ক্ষেত্রে, আপনি এমন মেটা-কোড লিখছেন যা সত্যিই একেবারে কোনও কিছু নিতে, এমনকি, বলার পক্ষে সক্ষম হতে হবে mydate.func_defaults[0]। সেক্ষেত্রে আপনাকে এই জাতীয় কিছু করতে হবে:

def mydate(*args, **kw):
  if 'date' in kw:
    date = kw['date']
  elif len(args):
    date = args[0]
  else:
    date = datetime.now()
  print date

4
নোট করুন যে ডামি মান শ্রেণিটি বাস্তবে ইনস্ট্যান্ট করার কোনও কারণ নেই - কেবল ক্লাসটিই ডামি মান হিসাবে ব্যবহার করুন।
অ্যাম্বার

আপনি সরাসরি এটি করতে পারেন, কেবলমাত্র ফাংশন কলের ফলাফলের পরিবর্তে ফাংশনে পাস করুন। আমার পোস্ট উত্তর দেখুন।

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

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

এটি প্রাসঙ্গিক কারণ তার myfuncফাংশনটি (এবং মুদ্রণ) গ্রহণের জন্য করা হয়েছে datetime; আপনি এটি পরিবর্তন করেছেন যাতে এটি সেভাবে ব্যবহার করা যায় না।
অবধি

1

ফাংশন কলের ফলাফলের পরিবর্তে প্যারামিটার হিসাবে ফাংশনটি পাস করুন।

এটি এর পরিবর্তে:

def myfunc(date=datetime.now()):
    print date

এটা চেষ্টা কর:

def myfunc(date=datetime.now):
    print date()

এটি কাজ করে না, কারণ এখন ব্যবহারকারী আসলে প্যারামিটারটি পাস করতে পারে না — আপনি এটি একটি ফাংশন হিসাবে কল করার চেষ্টা করবেন এবং একটি ব্যতিক্রম ছুঁড়ে ফেলবেন। কোন ক্ষেত্রে আপনি কেবল কোনও print datetime.now()শর্ত ছাড়াই কোনও প্যারাম গ্রহণ করবেন না ।
abarnert

চেষ্টা করে দেখুন আপনি কোনও তারিখ পার করছেন না, আপনি ডেটটাইম.নু ফাংশনটি পার করছেন।

হ্যাঁ, ডিফল্টটি datetime.nowফাংশনটি পার করছে । তবে যে কোনও ব্যবহারকারী অ-ডিফল্ট মানটি পাস করে কোনও ফাংশন নয়, একটি ডেটটাইম পাস করবে। foo = datetime.now(); myfunc(foo)উত্থাপন করবে TypeError: 'datetime.datetime' object is not callable। আমি যদি আসলে আপনার ফাংশনটি ব্যবহার করতে চাইতাম তবে এর myfunc(lambda: foo)পরিবর্তে আমাকে এমন কিছু করতে হবে, যা কোনও যুক্তিসঙ্গত ইন্টারফেস নয়।
29:59

4
ইন্টারফেস যা ফাংশন গ্রহণ করে তা অস্বাভাবিক নয়। আপনি চাইলে আমি পাইথন স্টাডলিব থেকে উদাহরণের নামকরণ শুরু করতে পারি।

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