Django,Python:AttributeError: 'NoneType'对象没有属性'_meta'

6

我正在尝试测试自己编写的Python update_or_create方法,但是遇到了错误,我进行了谷歌搜索,但没有找到答案。

以下是源代码:

class ListingManager(models.Manager):#manage the creating/editting/deleting of listings
    def update_or_create_listing(self, listing_attributes, scraped = False, **extra_attributes):
        from sitebot.tasks import scrape_listing_url
        
        keys = listing_attributes.keys()
        print keys
        site = Site.objects.get(id = listing_attributes['site_id'])
        
        if 'sku' in keys and 'site_id' in keys and 'url' in keys:
            #create a listing if no such listing exists
            #SiteUrl.objects.get_or_create(href )
            listing, created = self.get_or_create(sku = listing_attributes['sku'], site = site, defaults = {'url': listing_attributes['url']}) 
            dynamo_db_listing_attributes = []
            if len(keys)> 3: 
                dynamo_db_listing_attributes = listing.create_or_update_attributes(listing_attributes = listing_attributes, **extra_attributes)
                if scraped == True and listing.scraped == False: #if the listing is already scraped, update the scraped status
                    listing.scraped = scraped
                    listing.save()
            if created == True and listing.scraped == False: #if the listing is just created and not scraped yet
                scrape_listing_url.delay(listing_id = str(listing.id), sku = listing.sku, listing_url = listing.url, scraper_name = listing.site.scraper.name) # what does delay do?
            return listing, listing_attributes 
        else:
            raise KeyError

这是测试代码:

class ListingManagerClassTests(TestCase):
    def setUp(self):
        #Generate Site for listing
        site = models.Site()
    #Generating Site requires ForeignKey Country
        country_for_site = models.Country() 
        country_for_site.save()
    #Generating Site requires ForeignKey Scraper
        scraper_for_site = models.Scraper() 
        scraper_for_site.scrapes_per_day = 1
        scraper_for_site.max_results = 10
        scraper_for_site.save()
        site.country = country_for_site
        site.scraper = scraper_for_site
        site.name = "siteforListingMangerTest"
        site.save()

    def test_create_listing(self):
        """update_or_create_listing should return the created listing"""
        lm = models.ListingManager()
        site = models.Site.objects.get(name="siteforListingMangerTest")
        listing_attributes = {'sku':'123456','site_id':site.id,
                              'url':'www.aaa.com'}
        #Create the new listing
        created_listing, created_listing_attributes = lm.update_or_create_listing(listing_attributes,False)
        #check if the retreived listing is the right one
        assertEqual(created_listing.sku, '123456')
        assertEqual(created_listing.site, site)
        assertEqual(created_listing.url,'www.aaa.com')

错误信息如下:

ERROR: test_create_listing (sitebot.tests.ListingManagerClassTests)
update_or_create_listing should return the created listing
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/wx2228/Desktop/BestBot/bestbot/sitebot/tests.py", line 35, in test_create_listing
    created_listing, created_listing_attributes = lm.update_or_create_listing(listing_attributes,False)
  File "/home/wx2228/Desktop/BestBot/bestbot/sitebot/models.py", line 90, in update_or_create_listing
    listing, created = self.get_or_create(sku = listing_attributes['sku'], site = site, defaults = {'url': listing_attributes['url']})
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py", line 127, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 402, in get_or_create
    lookup, params = self._extract_model_params(defaults, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 457, in _extract_model_params
    for f in self.model._meta.fields:
AttributeError: 'NoneType' object has no attribute '_meta'

代码清单的源代码:

class Listing(models.Model):#representing the listing of an product
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    dynamoDB_connection = DynamoDBConnection(region=RegionInfo(name='us-west-2', endpoint='dynamodb.us-west-2.amazonaws.com'))
    listings_dynamo_table = Table(table_name = 'sitebot_listings', connection= dynamoDB_connection)
    sku = models.CharField(max_length=50)
    site = models.ForeignKey(Site)
    url = models.CharField(max_length=200, null = True)
    scraped = models.BooleanField(default = False)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    
    objects = ListingManager()

你有一个名为“Listing”的数据模型吗?如果有的话,能提供一下源代码吗? - Jean Jung
你尝试过调用 Listing.objects.update_or_create_listings 吗? - Jean Jung
3个回答

8

直接实例化ListingManager会阻止查询引擎找到底层对象。

您可以通过替换以下行来解决此问题:

lm = models.ListingManager()

使用以下代码行:

lm = Listing.objects

(或者)
lm = Listing.objects.all()

无论如何,你需要通过模型本身来引用管理器,否则查询管理器将会迷失。

这应该能够工作(我刚刚花了半天时间解决了一个类似的问题。一定要爱 Django 的魔法错误信息 ;))


lm = Listing.objects,谢谢!当我尝试模拟“prefetch_related”查询的某些部分时,这对我很有用。 - micgeronimo
这对我来说很有意义,因为当您从Django shell调用ListingManager()时,您将获得该模型对象的新实例。这与获取已属于模型的对象非常不同。 - Kermit

2

Python试图在self.model中找到字段_meta。当它说NoneType没有该属性时,这意味着在您遇到该行时,self.model为None。您需要追溯代码并查看为什么其值在该点上为None。


0

当我重命名一个表并将另一个表的外键设置为它时,我遇到了这个问题。

将其分成2个迁移,然后它应该可以工作;)


这应该是一个注释。 - executable

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接