2010-08-26 37 views
18

Làm cách nào tôi có thể đặt giá trị mặc định cho trường được lấy từ các đối tượng hiện có của mô hình?Django: giá trị mặc định của trường từ trường hợp của mô hình tự

tôi đã cố gắng những điều này và nó đã không làm việc:

1)

class ModelA(models.Model): 
    fieldA = models.CharField(default=self.get_previous()) 

    def get_previous(self): 
     return ModelA.objects.all()[0].fieldA 

NameError: name 'self' is not defined

2)

class ModelA(models.Model): 
    fieldA = models.CharField(default=ModelA.get_previous()) 

    @staticmethod 
    def get_previous(): 
     return ModelA.objects.all()[0].fieldA 

NameError: name 'ModelA' is not defined

3)

class ModelA(models.Model): 
    fieldA = models.CharField(default=get_previous()) 

def get_previous(): 
    return ModelA.objects.all()[0].fieldA 

NameError: global name 'get_previous' is not defined

4)

def get_previous(): 
    return ModelA.objects.all()[0].fieldA 

class ModelA(models.Model): 
    fieldA = models.CharField(default=get_previous()) 

NameError: global name 'ModelA' is not defined

tôi thì rõ ràng lý do tại sao 3) và 4) sẽ không làm việc. Tôi có thể hình dung lý do tại sao 1) sẽ không hoạt động - có vẻ như tính thích hợp của lớp không thể tham chiếu đến ví dụ (nghĩa là bản thân). Tôi có thể hình dung lý do tại sao 2) sẽ không hoạt động - dường như không có tham chiếu đến ModelA cho đến khi thông dịch viên đi toàn bộ lớp học.

Vậy tôi nên tiếp cận điều này như thế nào?

Trả lời

16

Trong ví dụ của bạn, bạn cần phải xóa toán tử gọi ().

Hiện tại, câu lệnh được thực thi ngay lập tức tại chu kỳ đọc phân tích cú pháp đầu tiên. Bằng cách chỉ định tên biểu tượng thay vào đó, lớp Django sẽ nhận được một con trỏ hàm mà nó sẽ thực thi khi nó thực sự cần giá trị mặc định.

Ví dụ trở thành:

def get_previous(): 
    return ModelA.objects.all()[0].fieldA 

class ModelA(models.Model): 
    fieldA = models.CharField(default=get_previous) 

Nếu bạn đang đi để làm điều này cho rất nhiều lĩnh vực, xem xét overridding các save chức năng, vì vậy bạn chỉ cần lấy đối tượng trước đó từ cơ sở dữ liệu chỉ một lần.

+1

Điểm tốt! Trong trường hợp của tôi mặc dù tôi có nhiều lĩnh vực để có được giá trị mặc định vì vậy tôi sẽ cần chức năng riêng biệt cho mỗi một. (Nhưng tôi sẽ xem xét sử dụng lambda để khái quát hóa điều này, một cái gì đó như 'lambda: get_default ('field_name')') – grucha

+1

Tương đương, bạn sẽ có thể làm 'default = lambda: ModelA.objects.all() [0]. fieldA'. –

+1

Lưu ý rằng việc sử dụng hàm lambda mặc định sẽ gây rối với việc di chuyển vì các hàm lambda không thể được tuần tự hóa. – Ironbeard

3

Nếu bạn muốn chỉ ra giá trị mặc định, ghi đè __getattr__() phương pháp như thế này:

class ModelA(models.Model): 
    # your fields 
    def __getattr__(self, name): 
    if(name == 'fieldA' and !self.fieldA): 
     return self.get_previous() 
    else: 
     return super(ModelA, self).__getattr__(name) 

Tiết kiệm trị mặc định từ đối tượng sẽ ít difficultier. Giải pháp đầu tiên xuất hiện trong đầu tôi, override save() method (tôi tin rằng có giải pháp đơn giản hơn)

3

Tùy chọn 1: Use model forms. Đây là các biểu mẫu dựa trên các mô hình, bạn có thể dễ dàng điền các giá trị của chúng với các giá trị từ một cá thể cụ thể. Tùy chọn này là tốt nếu bạn muốn giá trị mặc định là một cái gì đó được hiển thị cho người dùng trong biểu mẫu, rõ ràng.

Tùy chọn 2: Override the model's save method và mã kiểm tra ở đó - nếu trườngA là Không, thì hãy đặt một số giá trị trong đó. Tùy chọn này sẽ tốt hơn nếu bạn muốn giá trị mặc định hoạt động ở lớp dữ liệu và không chỉ là các giá trị mặc định của biểu mẫu (ví dụ, đối với các trường hợp bạn tạo theo các cách khác).

+0

Điểm của tôi là hiển thị giá trị mặc định cho người dùng, không lưu giá trị đó nếu không có giá trị để Option_1 của câu trả lời của bạn có vẻ tốt. Mặc dù tôi thích câu trả lời của vdboor nhiều hơn vì nó là cấp python và không khá cụ thể django. Djangonauts, sửa tôi nếu tôi đi sai đường ;-) – grucha

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