Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django,python:AttributeError: 'NoneType' object has no attribute '_meta'

Tags:

python

django

I am trying to test my own update_or_create method written in Python, but I run into a error, I Googled it and find no answer. Here is the source code:

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

and this is the test code:

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')

and the error is:

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'

source code for Listing:

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()
like image 931
wx2227 Avatar asked Sep 24 '15 23:09

wx2227


2 Answers

Instantiating the ListingManager directly prevents the query engine to find the underlying object.

You can fix this by replacing the line:

lm = models.ListingManager()

With the line:

lm = Listing.objects

(or maybe)

lm = Listing.objects.all()

Anyway, you need to refer to the Manager through the Model itself, otherwise the query manager will get lost.

It should work (I just spent half a day on a similar problem. Gotta love Django magic error messages ;) )

like image 164
Sylvain Avatar answered Sep 19 '22 22:09

Sylvain


Python is trying to find the field _meta in self.model. When it says that NoneType does not have that attribute, it means that self.model is None at the point you hit that line. You will have to trace back through your code and see why its value would be None at that point.

like image 43
Gene Callahan Avatar answered Sep 19 '22 22:09

Gene Callahan