我尝试通过django管理添加新文档,当我提交表单时,网页发送了一个添加请求,并在控制台显示whois sender= <class 'my_apps.document.models.Document'> is super = <django.db.models.query_utils.DeferredAttribute object at 0x000002058684C400>
时卡住了
models.py
# document/models.py
from pustakalaya_apps.audio.models import Audio
from pustakalaya_apps.video.models import Video
from .search import DocumentDoc
from django.contrib.contenttypes.models import ContentType
from star_ratings.models import Rating
import datetime
date = datetime.datetime.now()
logger = logging.getLogger('app.logger')
class FeaturedItemManager(models.Manager):
def get_queryset(self):
return super(FeaturedItemManager, self).get_queryset().filter(published="yes", featured="yes").order_by("-updated_date")[:10]
def accessibleuploadpath(instance, filename):
formatted_filename = ''.join(letter for letter in filename.replace(' ', '_') if letter.isalnum() or letter == '_')
directory_path = "uploads/accessibility/documents/{}/{}_{}/{}".format(
time.strftime("%Y/%m/%d"),
"_".join(formatted_filename.split(" ")),
str(uuid.uuid4())[:8],
filename
)
return directory_path
class Document(AbstractItem, HitCountMixin):
"""Book document type to store book type item
Child class of AbstractItem
"""
ITEM_INTERACTIVE_TYPE = (
("yes", _("Yes")),
("NA", _("Not applicable")),
)
DOCUMENT_TYPE = (
("book", _("Book")),
("working paper", _("Working paper")),
("thesis", _("Thesis")),
("journal paper", _("Journal paper")),
("technical report", _("Technical report")),
("article", _("Article")),
("exam sets", _("Exam sets"))
)
DOCUMENT_FILE_TYPE = (
("ppt", _("PPT")),
("doc", _("Doc")),
("docx", _("Docx")),
("pdf", _("PDF")),
("xlsx", _("Excel")),
("epub", _("Epub")),
("rtf", _("Rtf")),
("mobi", _("Mobi")),
)
collections = models.ManyToManyField(
Collection,
verbose_name=_("Add to these collections"),
)
document_type = models.CharField(
_("Document type"),
max_length=40, # TODO: Change to match the exact value.
choices=DOCUMENT_TYPE,
)
document_file_type = models.CharField(
_("Document file format"),
choices=DOCUMENT_FILE_TYPE,
max_length=23,
default="pdf"
)
document_series = models.ForeignKey(
"DocumentSeries",
verbose_name=_("Series"),
on_delete=models.SET_NULL,
blank=True,
null=True
)
education_levels = models.ManyToManyField(
EducationLevel,
verbose_name=_("Education Levels"),
blank=True
)
grades_subjects_chapters = models.ManyToManyField(
GradeSubjectChapter,
verbose_name=_("Grade>Subject>Chapter"),
blank=True
)
languages = models.ManyToManyField(
Language,
verbose_name=_("Language(s)"),
blank=True
)
document_interactivity = models.CharField(
verbose_name=_("Interactive"),
max_length=15,
choices=ITEM_INTERACTIVE_TYPE,
blank=True,
default="NA"
)
# This field should be same on all other model to make searching easy in search engine.
type = models.CharField(
max_length=255, editable=False, default="document"
)
document_total_page = models.CharField(
verbose_name=_("Total Pages"),
blank=True,
validators=[validate_number],
max_length=7
)
document_authors = models.ManyToManyField(
Biography,
verbose_name=_("Author(s)"),
related_name="authors",
blank=True,
)
document_editors = models.ManyToManyField(
Biography,
verbose_name=_("Editor(s)"),
related_name="editors",
blank=True,
)
document_translator = models.ManyToManyField(
Biography,
verbose_name=_("Translator(s)"),
related_name="translators",
blank=True,
)
document_illustrators = models.ManyToManyField(
Biography,
verbose_name=_("Illustrator"),
related_name="illustrators",
blank=True
)
publisher = models.ManyToManyField(
Publisher,
verbose_name=_("Publisher name"),
related_name="publisher",
blank=True,
)
# Better to have plural name
keywords = models.ManyToManyField(
Keyword,
verbose_name=_("Select list of keywords"),
blank=True
)
license = models.ForeignKey(
LicenseType,
on_delete=models.SET_NULL,
verbose_name=_("license"),
blank=True,
null=True,
)
thumbnail = models.ImageField(
upload_to="uploads/thumbnails/document/%Y/%m/%d",
max_length=255,
blank=True,
help_text=_("maximum size of thumbnail should be 255px by 300px")
)
sponsors = models.ManyToManyField(
Sponsor,
verbose_name=_("Sponsor"),
blank=True,
)
submitted_by = models.ForeignKey(
User,
on_delete=models.SET_NULL,
editable=False,
null=True
)
# Manager to return the featured objects.
objects = models.Manager()
featured_objects = FeaturedItemManager()
# View count properties.
hit_count_generic = GenericRelation(
HitCount, object_id_field='object_pk',
related_query_name='hit_count_generic_relation')
class Meta:
ordering = ('title',)
def save(self):
if self.thumbnail == None or self.thumbnail == '':
filename = ''.join(letter for letter in self.title.replace(' ', '_') if letter.isalnum() or letter == '_')
thumbnail = "uploads/thumbnails/document/{}/{}.jpg".format(time.strftime("%Y/%m/%d"), filename)
self.thumbnail = thumbnail
print(settings.MEDIA_ROOT)
print(settings.STATIC_ROOT)
super(Document, self).save()
else:
super(Document, self).save()
@property
def getauthors(self):
author_list = [(author.getname, author.pk) for author in self.document_authors.all()]
return author_list or [None] # If emtpy, return something otherwise it will break elastic index while searching.
@property
def get_view_count(self):
try:
hitcount = HitCount.objects.get(object_pk=self.id)
# print('Indexing hitcount................................................', hitcount.hits)
return hitcount.hits or 0
except HitCount.DoesNotExist:
# print('Does not exists............................................... 0')
return 0
def get_similar_items(self):
from pustakalaya_apps.video.models import Video
from pustakalaya_apps.audio.models import Audio
documents = Document.objects.filter(published='yes', keywords__in=[keyword.id for keyword in self.keywords.all()])
audios = Audio.objects.filter(published='yes', keywords__in=[keyword.id for keyword in self.keywords.all()])
videos = Video.objects.filter(published='yes', keywords__in=[keyword.id for keyword in self.keywords.all()])
all_items = chain(documents, audios, videos)
item_counter = collections.Counter(all_items)
return chain(item_counter.most_common(6))
def __str__(self):
return self.title
def doc(self):
"""Create and return document object"""
item_attr = super(Document, self).doc()
document_attr = dict(
**item_attr,
type=self.type,
education_levels=[education_level.level for education_level in self.education_levels.all()],
grades=[grade_subject_chapter.gradesubject.grade.name for grade_subject_chapter in
self.grades_subjects_chapters.all()],
subjects=[grade_subject_chapter.gradesubject.subject.name for grade_subject_chapter in
self.grades_subjects_chapters.all()],
chapters=[grade_subject_chapter.chapter.name for grade_subject_chapter in
self.grades_subjects_chapters.all()],
communities=[collection.community_name for collection in self.collections.all()],
collections=[collection.collection_name for collection in self.collections.all()],
collections_ids=[collection.pk for collection in self.collections.all()],
languages=[language.language.lower() for language in self.languages.all()],
publisher=[publisher.publisher_name for publisher in self.publisher.all()],
sponsors=[sponsor.name for sponsor in self.sponsors.all()], # Multi value # TODO some generators
keywords=[keyword.keyword for keyword in self.keywords.all()],
# License type
license_type=self.license.license if self.license else None,
# Document type specific
thumbnail=self.thumbnail.name,
# document_identifier_type=self.document_identifier_type,
document_file_type=self.document_file_type,
document_type=self.document_type,
document_authors=[
author.getname for author in self.document_authors.all()
],
document_illustrators=[
illustrator.getname for illustrator in self.document_illustrators.all()
], # Multi value TODO generator
document_editors=[
editor.getname for editor in self.document_editors.all()
], # Multi value
document_translator=[
translator.getname for translator in self.document_translator.all()
],
document_total_page=self.document_total_page,
# Document interactivity
document_interactivity=self.document_interactivity,
# author with name and id.
author_list=self.getauthors,
url=self.get_absolute_url()
)
# Create ES Document for indexing
obj = DocumentDoc(
**document_attr,
)
return obj
@property
def get_publisher_name(self):
"""
Method that return publisher name to index in elastic search server
If publisher name is None return empty string
:return:
"""
if self.publisher is None:
return " "
return self.publisher.publisher_name
def delete_index(self):
try:
self.doc().delete()
except NotFoundError:
# TODO:
pass
def index(self):
"""index or update a document instance to elastic search index server"""
# Index to index server if any doc is not empty and published status is "yes"
if self.published == "no":
# delete this if the published is set to no form
self.delete_index()
else:
#save only when published is yes
self.doc().save()
def bulk_index(self):
# Do bulk index if doc item is not empty.
return self.doc().to_dict(include_meta=True)
def get_absolute_url(self):
return reverse("document:detail_without_slug", kwargs={ "pk": self.pk})
# return reverse("document:detail", kwargs={"title": slugify(self.title), "pk": self.pk})
def get_dashboard_edit_url(self):
return reverse("dashboard:document_update", kwargs={"pk": self.pk})
def get_dashboard_delete_url(self):
return reverse("dashboard:document_delete", kwargs={"pk": self.pk})
def get_admin_url(self):
return urlresolvers.reverse("admin:%s_%s_change" %(self._meta.app_label, self._meta.model_name), args=(self.pk,))
def document_title(self):
return self.title
def published_yes_no(self):
return self.published
def featured_yes_no(self):
return self.featured
def updated_date_string(self):
return self.updated_date
def submited_by(self):
return self.submitted_by
def document_link_name(self):
return self.link_name;
def get_fileuploads(self):
return self.documentfileupload_set.all()
class UnpublishedDocument(Document):
"""
This is the proxy model of Document,
Used in admin.py to display the list of unpublished document.
"""
class Meta:
proxy = True
class FeaturedDocument(Document):
"""
This is the proxy model of Document,
Used in admin.py to display the list of unpublished document.
"""
class Meta:
proxy = True
class DocumentSeries(AbstractSeries):
"""BookSeries table inherited from AbstractSeries"""
class Meta:
verbose_name_plural = _("Document series")
def __str__(self):
return self.series_name
def uploadpath(instance, filename):
formatted_filename = ''.join(letter for letter in instance.file_name.replace(' ', '_') if letter.isalnum() or letter == '_')
directory_path = "uploads/documents/{}/{}_{}/{}".format(
time.strftime("%Y/%m/%d"),
"_".join(formatted_filename.split(" ")),
str(uuid.uuid4())[:8],
filename
)
return directory_path
class DocumentFileUpload(AbstractTimeStampModel):
"""Class to upload the multiple document objects"""
file_name = models.CharField(
_("File name"),
max_length=255,
blank=True,
default=""
)
document = models.ForeignKey(
Document,
on_delete=models.CASCADE
)
publisher = models.ManyToManyField(
Publisher,
verbose_name=_("Publisher(s)"),
blank=True,
)
upload = models.FileField(
upload_to=uploadpath,
max_length=255
)
total_pages = models.IntegerField(default=0, editable=False)
def get_files(self):
images = []
for i in range(self.total_pages):
path, file_name = os.path.split(self.upload.url)
images.append("{}/{}.png".format(path, i))
return images
def __str__(self):
return self.file_name
class Meta:
ordering=['created_date']
def documentfileupload_post_save(sender, instance=False, **kwargs):
"""This post save function creates a thumbnail for the Document"""
documentfile = DocumentFileUpload.objects.filter(document=instance.document)
for file in documentfile:
filename = ''.join(letter for letter in file.document.title.replace(' ', '_') if letter.isalnum() or letter == '_')
if file.document.thumbnail == "uploads/thumbnails/document/{}/{}.jpg".format(time.strftime("%Y/%m/%d"), filename):
path = os.path.join(settings.MEDIA_ROOT, "uploads/thumbnails/document/{}".format(time.strftime("%Y/%m/%d")))
if not os.path.exists(path):
try:
logger.info('Making required folder structures for converted thumbnail uploads.')
os.makedirs(path)
logger.info('Folder structures made successfully.')
except Exception as e:
logger.info('Got exception: {}'.format(e))
pass
logger.info('Creating Document Thumbnail...')
file_path = settings.MEDIA_ROOT + str(file.upload)
pages = convert_from_path(file_path, 50)[0]
upload_path = settings.MEDIA_ROOT + str(file.document.thumbnail)
pages.save(upload_path, 'JPEG')
logger.info('Document Thumbnail created successfully...')
# Hook up the signal
post_save.connect(documentfileupload_post_save, sender=DocumentFileUpload)
def add_file_name(sender, instance=False, **kwargs):
logger = logging.getLogger('app.logger')
try:
if not instance.file_name:
base = os.path.basename(instance.upload.name)
filename = os.path.splitext(base)[0].capitalize()
instance.file_name = filename
logger.info('File name field feeded.')
except Exception as e:
logger.error('Failed to feed file_name field: {}'.format(e))
pre_save.connect(add_file_name, sender=DocumentFileUpload)
class DocumentLinkInfo(LinkInfo):
document = models.ForeignKey(
Document,
verbose_name=_("Link"),
#on_delete=models.CASCADE,
)
publisher = models.ManyToManyField(
Publisher,
verbose_name=_("Publisher(s)"),
blank=True,
)
def __str__(self):
return self.link_name
class Meta:
ordering=['created_date']
class DocumentIdentifier(AbstractTimeStampModel):
identifier_type = models.CharField(
verbose_name=_("Identifier Type"),
max_length=8,
blank=True,
choices=(
("issn", _("ISSN")),
("ismn", _("ISMN")),
("govt_doc", _("Gov't Doc")),
("uri", _("URI")),
("isbn", _("ISBN"))
)
)
identifier_id = models.CharField(
_("Identifier ID"),
blank=True,
max_length=30
)
document = models.OneToOneField(
Document,
verbose_name=_("document"),
on_delete=models.CASCADE,
)
def __str__(self):
return self.identifier_type
signals.py
from __future__ import print_function
import os
from django.dispatch import receiver
from django.db import transaction
from django.db.models.signals import post_save, pre_delete, m2m_changed, post_delete
from .models import Document, DocumentFileUpload
from ****_apps.core.utils import send_mail_on_user_submission, write_gradewise_to_file
from django.contrib.auth.models import User
@receiver(m2m_changed, sender=Document.keywords.through)
@receiver(m2m_changed, sender=Document.document_authors.through)
@receiver(m2m_changed, sender=Document.education_levels.through)
@receiver(m2m_changed, sender=Document.document_illustrators.through)
@receiver(m2m_changed, sender=Document.document_editors.through)
@receiver(m2m_changed, sender=Document.collections.through)
@receiver(m2m_changed, sender=Document)
@receiver(post_save, sender=Document)
@transaction.atomic
def index_or_update_document(sender, instance, **kwargs):
# send an email to user when the document is published.
# By pass for unpublished items
# if instance.published == "no":
# return
if instance.published == "yes":
# added to restrict the if user is super user
# if not sender is User.is_superuser:
print("whois sender=",sender,"is super =",User.is_superuser)
send_mail_on_user_submission(item=instance)
if instance.license is not None:
if instance.license:
instance.license_type = instance.license.license
# Save or update index
instance.index()
@receiver(pre_delete, sender=Document)
@transaction.atomic
def delete_document(sender, instance, **kwargs):
# By pass for unpublished items
# if instance.published == "no":
# return
# Delete an index first before instance in db.
instance.delete_index()
@receiver(post_save, sender=DocumentFileUpload)
@transaction.atomic
def create_or_update_documentuploads(sender, instance, **kwargs):
if instance.document.is_grade_wise == 'yes':
write_gradewise_to_file(instance.upload.url, 'document', 'save')
@receiver(post_delete, sender=DocumentFileUpload)
@transaction.atomic
def delete_documentuploads(sender, instance, **kwargs):
if instance.document.is_grade_wise == 'yes':
write_gradewise_to_file(instance.upload.url, 'document', 'delete')
views.py
def documents(request):
documents = 1 or Document.objects.all()
return render(request, 'document/documents.html', {'documents': documents})
search.py
class DocumentDoc(ItemDoc):
"""Elastic search schema for document type"""
# Document type specific
thumbnail = Text()
document_total_page = Long()
document_file_type = Text()
document_type = Text()
document_authors = Text(multi=True)
document_illustrators = Text(multi=True) # Multi value TODO generator
document_editors = Text(multi=True)
document_interactivity = Text()
class Meta:
index = settings.ES_INDEX
doc_type = "document"
每个必填字段均已填写,数据库已连接,并且已应用正确的迁移。
1条答案
按热度按时间pftdvrlh1#
您应该使
save()
方法签名与底层方法签名兼容,例如*args
和**kwargs
。但是,您已经有了一个
upload_to
,因此thumbnail
不会是None
或空。如果要自动指定随机文件名,请用途: