kopia lustrzana https://github.com/jedie/PyInventory
commit
2882d29fc7
|
@ -155,6 +155,7 @@ Files are separated into: "/src/" and "/development/"
|
|||
== history
|
||||
|
||||
* [[https://github.com/jedie/PyInventory/compare/v0.9.0...master|compare v0.9.0...master]] **dev**
|
||||
* NEW: It's not possible to upload file(s) to item.
|
||||
* Add a auto login if Django dev. server is used.
|
||||
** tbc
|
||||
* [[https://github.com/jedie/PyInventory/compare/v0.8.4...v0.9.0|v0.9.0 - 11.04.2021]]
|
||||
|
|
|
@ -218,6 +218,8 @@ history
|
|||
|
||||
* `compare v0.9.0...master <https://github.com/jedie/PyInventory/compare/v0.9.0...master>`_ **dev**
|
||||
|
||||
* NEW: It's not possible to upload file(s) to item.
|
||||
|
||||
* Add a auto login if Django dev. server is used.
|
||||
|
||||
* tbc
|
||||
|
@ -377,4 +379,4 @@ donation
|
|||
|
||||
------------
|
||||
|
||||
``Note: this file is generated from README.creole 2021-04-28 16:53:58 with "python-creole"``
|
||||
``Note: this file is generated from README.creole 2021-04-28 19:03:46 with "python-creole"``
|
|
@ -11,7 +11,7 @@ from import_export.resources import ModelResource
|
|||
from inventory.admin.base import BaseUserAdmin
|
||||
from inventory.forms import ItemModelModelForm
|
||||
from inventory.models import ItemLinkModel, ItemModel
|
||||
from inventory.models.item import ItemImageModel
|
||||
from inventory.models.item import ItemFileModel, ItemImageModel
|
||||
|
||||
|
||||
class UserInlineMixin:
|
||||
|
@ -49,6 +49,14 @@ class ItemImageModelInline(UserInlineMixin, SortableInlineAdminMixin, admin.Tabu
|
|||
readonly_fields = ('preview',)
|
||||
|
||||
|
||||
class ItemFileModelInline(UserInlineMixin, SortableInlineAdminMixin, admin.TabularInline):
|
||||
model = ItemFileModel
|
||||
extra = 0
|
||||
fields = (
|
||||
'position', 'file', 'name', 'tags'
|
||||
)
|
||||
|
||||
|
||||
class ItemModelResource(ModelResource):
|
||||
class Meta:
|
||||
model = ItemModel
|
||||
|
@ -134,7 +142,7 @@ class ItemModelAdmin(ImportExportMixin, BaseUserAdmin):
|
|||
)}),
|
||||
)
|
||||
readonly_fields = ('id', 'create_dt', 'update_dt', 'user')
|
||||
inlines = (ItemImageModelInline, ItemLinkModelInline)
|
||||
inlines = (ItemImageModelInline, ItemFileModelInline, ItemLinkModelInline)
|
||||
|
||||
def get_changelist(self, request, **kwargs):
|
||||
self.user = request.user
|
||||
|
|
Plik binarny nie jest wyświetlany.
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-11-15 13:09+0100\n"
|
||||
"PO-Revision-Date: 2020-11-15 13:14+0100\n"
|
||||
"POT-Creation-Date: 2021-04-28 18:31+0200\n"
|
||||
"PO-Revision-Date: 2021-04-28 18:29+0200\n"
|
||||
"Last-Translator: Jens Diemer\n"
|
||||
"Language-Team: \n"
|
||||
"Language: de\n"
|
||||
|
@ -50,8 +50,8 @@ msgstr "Benutzer"
|
|||
|
||||
msgid "BaseModel.user.help_text"
|
||||
msgstr ""
|
||||
" Der Benutzer dem dieser Eintrag gehört und verwalten kann (Wird "
|
||||
"automatisch gesetzt)"
|
||||
"Der Benutzer dem dieser Eintrag gehört und verwalten kann (Wird automatisch "
|
||||
"gesetzt)"
|
||||
|
||||
msgid "BaseModel.name.verbose_name"
|
||||
msgstr "Name"
|
||||
|
@ -65,6 +65,12 @@ msgstr "Tags"
|
|||
msgid "BaseModel.tags.help_text"
|
||||
msgstr " "
|
||||
|
||||
msgid "BaseItemAttachmentModel.name.verbose_name"
|
||||
msgstr "Name"
|
||||
|
||||
msgid "BaseItemAttachmentModel.name.help_text"
|
||||
msgstr "Optionalen Namen (Wird automatisch aus dem Dateinamen gesetzt)"
|
||||
|
||||
msgid "ItemModel.kind.verbose_name"
|
||||
msgstr "Art"
|
||||
|
||||
|
@ -100,7 +106,7 @@ msgstr "Übergeordnet"
|
|||
|
||||
msgid "ItemModel.parent.help_text"
|
||||
msgstr ""
|
||||
" Eingebaut in einem anderen Gegenstand? (e.g.: Grafikkarte eingebaut in "
|
||||
"Eingebaut in einem anderen Gegenstand? (e.g.: Grafikkarte eingebaut in "
|
||||
"Rechner)"
|
||||
|
||||
msgid "ItemModel.lent_to.verbose_name"
|
||||
|
@ -170,15 +176,7 @@ msgid "ItemImageModel.image.verbose_name"
|
|||
msgstr "Bild"
|
||||
|
||||
msgid "ItemImageModel.image.help_text"
|
||||
msgstr ""
|
||||
|
||||
msgid "ItemImageModel.name.verbose_name"
|
||||
msgstr "Name"
|
||||
|
||||
msgid "ItemImageModel.name.help_text"
|
||||
msgstr ""
|
||||
"Optionalen Namen passend zum Bild (Wird automatisch aus dem Dateinamen "
|
||||
"gesetzt)"
|
||||
msgstr " "
|
||||
|
||||
msgid "ItemImageModel.verbose_name"
|
||||
msgstr "Bild"
|
||||
|
@ -186,6 +184,18 @@ msgstr "Bild"
|
|||
msgid "ItemImageModel.verbose_name_plural"
|
||||
msgstr "Bilder"
|
||||
|
||||
msgid "ItemFileModel.file.verbose_name"
|
||||
msgstr "Datei"
|
||||
|
||||
msgid "ItemFileModel.file.help_text"
|
||||
msgstr ""
|
||||
|
||||
msgid "ItemFileModel.verbose_name"
|
||||
msgstr "Datei"
|
||||
|
||||
msgid "ItemFileModel.verbose_name_plural"
|
||||
msgstr "Dateien"
|
||||
|
||||
msgid "BaseLink.name.verbose_name"
|
||||
msgstr "Name"
|
||||
|
||||
|
@ -227,16 +237,3 @@ msgstr "Standort"
|
|||
|
||||
msgid "LocationModel.verbose_name_plural"
|
||||
msgstr "Standorte"
|
||||
|
||||
#, python-format
|
||||
msgid "Image \"%(path)s\" does not exist"
|
||||
msgstr ""
|
||||
|
||||
msgid "German"
|
||||
msgstr ""
|
||||
|
||||
msgid "English"
|
||||
msgstr ""
|
||||
|
||||
msgid "Log in"
|
||||
msgstr ""
|
||||
|
|
Plik binarny nie jest wyświetlany.
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-11-15 13:09+0100\n"
|
||||
"PO-Revision-Date: 2020-11-15 13:15+0100\n"
|
||||
"POT-Creation-Date: 2021-04-28 18:31+0200\n"
|
||||
"PO-Revision-Date: 2021-04-28 18:30+0200\n"
|
||||
"Last-Translator: Jens Diemer\n"
|
||||
"Language-Team: \n"
|
||||
"Language: en\n"
|
||||
|
@ -50,7 +50,7 @@ msgstr "User"
|
|||
|
||||
msgid "BaseModel.user.help_text"
|
||||
msgstr ""
|
||||
" The user who is the owner of this entry and can manage it (will be set "
|
||||
"The user who is the owner of this entry and can manage it (will be set "
|
||||
"automatically)"
|
||||
|
||||
msgid "BaseModel.name.verbose_name"
|
||||
|
@ -65,11 +65,17 @@ msgstr "Tags"
|
|||
msgid "BaseModel.tags.help_text"
|
||||
msgstr " "
|
||||
|
||||
msgid "BaseItemAttachmentModel.name.verbose_name"
|
||||
msgstr "Name"
|
||||
|
||||
msgid "BaseItemAttachmentModel.name.help_text"
|
||||
msgstr ""
|
||||
|
||||
msgid "ItemModel.kind.verbose_name"
|
||||
msgstr "Kind"
|
||||
|
||||
msgid "ItemModel.kind.help_text"
|
||||
msgstr ""
|
||||
msgstr " "
|
||||
|
||||
msgid "ItemModel.producer.verbose_name"
|
||||
msgstr "Producer"
|
||||
|
@ -170,18 +176,24 @@ msgstr "Image"
|
|||
msgid "ItemImageModel.image.help_text"
|
||||
msgstr " "
|
||||
|
||||
msgid "ItemImageModel.name.verbose_name"
|
||||
msgstr "Name"
|
||||
|
||||
msgid "ItemImageModel.name.help_text"
|
||||
msgstr ""
|
||||
|
||||
msgid "ItemImageModel.verbose_name"
|
||||
msgstr "Image"
|
||||
|
||||
msgid "ItemImageModel.verbose_name_plural"
|
||||
msgstr "Images"
|
||||
|
||||
msgid "ItemFileModel.file.verbose_name"
|
||||
msgstr "File"
|
||||
|
||||
msgid "ItemFileModel.file.help_text"
|
||||
msgstr " "
|
||||
|
||||
msgid "ItemFileModel.verbose_name"
|
||||
msgstr "File"
|
||||
|
||||
msgid "ItemFileModel.verbose_name_plural"
|
||||
msgstr "Files"
|
||||
|
||||
msgid "BaseLink.name.verbose_name"
|
||||
msgstr "Name"
|
||||
|
||||
|
@ -204,7 +216,7 @@ msgid "Link.page_title.verbose_name"
|
|||
msgstr "Page title"
|
||||
|
||||
msgid "Link.page_title.help_text"
|
||||
msgstr ""
|
||||
msgstr " "
|
||||
|
||||
msgid "LocationModel.description.verbose_name"
|
||||
msgstr "Description"
|
||||
|
@ -223,16 +235,3 @@ msgstr "Location"
|
|||
|
||||
msgid "LocationModel.verbose_name_plural"
|
||||
msgstr "Locations"
|
||||
|
||||
#, python-format
|
||||
msgid "Image \"%(path)s\" does not exist"
|
||||
msgstr ""
|
||||
|
||||
msgid "German"
|
||||
msgstr ""
|
||||
|
||||
msgid "English"
|
||||
msgstr ""
|
||||
|
||||
msgid "Log in"
|
||||
msgstr ""
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
# Generated by Django 2.2.20 on 2021-04-28 15:44
|
||||
|
||||
from django.db import migrations, models
|
||||
import tagulous.models.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0005_serve_uploads_by_django_tools'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='itemimagemodel',
|
||||
name='name',
|
||||
field=models.CharField(blank=True, help_text='BaseItemAttachmentModel.name.help_text', max_length=255, null=True, verbose_name='BaseItemAttachmentModel.name.verbose_name'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Tagulous_BaseItemAttachmentModel_tags',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=255, unique=True)),
|
||||
('slug', models.SlugField()),
|
||||
('count', models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use')),
|
||||
('protected', models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0')),
|
||||
],
|
||||
options={
|
||||
'ordering': ('name',),
|
||||
'abstract': False,
|
||||
'unique_together': {('slug',)},
|
||||
},
|
||||
bases=(tagulous.models.models.BaseTagModel, models.Model),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,55 @@
|
|||
# Generated by Django 2.2.20 on 2021-04-28 15:54
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django_tools.serve_media_app.models
|
||||
import tagulous.models.fields
|
||||
import tagulous.models.models
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('inventory', '0006_refactor_image_model'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Tagulous_ItemFileModel_tags',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=255, unique=True)),
|
||||
('slug', models.SlugField()),
|
||||
('count', models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use')),
|
||||
('protected', models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0')),
|
||||
],
|
||||
options={
|
||||
'ordering': ('name',),
|
||||
'abstract': False,
|
||||
'unique_together': {('slug',)},
|
||||
},
|
||||
bases=(tagulous.models.models.BaseTagModel, models.Model),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ItemFileModel',
|
||||
fields=[
|
||||
('create_dt', models.DateTimeField(blank=True, editable=False, help_text='ModelTimetrackingMixin.create_dt.help_text', null=True, verbose_name='ModelTimetrackingMixin.create_dt.verbose_name')),
|
||||
('update_dt', models.DateTimeField(blank=True, editable=False, help_text='ModelTimetrackingMixin.update_dt.help_text', null=True, verbose_name='ModelTimetrackingMixin.update_dt.verbose_name')),
|
||||
('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='BaseModel.id.help_text', primary_key=True, serialize=False, verbose_name='BaseModel.id.verbose_name')),
|
||||
('name', models.CharField(blank=True, help_text='BaseItemAttachmentModel.name.help_text', max_length=255, null=True, verbose_name='BaseItemAttachmentModel.name.verbose_name')),
|
||||
('position', models.PositiveSmallIntegerField(default=0)),
|
||||
('file', models.FileField(help_text='ItemFileModel.file.help_text', upload_to=django_tools.serve_media_app.models.user_directory_path, verbose_name='ItemFileModel.file.verbose_name')),
|
||||
('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inventory.ItemModel')),
|
||||
('tags', tagulous.models.fields.TagField(_set_tag_meta=True, blank=True, case_sensitive=False, force_lowercase=False, help_text='BaseModel.tags.help_text', max_count=10, space_delimiter=False, to='inventory.Tagulous_ItemFileModel_tags', verbose_name='BaseModel.tags.verbose_name')),
|
||||
('user', models.ForeignKey(editable=False, help_text='BaseModel.user.help_text', on_delete=django.db.models.deletion.CASCADE, related_name='+', to=settings.AUTH_USER_MODEL, verbose_name='BaseModel.user.verbose_name')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'ItemFileModel.verbose_name',
|
||||
'verbose_name_plural': 'ItemFileModel.verbose_name_plural',
|
||||
'ordering': ('position',),
|
||||
},
|
||||
),
|
||||
]
|
|
@ -43,3 +43,34 @@ class BaseModel(TimetrackingBaseModel):
|
|||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
|
||||
class BaseItemAttachmentModel(BaseModel):
|
||||
"""
|
||||
Base model to store files or images to Items
|
||||
"""
|
||||
name = models.CharField(
|
||||
null=True, blank=True,
|
||||
max_length=255,
|
||||
verbose_name=_('BaseItemAttachmentModel.name.verbose_name'),
|
||||
help_text=_('BaseItemAttachmentModel.name.help_text')
|
||||
)
|
||||
item = models.ForeignKey('ItemModel', on_delete=models.CASCADE)
|
||||
position = models.PositiveSmallIntegerField(
|
||||
# Note: Will be set in admin via adminsortable2
|
||||
# The JavaScript which performs the sorting is 1-indexed !
|
||||
default=0, blank=False, null=False
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def full_clean(self, **kwargs):
|
||||
if self.user_id is None:
|
||||
# inherit owner of this link from item instance
|
||||
self.user_id = self.item.user_id
|
||||
|
||||
return super().full_clean(**kwargs)
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
|
|
@ -9,7 +9,7 @@ from django.urls import reverse
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from django_tools.serve_media_app.models import user_directory_path
|
||||
|
||||
from inventory.models.base import BaseModel
|
||||
from inventory.models.base import BaseItemAttachmentModel, BaseModel
|
||||
from inventory.models.links import BaseLink
|
||||
|
||||
|
||||
|
@ -177,45 +177,55 @@ class ItemLinkModel(BaseLink):
|
|||
ordering = ('position',)
|
||||
|
||||
|
||||
class ItemImageModel(BaseModel):
|
||||
class ItemImageModel(BaseItemAttachmentModel):
|
||||
"""
|
||||
Store Images to Items
|
||||
Store images to Items
|
||||
"""
|
||||
image = models.ImageField(
|
||||
upload_to=user_directory_path,
|
||||
verbose_name=_('ItemImageModel.image.verbose_name'),
|
||||
help_text=_('ItemImageModel.image.help_text')
|
||||
)
|
||||
name = models.CharField(
|
||||
null=True, blank=True,
|
||||
max_length=255,
|
||||
verbose_name=_('ItemImageModel.name.verbose_name'),
|
||||
help_text=_('ItemImageModel.name.help_text')
|
||||
)
|
||||
item = models.ForeignKey(
|
||||
ItemModel, on_delete=models.CASCADE
|
||||
)
|
||||
position = models.PositiveSmallIntegerField(
|
||||
# Note: Will be set in admin via adminsortable2
|
||||
# The JavaScript which performs the sorting is 1-indexed !
|
||||
default=0, blank=False, null=False
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return self.name or self.image.name
|
||||
|
||||
def full_clean(self, **kwargs):
|
||||
# Set name by image filename:
|
||||
if not self.name:
|
||||
filename = Path(self.image.name).name
|
||||
self.name = clean_filename(filename)
|
||||
|
||||
if self.user_id is None:
|
||||
# inherit owner of this link from item instance
|
||||
self.user_id = self.item.user_id
|
||||
|
||||
return super().full_clean(**kwargs)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('ItemImageModel.verbose_name')
|
||||
verbose_name_plural = _('ItemImageModel.verbose_name_plural')
|
||||
ordering = ('position',)
|
||||
|
||||
|
||||
class ItemFileModel(BaseItemAttachmentModel):
|
||||
"""
|
||||
Store files to Items
|
||||
"""
|
||||
file = models.FileField(
|
||||
upload_to=user_directory_path,
|
||||
verbose_name=_('ItemFileModel.file.verbose_name'),
|
||||
help_text=_('ItemFileModel.file.help_text')
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return self.name or self.file.name
|
||||
|
||||
def full_clean(self, **kwargs):
|
||||
# Set name by filename:
|
||||
if not self.name:
|
||||
filename = Path(self.file.name).name
|
||||
self.name = clean_filename(filename)
|
||||
|
||||
return super().full_clean(**kwargs)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('ItemFileModel.verbose_name')
|
||||
verbose_name_plural = _('ItemFileModel.verbose_name_plural')
|
||||
ordering = ('position',)
|
||||
|
|
|
@ -44,16 +44,25 @@ class AdminTestCase(HtmlAssertionMixin, TestCase):
|
|||
data={
|
||||
'kind': 'kind',
|
||||
'name': 'name',
|
||||
|
||||
'itemimagemodel_set-TOTAL_FORMS': '0',
|
||||
'itemimagemodel_set-INITIAL_FORMS': '0',
|
||||
'itemimagemodel_set-MIN_NUM_FORMS': '0',
|
||||
'itemimagemodel_set-MAX_NUM_FORMS': '1000',
|
||||
'itemimagemodel_set-__prefix__-position': '0',
|
||||
|
||||
'itemfilemodel_set-TOTAL_FORMS': '0',
|
||||
'itemfilemodel_set-INITIAL_FORMS': '0',
|
||||
'itemfilemodel_set-MIN_NUM_FORMS': '0',
|
||||
'itemfilemodel_set-MAX_NUM_FORMS': '1000',
|
||||
'itemfilemodel_set-__prefix__-position': '0',
|
||||
|
||||
'itemlinkmodel_set-TOTAL_FORMS': '0',
|
||||
'itemlinkmodel_set-INITIAL_FORMS': '0',
|
||||
'itemlinkmodel_set-MIN_NUM_FORMS': '0',
|
||||
'itemlinkmodel_set-MAX_NUM_FORMS': '1000',
|
||||
'itemlinkmodel_set-__prefix__-position': '0',
|
||||
|
||||
'_save': 'Save',
|
||||
},
|
||||
)
|
||||
|
@ -84,6 +93,7 @@ class AdminTestCase(HtmlAssertionMixin, TestCase):
|
|||
data={
|
||||
'kind': 'kind',
|
||||
'name': 'name',
|
||||
|
||||
'itemimagemodel_set-TOTAL_FORMS': '1',
|
||||
'itemimagemodel_set-INITIAL_FORMS': '0',
|
||||
'itemimagemodel_set-MIN_NUM_FORMS': '0',
|
||||
|
@ -91,11 +101,19 @@ class AdminTestCase(HtmlAssertionMixin, TestCase):
|
|||
'itemimagemodel_set-0-position': '0',
|
||||
'itemimagemodel_set-__prefix__-position': '0',
|
||||
'itemimagemodel_set-0-image': img,
|
||||
|
||||
'itemfilemodel_set-TOTAL_FORMS': '0',
|
||||
'itemfilemodel_set-INITIAL_FORMS': '0',
|
||||
'itemfilemodel_set-MIN_NUM_FORMS': '0',
|
||||
'itemfilemodel_set-MAX_NUM_FORMS': '1000',
|
||||
'itemfilemodel_set-__prefix__-position': '0',
|
||||
|
||||
'itemlinkmodel_set-TOTAL_FORMS': '0',
|
||||
'itemlinkmodel_set-INITIAL_FORMS': '0',
|
||||
'itemlinkmodel_set-MIN_NUM_FORMS': '0',
|
||||
'itemlinkmodel_set-MAX_NUM_FORMS': '1000',
|
||||
'itemlinkmodel_set-__prefix__-position': '0',
|
||||
|
||||
'_save': 'Save',
|
||||
},
|
||||
)
|
||||
|
|
Ładowanie…
Reference in New Issue