2016-01-20 47 views
6

我有很多Hardware模型,其中有HardwareType各種特徵。像這樣:如何重寫Django中的model.Manager.create()方法?

# models.py 
from django.db import models 

class HardwareType(model.Models): 
    name = models.CharField(max_length=32, unique=True) 

    # some characteristics of this particular piece of hardware 
    weight = models.DecimalField(max_digits=12, decimal_places=3) 
    # and more [...]   

class Hardware(models.Model): 

    type = models.ForeignKey(HardwareType) 

    # some attributes 
    is_installed = models.BooleanField() 
    location_installed = models.TextField() 
    # and more [...] 

如果我想添加一個新Hardware對象,我首先要檢索HardwareType每一次,這是不是很乾:

tmp_hd_type = HardwareType.objects.get(name='NG35001') 
new_hd = Hardware.objects.create(type=tmp_hd_type, is_installed=True, ...) 

因此,我試圖重寫該HardwareManager.create()方法Hardware像這樣當創建新的自動導入類型:

# models.py 
from django.db import models 

class HardwareType(model.Models): 
    name = models.CharField(max_length=32, unique=True) 

    # some characteristics of this particular piece of hardware 
    weight = models.DecimalField(max_digits=12, decimal_places=3) 
    # and more [...] 

class HardwareManager(models.Manager): 
    def create(self, *args, **kwargs): 
     if 'type' in kwargs and kwargs['type'] is str: 
      kwargs['type'] = HardwareType.objects.get(name=kwargs['type']) 
     super(HardwareManager, self).create(*args, **kwargs)  

class Hardware(models.Model): 
    objects = HardwareManager() 

    type = models.ForeignKey(HardwareType) 

    # some attributes 
    is_installed = models.BooleanField() 
    location_installed = models.TextField() 
    # and more [...] 

# so then I should be able to do: 
new_hd = Hardware.objects.create(type='ND35001', is_installed=True, ...) 

但我不斷收到錯誤,真正š來自ORM的轉向行爲(我沒有在這裏,但我可以發佈他們,如果需要)。我搜索Django文檔和SO線程,但主要是我結束了在哪裏解決方案:(?我應該得到的HardwareType那裏)

  • Hardware.save()方法被覆蓋或
  • 經理定義一種新的create_something方法,其調用self.create()

我也開始挖掘到代碼中,只見那Manager是一些特殊的QuerySet但我不知道如何從那裏繼續。我真的想替換create方法,我似乎無法處理這一點。什麼阻止我做我想做的事情?

回答

1

Alasdair的答案的洞察力幫助了很多趕字符串和unicode字符串,但什麼是真正缺少的是在HardwareManager.create()方法調用super(HardwareManager, self).create(*args, **kwargs)return聲明。

我漸漸在我的測試昨天晚上的誤差(編碼時被累是不是一個好主意:P)爲ValueError: Cannot assign None: [...] does not allow null values.因爲我有create() d的new_hd的後續使用中None因爲我create()方法沒有一個return。多麼愚蠢的錯誤!

最終糾正代碼:

class HardwareManager(models.Manager): 
    def create(self, *args, **kwargs): 
     if 'type' in kwargs and isinstance(kwargs['type'], basestring): 
      kwargs['type'] = HardwareType.objects.get(name=kwargs['type']) 
     return super(HardwareManager, self).create(*args, **kwargs) 
2

沒有看到回溯,我認爲問題在這一行。

if 'type' in kwargs and kwargs['type'] is str: 

這是檢查kwargs['type']是否是相同的對象str,這將始終是假的。

在Python 3,檢查是否`kwargs [ '型']是一個字符串,你應該做的:

if 'type' in kwargs and isinstance(kwargs['type'], str): 

如果您正在使用Python 2,你應該使用basestring,趕上字節串和unicode字符串。

if 'type' in kwargs and isinstance(kwargs['type'], basestring): 
+0

我會在幾個小時試試這個,並與錯誤(如果有的話)送還給你。謝謝 ! – achedeuzot

+3

2。x您可以使用'isinstance(foo,basestring)'來捕獲Unicode和str。 –

+0

@DanielRoseman是否使用模型中定義的'model.save'方法或''Manager.create'? – DhiaTN