From e08aac9aad6a1a5b95201289ad87deed586f3b04 Mon Sep 17 00:00:00 2001 From: Jeff MacKinnon Date: Tue, 21 Nov 2023 15:08:11 -0400 Subject: [PATCH] Initial Commit --- .gitignore | 1 + LICENSE | 0 MANIFEST.in | 4 ++++ README.md | 3 +++ dist/django-tags-0.1.tar.gz | Bin 0 -> 3310 bytes pyproject.toml | 3 +++ setup.cfg | 33 +++++++++++++++++++++++++++++++++ setup.py | 3 +++ tags/__init__.py | 0 tags/admin.py | 13 +++++++++++++ tags/apps.py | 6 ++++++ tags/forms.py | 9 +++++++++ tags/models.py | 29 +++++++++++++++++++++++++++++ tags/templates/tags/list.html | 10 ++++++++++ tags/tests.py | 3 +++ tags/urls.py | 11 +++++++++++ tags/views.py | 14 ++++++++++++++ 17 files changed, 142 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 MANIFEST.in create mode 100644 README.md create mode 100644 dist/django-tags-0.1.tar.gz create mode 100644 pyproject.toml create mode 100644 setup.cfg create mode 100644 setup.py create mode 100644 tags/__init__.py create mode 100644 tags/admin.py create mode 100644 tags/apps.py create mode 100644 tags/forms.py create mode 100644 tags/models.py create mode 100644 tags/templates/tags/list.html create mode 100644 tags/tests.py create mode 100644 tags/urls.py create mode 100644 tags/views.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..690fe81 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +django_tags* \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e69de29 diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..dae0c2f --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,4 @@ +include LICENSE +include README.md +recursive-include docs * +recursive-include tags/templates * diff --git a/README.md b/README.md new file mode 100644 index 0000000..b8cce36 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Jeff Django tags + +This is a simple app that allows us to create tags and then tag any entity within the project. \ No newline at end of file diff --git a/dist/django-tags-0.1.tar.gz b/dist/django-tags-0.1.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..d0db614373f254a3d16190c44c9a3ba1afbc38e1 GIT binary patch literal 3310 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 K7a6t~82$(D7y1VP literal 0 HcmV?d00001 diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..c515c82 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ['setuptools>=40.8.0'] +build-backend = 'setuptools.build_meta' \ No newline at end of file diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..de2db7d --- /dev/null +++ b/setup.cfg @@ -0,0 +1,33 @@ +[metadata] +name = django-tags +version = 0.1 +description = A Django app to tag entities. +long_description = file: readme.md +url = https://www.jeffmackinnon.com/pages/apps.html +author = Jeff MacKinnon +author_email = jeff@fastmail.in +license = BSD-3-Clause +classifiers = + Environment :: Web Environment + Framework :: Django + Framework :: Django :: 4.2 + Intended Audience :: Developers + License :: OSI Approved :: BSD License + Operating System :: OS Independent + Programming Language :: Python + Programming Language :: Python :: 3 + Programming Language :: Python :: 3 :: Only + Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 + Programming Language :: Python :: 3.11 + Programming Language :: Python :: 3.12 + Topic :: Internet :: WWW/HTTP + Topic :: Internet :: WWW/HTTP :: Dynamic Content + +[options] +include_package_data = true +packages = find: +python_requires = >=3.8 +install_requires = + Django >= 4.2 \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..fc1f76c --- /dev/null +++ b/setup.py @@ -0,0 +1,3 @@ +from setuptools import setup + +setup() \ No newline at end of file diff --git a/tags/__init__.py b/tags/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tags/admin.py b/tags/admin.py new file mode 100644 index 0000000..cee8e6e --- /dev/null +++ b/tags/admin.py @@ -0,0 +1,13 @@ +from django.contrib import admin +from . import models + +# Register your models here. + +@admin.register(models.Tag) +class TagAdmin(admin.ModelAdmin): + list_display = ['label', 'type'] + list_editable = ['type'] + +@admin.register(models.TaggedItem) +class TaggedAdmin(admin.ModelAdmin): + list_display = ['tag', 'content_type', 'content_object', 'tagged'] diff --git a/tags/apps.py b/tags/apps.py new file mode 100644 index 0000000..77cbbb0 --- /dev/null +++ b/tags/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class TagsConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'tags' diff --git a/tags/forms.py b/tags/forms.py new file mode 100644 index 0000000..ff4c66b --- /dev/null +++ b/tags/forms.py @@ -0,0 +1,9 @@ +from django import forms +from .models import Tag + +class TagForm(forms.ModelForm): + + class Meta: + model = Tag + fields = ['label', 'type'] + labels = {'label':'New Tag', 'type':'Tag Type'} diff --git a/tags/models.py b/tags/models.py new file mode 100644 index 0000000..6181aa1 --- /dev/null +++ b/tags/models.py @@ -0,0 +1,29 @@ +from django.db import models +from django.contrib.contenttypes.models import ContentType +from django.contrib.contenttypes.fields import GenericForeignKey + + +# Create your models here. + +class Tag(models.Model): + label = models.CharField(max_length=255) + type = models.CharField(max_length=255, default=None, null=True, blank=True) + + def __str__(self) -> str: + return self.label + + + +class TaggedItem(models.Model): + """ + This keeps track of the generic items that are tagged and when they were tagged. + + The time is important because when a profile is tagged + Public and then is changed to -> Private all information past that point is not going to be shared. + + """ + tag = models.ForeignKey(Tag, on_delete=models.CASCADE) + content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) + object_id = models.PositiveIntegerField() + content_object = GenericForeignKey() + tagged = models.DateTimeField(auto_now_add=True) diff --git a/tags/templates/tags/list.html b/tags/templates/tags/list.html new file mode 100644 index 0000000..eee3984 --- /dev/null +++ b/tags/templates/tags/list.html @@ -0,0 +1,10 @@ +{% block content %} +

All the tags

+ +
    + {% for tag in tags %} +
  • {{ tag.label }} - {{ tag.type }}
  • + {% endfor %} +
+ +{% endblock %} \ No newline at end of file diff --git a/tags/tests.py b/tags/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/tags/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/tags/urls.py b/tags/urls.py new file mode 100644 index 0000000..e64fb3e --- /dev/null +++ b/tags/urls.py @@ -0,0 +1,11 @@ +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.TagsListView.as_view(), name="tags.list"), + # path('tags/', views.TagsDetailView.as_view(), name="tags.detail"), + #path('tags//edit', views.TagsUpdateView.as_view(), name="tags.update"), + #path('tags//delete', views.TagsDeleteView.as_view(), name="tags.delete"), + #path('tags/new', views.TagsCreateView.as_view(), name="tags.new"), + + ] diff --git a/tags/views.py b/tags/views.py new file mode 100644 index 0000000..d1d6c20 --- /dev/null +++ b/tags/views.py @@ -0,0 +1,14 @@ +from django.shortcuts import render +from django.views.generic import ListView + +from .models import Tag +#from .forms import TagForm + +# Create your views here. +class TagsListView(ListView): + model = Tag + + def get(self, request, *args, **kwargs): + tags = Tag.objects.all() + context = {'tags':tags} + return render(request, 'tags/list.html', context) \ No newline at end of file