import sys
from importlib import import_module
from airtable import Airtable
from django.db import models, IntegrityError
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.core.management.base import BaseCommand
from logging import getLogger
from modelcluster.contrib.taggit import ClusterTaggableManager
from taggit.managers import TaggableManager
from wagtail.core.models import Page
from wagtail_airtable.tests import MockAirtable
from wagtail_airtable.utils import get_model_for_path, get_validated_models
logger = getLogger(__name__)
DEFAULT_OPTIONS = {
"verbosity": 1,
}
TESTING = any(x in ["test", "runtests.py"] for x in sys.argv)
class Importer:
def __init__(self, models=[], options=DEFAULT_OPTIONS):
self.models = models
self.options = options
self.records_used = []
self.cached_records = {}
self.created = 0
self.updated = 0
self.skipped = 0
def debug_message(self, message):
"""
Local function. Print debug messages if `verbosity` is 2 or higher.
"""
if self.options["verbosity"] >= 2:
if not TESTING:
print(message)
return message
def get_model_serializer(self, serializer_string):
location, serializer_name = serializer_string.rsplit(".", 1)
module = import_module(location)
serializer_class = getattr(module, serializer_name)
return serializer_class
def get_model_settings(self, model) -> dict:
return settings.AIRTABLE_IMPORT_SETTINGS.get(model._meta.label, {})
def get_column_to_field_names(self, airtable_unique_identifier) -> tuple:
uniq_id_type = type(airtable_unique_identifier)
airtable_unique_identifier_column_name = None
airtable_unique_identifier_field_name = None
if uniq_id_type == str:
# The unique identifier is a string.
# Use it as the Airtable Column name and the Django field name
airtable_unique_identifier_column_name = airtable_unique_identifier
airtable_unique_identifier_field_name = airtable_unique_identifier
elif uniq_id_type == dict:
# Unique identifier is a dictionary.
# Use the key as the Airtable Column name and the value as the Django Field name.
(
airtable_unique_identifier_column_name,
airtable_unique_identifier_field_name,
) = list(airtable_unique_identifier.items())[0]
return (
airtable_unique_identifier_column_name,
airtable_unique_identifier_field_name,
)
def get_or_set_cached_records(self, airtable_client):
# Memoize results from Airtable so we don't hit the same API multiple times
# This is largely used to support additional Wagtail/Airatble settings
# that are identical to each other, as in they would use the
# same Airtable Base as the key in the dictionary.
# ie.
# 'yourapp.YourPage': {
# ...
# 'AIRTABLE_TABLE_NAME': 'Your Table',
# },
# 'different_app.DifferentPage': {
# ...
# 'AIRTABLE_TABLE_NAME': 'Your Table', # Same Airtable Table name
# }
# All of the above settings will use the 'Your Table' results
# instead of hitting the Airtable API for each model and getting the same
# results every time. This is designed to help with API efficiency, reduce
# load/import times, and to reduce how much memory is required to save all
# the records from Airtable.
if self.cached_records.get(airtable_client.table_name):
all_records = self.cached_records.get(airtable_client.table_name)
else:
# Get all the airtable records for the specified table.
all_records = airtable_client.get_all()
self.cached_records[airtable_client.table_name] = all_records
return all_records
def convert_mapped_fields(self, record_fields_dict, mapped_fields_dict) -> dict:
# Create a dictionary of newly mapped key:value pairs based on the `mappings` dict above.
# This wil convert "airtable column name" to "django_field_name"
mapped_fields_dict = {
mapped_fields_dict[key]: value
for (key, value) in record_fields_dict.items()
if key in mapped_fields_dict
}
return mapped_fields_dict
def update_object(
self, instance, record_id, serialized_data, is_wagtail_model=False
) -> bool:
"""
Attempts to update an object.
Returns a bool that determines if the object was updated or not.
"""
if serialized_data.is_valid():
self.debug_message(
"\t\t Serializer data was valid. Setting attrs on model..."
)
model = type(instance)
for field_name, value in serialized_data.validated_data.items():
field_type = type(
model._meta.get_field(field_name)
) # ie. django.db.models.fields.CharField
# If this field type is a subclass of a known Wagtail Tag, or a Django m2m field
# We need to loop through all the values and add them to the m2m-style field.
if issubclass(
field_type,
(TaggableManager, ClusterTaggableManager, models.ManyToManyField,),
):
m2m_field = getattr(instance, field_name)
for m2m_value in value:
m2m_field.add(m2m_value)
else:
setattr(instance, field_name, value)
# When an object is saved it should NOT push its newly saved data back to Airtable.
# This could theoretically cause a loop. By default this setting is True. But the
# below line confirms it's false, just to be safe.
instance.airtable_record_id = record_id
instance.push_to_airtable = False
try:
if is_wagtail_model:
self.debug_message("\t\t This is a Wagtail Page model")
# Wagtail page. Requires a .save_revision()
if not instance.locked:
self.debug_message(
"\t\t\t Page is not locked. Saving page and creating a new revision."
)
# Only save the page if the page is not locked
instance.save()
instance.save_revision()
self.updated = self.updated + 1
else:
self.debug_message("\t\t\t Page IS locked. Skipping Page save.")
self.skipped = self.skipped + 1
else:
# Django model. Save normally.
self.debug_message("\t\t Saving Django model")
instance.save()
self.updated = self.updated + 1
# New record being processed. Save it to the list of records.
self.records_used.append(record_id)
# Object updated (and record was used)
return True
except ValidationError as error:
self.skipped = self.skipped + 1
error_message = "; ".join(error.messages)
logger.error(
f"Unable to save {instance._meta.label} -> '{instance}'. Error(s): {error_message}"
)
self.debug_message(
f"\t\t Could not save Wagtail/Django model. Error: {error_message}"
)
else:
logger.info(f"Invalid data for record {record_id}")
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
资源分类:Python库 所属语言:Python 资源全名:wagtail-airtable-0.1.0.tar.gz 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059
资源推荐
资源详情
资源评论
收起资源包目录
wagtail-airtable-0.1.0.tar.gz (17个子文件)
wagtail-airtable-0.1.0
PKG-INFO 509B
pyproject.toml 395B
LICENSE 1KB
wagtail_airtable
serializers.py 738B
apps.py 106B
utils.py 4KB
templates
wagtail_airtable
airtable_import_listing.html 1KB
management
commands
reset_local_airtable_records.py 889B
import_airtable.py 26KB
mixins.py 13KB
__init__.py 0B
migrations
__init__.py 0B
views.py 5KB
tests.py 5KB
wagtail_hooks.py 2KB
forms.py 719B
setup.py 833B
共 17 条
- 1
资源评论
挣扎的蓝藻
- 粉丝: 14w+
- 资源: 15万+
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功