2010-02-04 33 views
17

làm tiêu đề đề xuất. Tôi muốn thêm 30 ngày vào trường DateField. Điều này được tự động điền khi tạo bản ghi bằng cách sử dụng auto_now_add=TrueLàm thế nào mô hình django DateField của tôi có thể thêm 30 ngày vào giá trị được cung cấp?

Bất kỳ ý tưởng nào về cách thực hiện việc này?

Cảm ơn

+0

Đây là một đoán, nhưng Django Các hình thức cho phép chức năng cuộc gọi trong 'ban đầu =' giá trị của họ. Nếu đây là trường hợp cũng cho các mô hình, sau đó bạn có thể loại bỏ auto_add_now và thay thế nó bằng 'default = lambda: datetime.now() + timedelta (days = 30)' –

Trả lời

26

// Cập nhật

Các comment dưới các bài bản gốc đã cho tôi suy nghĩ. Tôi đoán đây là giải pháp tốt nhất cho đến nay:

from datetime import datetime, timedelta 

class MyModel(models.Model): 
    mydate = models.DateTimeField(default=datetime.now()+timedelta(days=30)) 

// 2. Cập nhật

Nếu bạn muốn xác định một thuộc tính mô hình mà vẫn giữ lượng ngày mà nên được bổ sung bạn sẽ cần ghi đè phương thức lưu. Cho đến nay tôi không thể nghĩ ra một cách đơn giản hơn.

Giải pháp:

class MyModel(models.Model): 
    mydate = models.DateTimeField(editable=False) 
    daysadded = models.IntegerField() 

    def save(self): 
    from datetime import datetime, timedelta 
    d = timedelta(days=self.daysadded) 

    if not self.id: 
     self.mydate = datetime.now() + d 
     super(MyModel, self).save() 

Như becomingGuru đã đề nghị bạn nên ghi đè lên mô hình của bạn phương pháp tiết kiệm.

Ví dụ:

class MyModel(models.Model): 
    mydate = models.DateTimeField(auto_now_add=True)  

    def save(self): 
    from datetime import timedelta 
    d = timedelta(days=30) 

    // only add 30 days if it's the first time the model is saved 
    if not self.id: 
     // not saving the model before adding the timedelta gave me errors 
     super(MyModel, self).save() 

     self.mydate += d 

     // final save 
     super(MyModel, self).save() 

Đây không phải là cách tốt nhất đối với tôi kể từ khi bạn có để lưu các mô hình hai lần. Nhưng việc sử dụng auto_now_add yêu cầu bạn phải lưu mô hình trước tiên trước khi một cá thể datetime cho mydate được tạo.

Một cách tiếp cận đó sẽ yêu cầu tiết kiệm chỉ có một:

class MyModel(models.Model): 
    mydate = models.DateTimeField(editable=False) // editable=False to hide in admin 

    def save(self): 
    from datetime import datetime, timedelta 
    d = timedelta(days=30) 

    // only add 30 days if it's the first time the model is saved 
    if not self.id: 
     self.mydate = datetime.now() + d 
     super(MyModel, self).save() 

Hy vọng rằng sẽ giúp!

+0

Hoạt động hoàn hảo nhờ! – dotty

+0

CẬP NHẬT: Đã hoạt động như mong đợi, tuy nhiên 30 ngày sẽ là biến số. Có thể là 30 ngày, 60 ngày, 90 ngày, v.v. Bất kỳ ý tưởng nào? Tôi có nên thêm trường 'expires_in' giữ số ngày hết hạn không? Làm cách nào tôi có thể sử dụng trường 'expires_in' mới này để chỉnh sửa dòng "timedelta (days = 30)"? – dotty

+0

Tôi có hiểu chính xác bạn không? Bạn muốn một trường mô hình khác chứa một giá trị mô tả số ngày sẽ được thêm vào? – Jens

2

Sử dụng Trăn timedelta:

from datetime import timedelta 
d = timedelta(days=30) 

# object is your current instance of the model 
object.yourdatefield += d 
# or this because I am not sure whether the previous works 
object.yourdatefield = object.yourdatefield + d 

object.save() 

Và từ Django documentation:

DateField
Một ngày, đại diện trong Python bằng một ví dụ datetime.date.

Nếu bạn muốn thêm 30 ngày khi tạo đối tượng, hãy quên đi auto_now_add=True và làm như trở thành Guru gợi ý. Thông tin về việc ghi đè save() cũng có thể được tìm thấy trong số Django documentation.

1

Ghi đè lưu trên mô hình và trong khi lưu, hãy kiểm tra xem pk có được điền hay không.

>>> from datetime import datetime 
>>> from datetime import timedelta 
>>> cur_date = datetime.now() 
>>> cur_date 
datetime.datetime(2010, 2, 4, 5, 0, 24, 437405) 
>>> cur_date+timedelta(days=30) 
datetime.datetime(2010, 3, 6, 5, 0, 24, 437405) 
42

Không cần triển khai phương thức lưu tùy chỉnh.

Cũng làm điều này default=datetime.now()+timedelta(days=30) là hoàn toàn sai! Nó được đánh giá khi bạn bắt đầu thể hiện của bạn của django. Nếu bạn sử dụng apache nó có thể sẽ hoạt động, bởi vì trên một số cấu hình, apache sẽ thu hồi ứng dụng django của bạn trên mọi yêu cầu, nhưng bạn vẫn có thể tìm thấy bản thân một số ngày tìm kiếm mã của bạn và cố gắng tìm ra lý do tại sao điều này không được tính như bạn mong đợi.

Cách đúng để thực hiện việc này là chuyển đối tượng có thể gọi đến đối số mặc định. Nó có thể là một hàm datetime.today hoặc hàm tùy chỉnh của bạn. Sau đó, nó được đánh giá mỗi khi bạn yêu cầu một giá trị mặc định mới.

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) 
+3

Tôi sử dụng rất nhiều! Đặc biệt hữu ích khi bạn muốn nhận được tất cả các bài viết không quá 20 ngày hoặc lâu hơn. Chỉ cần sử dụng 'BlogPost.objects.filter (pub_date__gt = datetime.now() - timedelta (ngày = 20) ´. Điều này dịch thành SQL và do đó rất hiệu quả! [Tham khảo trong tài liệu django] (https: //docs.djangoproject. com/vi/dev/ref/models/querysets/# field-lookups) –

+0

@ mart0903 mã của bạn chỉ là những gì tôi cần: 'BlogPost.objects.filter (pub_date__gt = datetime.now() - timedelta (days = 20)' Nói cách khác, chỉ các đối tượng có pub_date mới hơn 20 ngày trước –

+1

default = lambda: datetime.now() + timedelta (ngày = 30) – exshinigami

Các vấn đề liên quan