Django
This commit is contained in:
0
apps/dyn_dt/.gitkeep
Normal file
0
apps/dyn_dt/.gitkeep
Normal file
0
apps/dyn_dt/__init__.py
Normal file
0
apps/dyn_dt/__init__.py
Normal file
8
apps/dyn_dt/admin.py
Normal file
8
apps/dyn_dt/admin.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from django.contrib import admin
|
||||
from .models import *
|
||||
|
||||
# Register your models here.
|
||||
|
||||
admin.site.register(PageItems)
|
||||
admin.site.register(HideShowFilter)
|
||||
admin.site.register(ModelFilter)
|
||||
5
apps/dyn_dt/apps.py
Normal file
5
apps/dyn_dt/apps.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
class DynDtConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'apps.dyn_dt'
|
||||
3
apps/dyn_dt/forms.py
Normal file
3
apps/dyn_dt/forms.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django import forms
|
||||
|
||||
# Create your forms here.
|
||||
63
apps/dyn_dt/migrations/0001_initial.py
Normal file
63
apps/dyn_dt/migrations/0001_initial.py
Normal file
@@ -0,0 +1,63 @@
|
||||
# Generated by Django 4.2.9 on 2025-03-30 11:44
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = []
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="HideShowFilter",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("parent", models.CharField(blank=True, max_length=255, null=True)),
|
||||
("key", models.CharField(max_length=255)),
|
||||
("value", models.BooleanField(default=False)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="ModelFilter",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("parent", models.CharField(blank=True, max_length=255, null=True)),
|
||||
("key", models.CharField(max_length=255)),
|
||||
("value", models.CharField(max_length=255)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="PageItems",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("parent", models.CharField(blank=True, max_length=255, null=True)),
|
||||
("items_per_page", models.IntegerField(default=25)),
|
||||
],
|
||||
),
|
||||
]
|
||||
0
apps/dyn_dt/migrations/__init__.py
Normal file
0
apps/dyn_dt/migrations/__init__.py
Normal file
24
apps/dyn_dt/models.py
Normal file
24
apps/dyn_dt/models.py
Normal file
@@ -0,0 +1,24 @@
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
# Create your models here.
|
||||
|
||||
class PageItems(models.Model):
|
||||
parent = models.CharField(max_length=255, null=True, blank=True)
|
||||
items_per_page = models.IntegerField(default=25)
|
||||
|
||||
class HideShowFilter(models.Model):
|
||||
parent = models.CharField(max_length=255, null=True, blank=True)
|
||||
key = models.CharField(max_length=255)
|
||||
value = models.BooleanField(default=False)
|
||||
|
||||
def __str__(self):
|
||||
return self.key
|
||||
|
||||
class ModelFilter(models.Model):
|
||||
parent = models.CharField(max_length=255, null=True, blank=True)
|
||||
key = models.CharField(max_length=255)
|
||||
value = models.CharField(max_length=255)
|
||||
|
||||
def __str__(self):
|
||||
return self.key
|
||||
0
apps/dyn_dt/templatetags/__init__.py
Normal file
0
apps/dyn_dt/templatetags/__init__.py
Normal file
22
apps/dyn_dt/templatetags/get_attribute.py
Normal file
22
apps/dyn_dt/templatetags/get_attribute.py
Normal file
@@ -0,0 +1,22 @@
|
||||
from django import template
|
||||
from datetime import datetime
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.filter(name="getattribute")
|
||||
def getattribute(value, arg):
|
||||
try:
|
||||
attr_value = getattr(value, arg)
|
||||
|
||||
if isinstance(attr_value, datetime):
|
||||
return attr_value.strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
return attr_value
|
||||
except:
|
||||
return ''
|
||||
|
||||
|
||||
@register.filter
|
||||
def get(dict_data, key):
|
||||
return dict_data.get(key, [])
|
||||
3
apps/dyn_dt/tests.py
Normal file
3
apps/dyn_dt/tests.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
18
apps/dyn_dt/urls.py
Normal file
18
apps/dyn_dt/urls.py
Normal file
@@ -0,0 +1,18 @@
|
||||
from django.urls import path
|
||||
from apps.dyn_dt import views
|
||||
|
||||
urlpatterns = [
|
||||
path('dynamic-dt/', views.index, name="dynamic_dt"),
|
||||
|
||||
path('create-filter/<str:model_name>/', views.create_filter, name="create_filter"),
|
||||
path('create-page-items/<str:model_name>/', views.create_page_items, name="create_page_items"),
|
||||
path('create-hide-show-items/<str:model_name>/', views.create_hide_show_filter, name="create_hide_show_filter"),
|
||||
path('delete-filter/<str:model_name>/<int:id>/', views.delete_filter, name="delete_filter"),
|
||||
path('create/<str:aPath>/', views.create, name="create"),
|
||||
path('delete/<str:aPath>/<int:id>/', views.delete, name="delete"),
|
||||
path('update/<str:aPath>/<int:id>/', views.update, name="update"),
|
||||
|
||||
path('export-csv/<str:aPath>/', views.ExportCSVView.as_view(), name='export_csv'),
|
||||
|
||||
path('dynamic-dt/<str:aPath>/', views.model_dt, name="model_dt"),
|
||||
]
|
||||
13
apps/dyn_dt/utils.py
Normal file
13
apps/dyn_dt/utils.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from django.db.models import Q
|
||||
|
||||
def user_filter(request, queryset, fields, fk_fields=[]):
|
||||
value = request.GET.get('search')
|
||||
|
||||
if value:
|
||||
dynamic_q = Q()
|
||||
for field in fields:
|
||||
if field not in fk_fields:
|
||||
dynamic_q |= Q(**{f'{field}__icontains': value})
|
||||
return queryset.filter(dynamic_q)
|
||||
|
||||
return queryset
|
||||
315
apps/dyn_dt/views.py
Normal file
315
apps/dyn_dt/views.py
Normal file
@@ -0,0 +1,315 @@
|
||||
import requests, base64, json, csv
|
||||
from django.shortcuts import render, redirect, get_object_or_404
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils import timezone
|
||||
from django.http import HttpResponse, JsonResponse
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.conf import settings
|
||||
from django.urls import reverse
|
||||
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
|
||||
from django.urls import reverse
|
||||
from django.views import View
|
||||
from django.db import models
|
||||
from pprint import pp
|
||||
|
||||
from apps.dyn_dt.models import ModelFilter, PageItems, HideShowFilter
|
||||
from apps.dyn_dt.utils import user_filter
|
||||
|
||||
from cli import *
|
||||
|
||||
# Create your views here.
|
||||
|
||||
def index(request):
|
||||
|
||||
context = {
|
||||
'routes' : settings.DYNAMIC_DATATB.keys(),
|
||||
'segment': 'dynamic_dt'
|
||||
}
|
||||
|
||||
return render(request, 'dyn_dt/index.html', context)
|
||||
|
||||
def create_filter(request, model_name):
|
||||
model_name = model_name.lower()
|
||||
if request.method == "POST":
|
||||
keys = request.POST.getlist('key')
|
||||
values = request.POST.getlist('value')
|
||||
for i in range(len(keys)):
|
||||
key = keys[i]
|
||||
value = values[i]
|
||||
|
||||
ModelFilter.objects.update_or_create(
|
||||
parent=model_name,
|
||||
key=key,
|
||||
defaults={'value': value}
|
||||
)
|
||||
|
||||
return redirect(reverse('model_dt', args=[model_name]))
|
||||
|
||||
|
||||
def create_page_items(request, model_name):
|
||||
model_name = model_name.lower()
|
||||
if request.method == 'POST':
|
||||
items = request.POST.get('items')
|
||||
page_items, created = PageItems.objects.update_or_create(
|
||||
parent=model_name,
|
||||
defaults={'items_per_page':items}
|
||||
)
|
||||
return redirect(reverse('model_dt', args=[model_name]))
|
||||
|
||||
|
||||
def create_hide_show_filter(request, model_name):
|
||||
model_name = model_name.lower()
|
||||
if request.method == "POST":
|
||||
data_str = list(request.POST.keys())[0]
|
||||
data = json.loads(data_str)
|
||||
|
||||
HideShowFilter.objects.update_or_create(
|
||||
parent=model_name,
|
||||
key=data.get('key'),
|
||||
defaults={'value': data.get('value')}
|
||||
)
|
||||
|
||||
response_data = {'message': 'Model updated successfully'}
|
||||
return JsonResponse(response_data)
|
||||
|
||||
return JsonResponse({'error': 'Invalid request'}, status=400)
|
||||
|
||||
|
||||
def delete_filter(request, model_name, id):
|
||||
model_name = model_name.lower()
|
||||
filter_instance = ModelFilter.objects.get(id=id, parent=model_name)
|
||||
filter_instance.delete()
|
||||
return redirect(reverse('model_dt', args=[model_name]))
|
||||
|
||||
|
||||
def get_model_field_names(model, field_type):
|
||||
"""Returns a list of field names based on the given field type."""
|
||||
return [
|
||||
field.name for field in model._meta.get_fields()
|
||||
if isinstance(field, field_type)
|
||||
]
|
||||
|
||||
def model_dt(request, aPath):
|
||||
aModelName = None
|
||||
aModelClass = None
|
||||
choices_dict = {}
|
||||
|
||||
if aPath in settings.DYNAMIC_DATATB.keys():
|
||||
aModelName = settings.DYNAMIC_DATATB[aPath]
|
||||
aModelClass = name_to_class(aModelName)
|
||||
|
||||
if not aModelClass:
|
||||
return HttpResponse( ' > ERR: Getting ModelClass for path: ' + aPath )
|
||||
|
||||
#db_fields = [field.name for field in aModelClass._meta.get_fields() if not field.is_relation]
|
||||
db_fields = [field.name for field in aModelClass._meta.fields]
|
||||
fk_fields = get_model_fk_values(aModelClass)
|
||||
db_filters = []
|
||||
for f in db_fields:
|
||||
if f not in fk_fields.keys():
|
||||
db_filters.append( f )
|
||||
|
||||
for field in aModelClass._meta.fields:
|
||||
if field.choices:
|
||||
choices_dict[field.name] = field.choices
|
||||
|
||||
field_names = []
|
||||
for field_name in db_fields:
|
||||
fields, created = HideShowFilter.objects.get_or_create(key=field_name, parent=aPath.lower())
|
||||
if fields.key in db_fields:
|
||||
field_names.append(fields)
|
||||
|
||||
model_series = {}
|
||||
for f in db_fields:
|
||||
f_values = list ( aModelClass.objects.values_list( f, flat=True) )
|
||||
model_series[ f ] = ', '.join( str(i) for i in f_values)
|
||||
|
||||
# model filter
|
||||
filter_string = {}
|
||||
filter_instance = ModelFilter.objects.filter(parent=aPath.lower())
|
||||
for filter_data in filter_instance:
|
||||
if filter_data.key in db_fields:
|
||||
filter_string[f'{filter_data.key}__icontains'] = filter_data.value
|
||||
|
||||
order_by = request.GET.get('order_by', 'id')
|
||||
if order_by not in db_fields:
|
||||
order_by = 'id'
|
||||
|
||||
queryset = aModelClass.objects.filter(**filter_string).order_by(order_by)
|
||||
item_list = user_filter(request, queryset, db_fields, fk_fields.keys())
|
||||
|
||||
# pagination
|
||||
page_items = PageItems.objects.filter(parent=aPath.lower()).last()
|
||||
p_items = 25
|
||||
if page_items:
|
||||
p_items = page_items.items_per_page
|
||||
|
||||
page = request.GET.get('page', 1)
|
||||
paginator = Paginator(item_list, p_items)
|
||||
|
||||
try:
|
||||
items = paginator.page(page)
|
||||
except PageNotAnInteger:
|
||||
return redirect(reverse('model_dt', args=[aPath]))
|
||||
except EmptyPage:
|
||||
return redirect(reverse('model_dt', args=[aPath]))
|
||||
|
||||
read_only_fields = ('id', )
|
||||
|
||||
integer_fields = get_model_field_names(aModelClass, models.IntegerField)
|
||||
date_time_fields = get_model_field_names(aModelClass, models.DateTimeField)
|
||||
email_fields = get_model_field_names(aModelClass, models.EmailField)
|
||||
text_fields = get_model_field_names(aModelClass, (models.TextField, models.CharField))
|
||||
|
||||
context = {
|
||||
'page_title': 'Dynamic DataTable - ' + aPath.lower().title(),
|
||||
'link': aPath,
|
||||
'field_names': field_names,
|
||||
'db_field_names': db_fields,
|
||||
'db_filters': db_filters,
|
||||
'items': items,
|
||||
'page_items': p_items,
|
||||
'filter_instance': filter_instance,
|
||||
'read_only_fields': read_only_fields,
|
||||
|
||||
'integer_fields': integer_fields,
|
||||
'date_time_fields': date_time_fields,
|
||||
'email_fields': email_fields,
|
||||
'text_fields': text_fields,
|
||||
'fk_fields_keys': list( fk_fields.keys() ),
|
||||
'fk_fields': fk_fields ,
|
||||
'choices_dict': choices_dict,
|
||||
'segment': 'dynamic_dt'
|
||||
}
|
||||
return render(request, 'dyn_dt/model.html', context)
|
||||
|
||||
|
||||
@login_required(login_url='/accounts/login/')
|
||||
def create(request, aPath):
|
||||
aModelClass = None
|
||||
|
||||
if aPath in settings.DYNAMIC_DATATB.keys():
|
||||
aModelName = settings.DYNAMIC_DATATB[aPath]
|
||||
aModelClass = name_to_class(aModelName)
|
||||
|
||||
if not aModelClass:
|
||||
return HttpResponse( ' > ERR: Getting ModelClass for path: ' + aPath )
|
||||
|
||||
if request.method == 'POST':
|
||||
data = {}
|
||||
fk_fields = get_model_fk(aModelClass)
|
||||
|
||||
for attribute, value in request.POST.items():
|
||||
if attribute == 'csrfmiddlewaretoken':
|
||||
continue
|
||||
|
||||
# Process FKs
|
||||
if attribute in fk_fields.keys():
|
||||
value = name_to_class( fk_fields[attribute] ).objects.filter(id=value).first()
|
||||
|
||||
data[attribute] = value if value else ''
|
||||
|
||||
aModelClass.objects.create(**data)
|
||||
|
||||
return redirect(request.META.get('HTTP_REFERER'))
|
||||
|
||||
|
||||
@login_required(login_url='/accounts/login/')
|
||||
def delete(request, aPath, id):
|
||||
aModelClass = None
|
||||
|
||||
if aPath in settings.DYNAMIC_DATATB.keys():
|
||||
aModelName = settings.DYNAMIC_DATATB[aPath]
|
||||
aModelClass = name_to_class(aModelName)
|
||||
|
||||
if not aModelClass:
|
||||
return HttpResponse( ' > ERR: Getting ModelClass for path: ' + aPath )
|
||||
|
||||
item = aModelClass.objects.get(id=id)
|
||||
item.delete()
|
||||
return redirect(request.META.get('HTTP_REFERER'))
|
||||
|
||||
|
||||
@login_required(login_url='/accounts/login/')
|
||||
def update(request, aPath, id):
|
||||
aModelClass = None
|
||||
|
||||
if aPath in settings.DYNAMIC_DATATB.keys():
|
||||
aModelName = settings.DYNAMIC_DATATB[aPath]
|
||||
aModelClass = name_to_class(aModelName)
|
||||
|
||||
if not aModelClass:
|
||||
return HttpResponse( ' > ERR: Getting ModelClass for path: ' + aPath )
|
||||
|
||||
item = aModelClass.objects.get(id=id)
|
||||
fk_fields = get_model_fk(aModelClass)
|
||||
|
||||
if request.method == 'POST':
|
||||
for attribute, value in request.POST.items():
|
||||
|
||||
if attribute == 'csrfmiddlewaretoken':
|
||||
continue
|
||||
|
||||
if getattr(item, attribute, value) is not None:
|
||||
|
||||
# Process FKs
|
||||
if attribute in fk_fields.keys():
|
||||
value = name_to_class( fk_fields[attribute] ).objects.filter(id=value).first()
|
||||
|
||||
setattr(item, attribute, value)
|
||||
|
||||
item.save()
|
||||
|
||||
return redirect(request.META.get('HTTP_REFERER'))
|
||||
|
||||
|
||||
|
||||
# Export as CSV
|
||||
class ExportCSVView(View):
|
||||
def get(self, request, aPath):
|
||||
aModelName = None
|
||||
aModelClass = None
|
||||
|
||||
if aPath in settings.DYNAMIC_DATATB.keys():
|
||||
aModelName = settings.DYNAMIC_DATATB[aPath]
|
||||
aModelClass = name_to_class(aModelName)
|
||||
|
||||
if not aModelClass:
|
||||
return HttpResponse( ' > ERR: Getting ModelClass for path: ' + aPath )
|
||||
|
||||
db_field_names = [field.name for field in aModelClass._meta.get_fields()]
|
||||
fields = []
|
||||
show_fields = HideShowFilter.objects.filter(value=False, parent=aPath.lower())
|
||||
|
||||
for field in show_fields:
|
||||
if field.key in db_field_names:
|
||||
fields.append(field.key)
|
||||
else:
|
||||
print(f"Field {field.key} does not exist in {aModelClass} model.")
|
||||
|
||||
response = HttpResponse(content_type='text/csv')
|
||||
response['Content-Disposition'] = f'attachment; filename="{aPath.lower()}.csv"'
|
||||
|
||||
writer = csv.writer(response)
|
||||
writer.writerow(fields) # Write the header
|
||||
|
||||
filter_string = {}
|
||||
filter_instance = ModelFilter.objects.filter(parent=aPath.lower())
|
||||
for filter_data in filter_instance:
|
||||
filter_string[f'{filter_data.key}__icontains'] = filter_data.value
|
||||
|
||||
order_by = request.GET.get('order_by', 'id')
|
||||
queryset = aModelClass.objects.filter(**filter_string).order_by(order_by)
|
||||
|
||||
items = user_filter(request, queryset, db_field_names)
|
||||
|
||||
for item in items:
|
||||
row_data = []
|
||||
for field in fields:
|
||||
try:
|
||||
row_data.append(getattr(item, field))
|
||||
except AttributeError:
|
||||
row_data.append('')
|
||||
writer.writerow(row_data)
|
||||
|
||||
return response
|
||||
Reference in New Issue
Block a user