mirror of https://github.com/scrapy/scrapy.git
added DjangoItem item class
This commit is contained in:
parent
7b30c31b59
commit
decbdc5346
|
|
@ -0,0 +1,37 @@
|
|||
from scrapy.item import DictItem, Field
|
||||
|
||||
|
||||
class DjangoItemMeta(type):
|
||||
|
||||
def __new__(mcs, class_name, bases, attrs):
|
||||
cls = super(DjangoItemMeta, mcs).__new__(mcs, class_name, bases, attrs)
|
||||
cls.fields = cls.fields.copy()
|
||||
|
||||
if cls.django_model:
|
||||
cls._model_fields = []
|
||||
cls._model_meta = cls.django_model._meta
|
||||
for model_field in cls._model_meta.fields:
|
||||
# XXX: for now we're treating each PK as autogenerated field
|
||||
if model_field != cls._model_meta.pk:
|
||||
cls.fields[model_field.name] = Field()
|
||||
cls._model_fields.append(model_field.name)
|
||||
# add declared fields
|
||||
for n, v in attrs.iteritems():
|
||||
if isinstance(v, Field):
|
||||
cls.fields[n] = v
|
||||
return cls
|
||||
|
||||
|
||||
class DjangoItem(DictItem):
|
||||
|
||||
__metaclass__ = DjangoItemMeta
|
||||
|
||||
django_model = None
|
||||
|
||||
def save(self, commit=True):
|
||||
modelargs = dict((f, self.get(f, None)) for f in self._model_fields)
|
||||
model = self.django_model(**modelargs)
|
||||
if commit:
|
||||
model.save()
|
||||
return model
|
||||
|
||||
|
|
@ -34,9 +34,7 @@ class _ItemMeta(type):
|
|||
return cls
|
||||
|
||||
|
||||
class Item(DictMixin, BaseItem):
|
||||
|
||||
__metaclass__ = _ItemMeta
|
||||
class DictItem(DictMixin, BaseItem):
|
||||
|
||||
fields = {}
|
||||
|
||||
|
|
@ -81,6 +79,11 @@ class Item(DictMixin, BaseItem):
|
|||
return "%s(%s)" % (self.__class__.__name__, values)
|
||||
|
||||
|
||||
class Item(DictItem):
|
||||
|
||||
__metaclass__ = _ItemMeta
|
||||
|
||||
|
||||
class ScrapedItem(BaseItem):
|
||||
|
||||
def __init__(self, data=None):
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
import os
|
||||
from twisted.trial import unittest
|
||||
|
||||
from scrapy.contrib_exp.djangoitem import DjangoItem, Field
|
||||
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'scrapy.tests.test_djangoitem.settings'
|
||||
|
||||
try:
|
||||
from models import Person
|
||||
django = True
|
||||
except ImportError:
|
||||
django = False
|
||||
|
||||
|
||||
class BasePersonItem(DjangoItem):
|
||||
django_model = Person
|
||||
|
||||
|
||||
class NewFieldPersonItem(BasePersonItem):
|
||||
other = Field()
|
||||
|
||||
|
||||
class OverrideFieldPersonItem(BasePersonItem):
|
||||
age = Field(default=1)
|
||||
|
||||
|
||||
class DjangoItemTest(TestCase):
|
||||
|
||||
def setUp(
|
||||
if not django:
|
||||
raise unittest.SkipTest("Django is not available")
|
||||
|
||||
def test_base(self):
|
||||
i = BasePersonItem()
|
||||
self.assertEqual(i.fields.keys(), ['age', 'name'])
|
||||
|
||||
def test_new_fields(self):
|
||||
i = NewFieldPersonItem()
|
||||
self.assertEqual(i.fields.keys(), ['age', 'other', 'name'])
|
||||
|
||||
def test_override_field(self):
|
||||
i = OverrideFieldPersonItem()
|
||||
self.assertEqual(i.fields.keys(), ['age', 'name'])
|
||||
self.assertEqual(i.fields['age'], {'default': 1})
|
||||
|
||||
def test_save(self):
|
||||
i = BasePersonItem()
|
||||
self.assertEqual(i.fields.keys(), ['age', 'name'])
|
||||
|
||||
i['name'] = 'John'
|
||||
i['age'] = '22'
|
||||
person = i.save(commit=False)
|
||||
|
||||
self.assertEqual(person.name, 'John')
|
||||
self.assertEqual(person.age, '22')
|
||||
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
from django.db import models
|
||||
|
||||
|
||||
class Person(models.Model):
|
||||
name = models.CharField(max_length=255)
|
||||
age = models.IntegerField()
|
||||
|
||||
class Meta:
|
||||
app_label = 'test_djangoitem'
|
||||
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
DATABASE_ENGINE = 'sqlite3'
|
||||
DATABASE_NAME = ':memory:'
|
||||
Loading…
Reference in New Issue