Added all the functionality of app and admin

This commit is contained in:
bobbyvish
2024-03-11 14:48:48 +05:30
parent 69dbc56374
commit fd4aef5a40
92 changed files with 8931 additions and 716 deletions

View File

@@ -0,0 +1,46 @@
[
{
"model": "module_iam.iamappaction",
"pk": 1,
"fields": {
"name": "create",
"label": "create",
"slug": "create",
"created_on": "2024-03-10T01:39:43.656133",
"modified_on": "2024-03-10T01:39:43.656133"
}
},
{
"model": "module_iam.iamappaction",
"pk": 2,
"fields": {
"name": "read",
"label": "read",
"slug": "read",
"created_on": "2024-03-10T01:39:43.656133",
"modified_on": "2024-03-10T01:39:43.656133"
}
},
{
"model": "module_iam.iamappaction",
"pk": 3,
"fields": {
"name": "update",
"label": "update",
"slug": "update",
"created_on": "2024-03-10T01:39:43.656133",
"modified_on": "2024-03-10T01:39:43.656133"
}
},
{
"model": "module_iam.iamappaction",
"pk": 4,
"fields": {
"name": "delete",
"label": "delete",
"slug": "delete",
"created_on": "2024-03-10T01:39:43.656133",
"modified_on": "2024-03-10T01:39:43.656133"
}
}
]

View File

@@ -0,0 +1,46 @@
[
{
"model": "module_iam.iamprincipalsource",
"pk": 1,
"fields": {
"name": "app",
"label": "app",
"slug": "app",
"created_on": "2024-03-10T01:39:43.648496",
"modified_on": "2024-03-10T01:39:43.648496"
}
},
{
"model": "module_iam.iamprincipalsource",
"pk": 2,
"fields": {
"name": "web",
"label": "web",
"slug": "web",
"created_on": "2024-03-10T01:39:43.648496",
"modified_on": "2024-03-10T01:39:43.648496"
}
},
{
"model": "module_iam.iamprincipalsource",
"pk": 3,
"fields": {
"name": "google",
"label": "google",
"slug": "google",
"created_on": "2024-03-10T01:39:43.648496",
"modified_on": "2024-03-10T01:39:43.648496"
}
},
{
"model": "module_iam.iamprincipalsource",
"pk": 4,
"fields": {
"name": "apple",
"label": "apple",
"slug": "apple",
"created_on": "2024-03-10T01:39:43.648496",
"modified_on": "2024-03-10T01:39:43.648496"
}
}
]

View File

@@ -0,0 +1,35 @@
[
{
"model": "module_iam.iamprincipaltype",
"pk": 1,
"fields": {
"name": "admin",
"label": "admin",
"slug": "admin",
"created_on": "2024-03-10T01:39:43.648496",
"modified_on": "2024-03-10T01:39:43.648496"
}
},
{
"model": "module_iam.iamprincipaltype",
"pk": 2,
"fields": {
"name": "subadmin",
"label": "subadmin",
"slug": "subadmin",
"created_on": "2024-03-10T01:39:43.648496",
"modified_on": "2024-03-10T01:39:43.648496"
}
},
{
"model": "module_iam.iamprincipaltype",
"pk": 3,
"fields": {
"name": "user",
"label": "user",
"slug": "user",
"created_on": "2024-03-10T01:39:43.648496",
"modified_on": "2024-03-10T01:39:43.648496"
}
}
]

View File

@@ -0,0 +1,172 @@
[
{
"model": "module_iam.iamappresource",
"pk": 1,
"fields": {
"name": "manage_dashboard",
"label": "manage_dashboard",
"slug": "manage_dashboard",
"created_on": "2024-03-10T01:39:43.657388",
"modified_on": "2024-03-10T01:39:43.657388",
"action": [
1,
2,
3,
4
]
}
},
{
"model": "module_iam.iamappresource",
"pk": 2,
"fields": {
"name": "manage_iam",
"label": "manage_iam",
"slug": "manage_iam",
"created_on": "2024-03-10T01:39:43.657388",
"modified_on": "2024-03-10T01:39:43.657388",
"action": [
1,
2,
3,
4
]
}
},
{
"model": "module_iam.iamappresource",
"pk": 3,
"fields": {
"name": "manage_user",
"label": "manage_user",
"slug": "manage_user",
"created_on": "2024-03-10T01:39:43.657388",
"modified_on": "2024-03-10T01:39:43.657388",
"action": [
1,
2,
3,
4
]
}
},
{
"model": "module_iam.iamappresource",
"pk": 4,
"fields": {
"name": "manage_support",
"label": "manage_support",
"slug": "manage_support",
"created_on": "2024-03-10T01:39:43.657388",
"modified_on": "2024-03-10T01:39:43.657388",
"action": [
1,
2,
3,
4
]
}
},
{
"model": "module_iam.iamappresource",
"pk": 5,
"fields": {
"name": "manage_contact_us",
"label": "manage_contact_us",
"slug": "manage_contact_us",
"created_on": "2024-03-10T01:39:43.657388",
"modified_on": "2024-03-10T01:39:43.657388",
"action": [
1,
2,
3,
4
]
}
},
{
"model": "module_iam.iamappresource",
"pk": 6,
"fields": {
"name": "manage_feedback",
"label": "manage_feedback",
"slug": "manage_feedback",
"created_on": "2024-03-10T01:39:43.657388",
"modified_on": "2024-03-10T01:39:43.657388",
"action": [
1,
2,
3,
4
]
}
},
{
"model": "module_iam.iamappresource",
"pk": 7,
"fields": {
"name": "manage_cms",
"label": "manage_cms",
"slug": "manage_cms",
"created_on": "2024-03-10T01:39:43.657388",
"modified_on": "2024-03-10T01:39:43.657388",
"action": [
1,
2,
3,
4
]
}
},
{
"model": "module_iam.iamappresource",
"pk": 8,
"fields": {
"name": "manage_faqs",
"label": "manage_faqs",
"slug": "manage_faqs",
"created_on": "2024-03-10T01:39:43.657388",
"modified_on": "2024-03-10T01:39:43.657388",
"action": [
1,
2,
3,
4
]
}
},
{
"model": "module_iam.iamappresource",
"pk": 9,
"fields": {
"name": "manage_tc",
"label": "manage_tc",
"slug": "manage_tc",
"created_on": "2024-03-10T01:39:43.657388",
"modified_on": "2024-03-10T01:39:43.657388",
"action": [
1,
2,
3,
4
]
}
},
{
"model": "module_iam.iamappresource",
"pk": 10,
"fields": {
"name": "manage_privacypolicy",
"label": "manage_privacypolicy",
"slug": "manage_privacypolicy",
"created_on": "2024-03-10T01:39:43.657388",
"modified_on": "2024-03-10T01:39:43.657388",
"action": [
1,
2,
3,
4
]
}
}
]

325
module_iam/forms.py Normal file
View File

@@ -0,0 +1,325 @@
from typing import Any
from django import forms
from django.core.exceptions import ValidationError
from django.core import validators
from django.utils.translation import gettext_lazy as _
from module_project import constants
from . import models
# from .backend import EmailBackend
# from phonenumber_field.formfields import PhoneNumberField
from .iam_constant import PRINCIPAL_TYPE_ADMIN, PRINCIPAL_TYPE_SUBADMIN
from django.contrib.auth import authenticate
class CustomAuthenticationForm(forms.Form):
email = forms.EmailField(
max_length=254,
widget=forms.TextInput(attrs={"autofocus": True}),
label=_("Email"),
)
password = forms.CharField(
label=_("Password"),
strip=False,
widget=forms.PasswordInput(attrs={"autocomplete": "current-password"}),
)
def clean(self):
email = self.cleaned_data.get("email")
password = self.cleaned_data.get("password")
self.user = None
if email and password:
user = authenticate(email=email, password=password)
if user is None:
raise ValidationError({"__all__": [constants.INVALID_EMAIL_PASSWORD]})
elif not user.is_active:
raise ValidationError({"__all__": [constants.ACCOUNT_DEACTIVATED]})
self.user = user
return self.cleaned_data
class IAmPrincipalForm(forms.ModelForm):
password = forms.CharField(
widget=forms.PasswordInput(attrs={"autocomplete": "off"}),
validators=[
validators.MinLengthValidator(
limit_value=6, message="Password must be at least 6 characters long. "
)
],
)
confirm_password = forms.CharField(
widget=forms.PasswordInput(attrs={"autocomplete": "off"})
)
is_active = forms.BooleanField(
label="Active",
initial=True,
help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.",
required=False,
)
class Meta:
model = models.IAmPrincipal
fields = [
"principal_type",
"first_name",
"last_name",
"email",
"password",
"confirm_password",
"is_active",
]
def __init__(self, *args, **kwargs):
instance = kwargs.get("instance")
super().__init__(*args, **kwargs)
self.fields["principal_type"].queryset = models.IAmPrincipalType.objects.filter(
active=True, deleted=False
)
# If it's a create action, exclude 'is_active' field
if instance is None:
self.fields.pop("is_active", None)
else:
# Exclude 'password' and 'confirm_password' fields for updates
self.fields.pop("password", None)
self.fields.pop("confirm_password", None)
# Make the 'email' field read-only
self.fields["email"].widget.attrs["readonly"] = True
def clean_email(self):
email = self.cleaned_data.get("email")
# Skip uniqueness validation if it's an update action (instance exists)
if self.instance and self.instance.email == email:
return email
if models.IAmPrincipal.objects.filter(email=email).exists():
raise forms.ValidationError(constants.EMAIL_EXISTS)
return email
def save(self, commit=True):
instance = super().save(commit=False)
# Check if it's a new object (create action) or an existing one (update action)
if not instance.pk: # pk is None for new objects
instance.username = self.cleaned_data["email"]
instance.set_password(self.cleaned_data["password"])
principal_type = self.cleaned_data.get("principal_type")
if principal_type is not None:
# Set is_superuser and is_staff based on principal_type
if principal_type == models.IAmPrincipalType.objects.get(name=PRINCIPAL_TYPE_ADMIN):
instance.is_superuser = True
elif principal_type == models.IAmPrincipalType.objects.get(name=PRINCIPAL_TYPE_SUBADMIN):
instance.is_staff = True
if commit:
instance.save()
return instance
class IAmPrincipalProfileForm(forms.ModelForm):
GENDER_CHOICES = (
("male", "Male"),
("female", "Female"),
("other", "Other"),
)
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
email = forms.EmailField(required=True)
password = forms.CharField(
widget=forms.PasswordInput(attrs={"autocomplete": "off"})
)
confirm_password = forms.CharField(
widget=forms.PasswordInput(attrs={"autocomplete": "off"})
)
# date_of_birth = forms.CharField(widget=forms.DateInput(attrs={'type': 'date'}))
phone_number = forms.CharField(
widget=forms.TextInput(),
)
# is_staff = forms.BooleanField(
# label="Staff Status",
# label_suffix="",
# initial=True,
# required=False,
# help_text="Check this box to designate that this user will be assigned permissions in the future.",
# )
# is_superuser = forms.BooleanField(
# label="SuperAdmin Status",
# label_suffix="",
# required=False,
# help_text="Check this box to designates that this user has all permissions without explicitly assigning them.",
# )
# gender = forms.ChoiceField(choices=GENDER_CHOICES)
class Meta:
model = models.IAmPrincipal
fields = [
"principal_type",
"first_name",
"last_name",
"email",
"password",
"confirm_password",
# 'gender',
# 'date_of_birth',
"phone_number",
# 'address_line1',
# 'address_line2',
# 'city',
# 'state',
# 'country',
# 'post_code',
# 'profile_photo',
# "is_staff",
# "is_superuser",
]
def __init__(self, *args, **kwargs):
instance = kwargs.get("instance")
super().__init__(*args, **kwargs)
self.fields["principal_type"].queryset = models.IAmPrincipalType.objects.filter(
active=True, deleted=False
)
# self.fields['principal_source'].queryset = models.IAmPrincipalSource.objects.filter(active=True, deleted=False)
# Check if an instance is provided and customize the form fields accordingly
if instance is not None:
# Exclude the 'password' and 'confirm_password' fields
self.fields.pop("password", None)
self.fields.pop("confirm_password", None)
# Make the 'email' field read-only
self.fields["email"].widget.attrs["readonly"] = True
# Modify the 'is_superuser' field to be not required
# self.fields["is_superuser"].required = False
# self.fields["is_staff"].required = False
# Add or modify the 'is_active' field
self.fields["is_active"] = forms.BooleanField(
label="Active",
initial=instance.is_active,
help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.",
required=False,
)
def clean(self):
cleaned_data = super().clean()
password = cleaned_data.get("password")
confirm_password = cleaned_data.get("confirm_password")
if password and confirm_password and password != confirm_password:
self.add_error("confirm_password", "Password does not match")
return cleaned_data
def save(self, commit=True):
user = super().save(commit=False)
user.set_password(self.cleaned_data["password"])
if commit:
user.save()
return user
class ProfileEditForm(forms.ModelForm):
gender = forms.ChoiceField(choices=(('Male', 'Male'),('Female', 'Female'),('Other', 'Other')))
profile_photo = forms.ImageField(required=False)
class Meta:
model = models.IAmPrincipal
fields = [
"profile_photo",
"first_name",
"last_name",
"date_of_birth",
"gender",
"phone_no"
]
class IAmPrincipalGroupLinkForm(forms.ModelForm):
class Meta:
model = models.IAmPrincipal
fields = [
# "principal_type",
"email",
"principal_group",
]
# principal_type = forms.ModelChoiceField(
# label="Principal Type",
# queryset=models.IAmPrincipalType.objects.filter(active=True, deleted=False),
# widget=forms.widgets.TextInput(attrs={"readonly": True}),
# )
principal_group = forms.ModelMultipleChoiceField(
label="Groups",
queryset=models.IAmPrincipalGroup.objects.filter(active=True, deleted=False),
required=False,
widget=forms.widgets.SelectMultiple(
attrs={"class": "form_select js-example-basic-multiple"}
),
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Make the 'email' field read-only
# self.fields['principal_type'].widget.attrs['disabled'] = True
self.fields['email'].widget.attrs['readonly'] = True
class IAmPrincipalTypeForm(forms.ModelForm):
class Meta:
model = models.IAmPrincipalType
fields = ["name", "active"]
def __init__(self, *args, **kwargs):
instance = kwargs.get("instance")
super().__init__(*args, **kwargs)
if instance is None:
self.fields.pop("active")
class IAmPrincipalGroupRoleLinkForm(forms.ModelForm):
class Meta:
model = models.IAmPrincipalGroup
fields = ["name", "role", "active"]
role = forms.ModelMultipleChoiceField(
queryset=models.IAmRole.objects.filter(active=True, deleted=False),
required=False,
widget=forms.widgets.SelectMultiple(
attrs={"class": "form-select js-example-basic-multiple"}
),
)
def __init__(self, *args, **kwargs):
instance = kwargs.get("instance")
# data = kwargs.get('data')
super().__init__(*args, **kwargs)
if instance is None:
# This is an add operation, exclude the 'active' field
self.fields.pop("active")
class IAmPrincipalRoleAppResourceActionLinkForm(forms.ModelForm):
class Meta:
model = models.IAmRole
fields = ["name", "active", "app_resource_action"]
required = {"app_resource_action": False}
app_resource_action = forms.ModelMultipleChoiceField(
queryset=models.IAmAppResourceActionLink.objects.all(),
widget=forms.CheckboxSelectMultiple,
required=False,
)
def __init__(self, *args, **kwargs):
instance = kwargs.get("instance")
super().__init__(*args, **kwargs)
if instance is None:
self.fields.pop("active")

View File

@@ -1,25 +1,34 @@
# principal type constant
PRINCIPAL_TYPE_USER = "user"
PRINCIPAL_TYPE_ADMIN = "admin"
PRINCIPAL_TYPE_SUBADMIN = "subadmin"
# principal source constant
PRINCIPAL_SOURCE_APP = "app"
PRINCIPAL_SOURCE_WEB = "web"
PRINCIPAL_SOURCE_GOOGLE = "google"
PRINCIPAL_SOURCE_APPLE = "apple"
# app action constant
ACTION_CREATE = "create"
ACTION_READ = "read"
ACTION_UPDATE = "update"
ACTION_DELETE = "delete"
RESOURCE_MANAGE_DASHBOARD = "manage_dashboard"
RESOURCE_MANAGE_IAM = "manage_iam"
RESOURCE_MANAGE_CUSTOMER = "manage_customer"
RESOURCE_MANAGE_WALLET = "manage_wallet"
RESOURCE_MANAGE_PAYMENT = "manage_payment"
RESOURCE_MANAGE_GAMES = "manage_games"
RESOURCE_MANAGE_USER = "manage_user"
RESOURCE_MANAGE_SUPPORT = "manage_support"
RESOURCE_MANAGE_CONTACT_US = "manage_contact_us"
RESOURCE_MANAGE_TICKET = "manage_ticket"
RESOURCE_MANAGE_CMS = "manage_cms"
RESOURCE_MANAGE_REPORTS = "manage_reports"
RESOURCE_MANAGE_COUPON = "manage_coupon"
RESOURCE_MANAGE_FEEDBACK = "manage_feedback"
RESOURCE_MANAGE_STOCK = "manage_stock"
RESOURCE_MANAGE_NOTIFICATION = "manage_notification"
RESOURCE_MANAGE_CMS = "manage_cms"
RESOURCE_MANAGE_FAQS = "manage_faqs"
RESOURCE_MANAGE_T_C = "manage_tc"
RESOURCE_MANAGE_PRIVACYPOLICY = "manage_privacypolicy"
# These constants are used solely for managing the active and inactive state of pages

View File

@@ -0,0 +1,60 @@
from .iam_constant import (
PRINCIPAL_TYPE_USER,
PRINCIPAL_TYPE_ADMIN,
PRINCIPAL_TYPE_SUBADMIN,
PRINCIPAL_SOURCE_APP,
PRINCIPAL_SOURCE_WEB,
PRINCIPAL_SOURCE_GOOGLE,
PRINCIPAL_SOURCE_APPLE,
ACTION_CREATE,
ACTION_READ,
ACTION_UPDATE,
ACTION_DELETE,
RESOURCE_MANAGE_DASHBOARD,
RESOURCE_MANAGE_IAM,
RESOURCE_MANAGE_USER,
RESOURCE_MANAGE_SUPPORT,
RESOURCE_MANAGE_CONTACT_US,
RESOURCE_MANAGE_FEEDBACK,
RESOURCE_MANAGE_NOTIFICATION,
RESOURCE_MANAGE_CMS,
RESOURCE_MANAGE_FAQS,
RESOURCE_MANAGE_T_C,
RESOURCE_MANAGE_PRIVACYPOLICY,
RESOURCE_IAM_PRINCIPAL,
RESOURCE_IAM_PRINCIPAL_GROUP,
RESOURCE_IAM_GROUP,
RESOURCE_IAM_ROLE,
)
def iam_constants_context(request):
return {
'iam_constants_context': {
'PRINCIPAL_TYPE_USER': PRINCIPAL_TYPE_USER,
'PRINCIPAL_TYPE_ADMIN': PRINCIPAL_TYPE_ADMIN,
'PRINCIPAL_TYPE_SUBADMIN': PRINCIPAL_TYPE_SUBADMIN,
'PRINCIPAL_SOURCE_APP': PRINCIPAL_SOURCE_APP,
'PRINCIPAL_SOURCE_WEB': PRINCIPAL_SOURCE_WEB,
'PRINCIPAL_SOURCE_GOOGLE': PRINCIPAL_SOURCE_GOOGLE,
'PRINCIPAL_SOURCE_APPLE': PRINCIPAL_SOURCE_APPLE,
'ACTION_CREATE': ACTION_CREATE,
'ACTION_READ': ACTION_READ,
'ACTION_UPDATE': ACTION_UPDATE,
'ACTION_DELETE': ACTION_DELETE,
'RESOURCE_MANAGE_DASHBOARD': RESOURCE_MANAGE_DASHBOARD,
'RESOURCE_MANAGE_IAM': RESOURCE_MANAGE_IAM,
'RESOURCE_MANAGE_USER': RESOURCE_MANAGE_USER,
'RESOURCE_MANAGE_SUPPORT': RESOURCE_MANAGE_SUPPORT,
'RESOURCE_MANAGE_CONTACT_US': RESOURCE_MANAGE_CONTACT_US,
'RESOURCE_MANAGE_FEEDBACK': RESOURCE_MANAGE_FEEDBACK,
'RESOURCE_MANAGE_NOTIFICATION': RESOURCE_MANAGE_NOTIFICATION,
'RESOURCE_MANAGE_CMS': RESOURCE_MANAGE_CMS,
'RESOURCE_MANAGE_FAQS': RESOURCE_MANAGE_FAQS,
'RESOURCE_MANAGE_T_C': RESOURCE_MANAGE_T_C,
'RESOURCE_MANAGE_PRIVACYPOLICY': RESOURCE_MANAGE_PRIVACYPOLICY,
'RESOURCE_IAM_PRINCIPAL': RESOURCE_IAM_PRINCIPAL,
'RESOURCE_IAM_PRINCIPAL_GROUP': RESOURCE_IAM_PRINCIPAL_GROUP,
'RESOURCE_IAM_GROUP': RESOURCE_IAM_GROUP,
'RESOURCE_IAM_ROLE': RESOURCE_IAM_ROLE,
}
}

View File

@@ -0,0 +1,169 @@
from datetime import datetime
from .iam_constant import (
PRINCIPAL_TYPE_USER,
PRINCIPAL_TYPE_ADMIN,
PRINCIPAL_TYPE_SUBADMIN,
PRINCIPAL_SOURCE_APP,
PRINCIPAL_SOURCE_WEB,
PRINCIPAL_SOURCE_GOOGLE,
PRINCIPAL_SOURCE_APPLE,
ACTION_CREATE,
ACTION_READ,
ACTION_UPDATE,
ACTION_DELETE,
RESOURCE_MANAGE_DASHBOARD,
RESOURCE_MANAGE_IAM,
RESOURCE_MANAGE_USER,
RESOURCE_MANAGE_CONTACT_US,
RESOURCE_MANAGE_FEEDBACK,
RESOURCE_MANAGE_FAQS,
RESOURCE_MANAGE_T_C,
RESOURCE_MANAGE_CMS,
RESOURCE_MANAGE_PRIVACYPOLICY,
RESOURCE_MANAGE_SUPPORT
)
class IAMPrincipalType:
ADMIN = PRINCIPAL_TYPE_ADMIN
SUBADMIN = PRINCIPAL_TYPE_SUBADMIN
USER = PRINCIPAL_TYPE_USER
categories = [
ADMIN,
SUBADMIN,
USER,
]
@staticmethod
def create_iam_principal_type_fixture_data():
iam_category_fixture_data = []
created_on = datetime.now().isoformat()
modified_on = datetime.now().isoformat()
for idx, category in enumerate(IAMPrincipalType.categories, start=1):
iam_category_fixture_data.append(
{
"model": "module_iam.iamprincipaltype",
"pk": idx,
"fields": {
"name": category,
"label": category,
"slug": category,
"created_on": created_on,
"modified_on": modified_on,
},
}
)
return iam_category_fixture_data
class IAMPrincipalSource:
source = [
PRINCIPAL_SOURCE_APP,
PRINCIPAL_SOURCE_WEB,
PRINCIPAL_SOURCE_GOOGLE,
PRINCIPAL_SOURCE_APPLE
]
@staticmethod
def create_iam_principal_source_fixture_data():
iam_principal_source_fixture_data = []
created_on = datetime.now().isoformat()
modified_on = datetime.now().isoformat()
for idx, principal_source in enumerate(IAMPrincipalSource.source, start=1,):
iam_principal_source_fixture_data.append(
{
"model": "module_iam.iamprincipalsource",
"pk": idx,
"fields": {
"name": principal_source,
"label": principal_source,
"slug": principal_source,
"created_on": created_on,
"modified_on": modified_on,
},
}
)
return iam_principal_source_fixture_data
class IAMActions:
CREATE = ACTION_CREATE
READ = ACTION_READ
UPDATE = ACTION_UPDATE
DELETE = ACTION_DELETE
actions = [
CREATE,
READ,
UPDATE,
DELETE,
]
@staticmethod
def create_iam_action_fixture_data():
iam_action_fixture_data = []
created_on = datetime.now().isoformat()
modified_on = datetime.now().isoformat()
for idx, action in enumerate(IAMActions.actions, start=1):
iam_action_fixture_data.append(
{
"model": "module_iam.iamappaction",
"pk": idx,
"fields": {
"name": action,
"label": action,
"slug": action,
"created_on": created_on,
"modified_on": modified_on,
},
}
)
return iam_action_fixture_data
class IAMResources:
DASHBOARD = RESOURCE_MANAGE_DASHBOARD
IAM = RESOURCE_MANAGE_IAM
USER = RESOURCE_MANAGE_USER
SUPPORT = RESOURCE_MANAGE_SUPPORT
CONTACT_US = RESOURCE_MANAGE_CONTACT_US
FEEDBACK = RESOURCE_MANAGE_FEEDBACK
CMS = RESOURCE_MANAGE_CMS
FAQS = RESOURCE_MANAGE_FAQS
T_C = RESOURCE_MANAGE_T_C
PRIVACYPOLICY = RESOURCE_MANAGE_PRIVACYPOLICY
resources = [
DASHBOARD,
IAM,
USER,
SUPPORT,
CONTACT_US,
FEEDBACK,
CMS,
FAQS,
T_C,
PRIVACYPOLICY,
]
@staticmethod
def create_iam_resource_fixture_data():
iam_resource_fixture_data = []
created_on = datetime.now().isoformat()
modified_on = datetime.now().isoformat()
for idx, resource in enumerate(IAMResources.resources, start=1):
iam_resource_fixture_data.append(
{
"model": "module_iam.iamappresource",
"pk": idx,
"fields": {
"name": resource,
"label": resource,
"slug": resource,
"created_on": created_on,
"modified_on": modified_on,
"action": [1, 2, 3, 4],
},
}
)
return iam_resource_fixture_data

View File

@@ -0,0 +1,122 @@
import os
import json
import subprocess
from datetime import datetime
from tqdm import tqdm
from django.core.management.base import BaseCommand
from module_iam.iam_fixture_script import IAMPrincipalType, IAMActions, IAMResources, IAMPrincipalSource
class Command(BaseCommand):
help = "Load IAM fixtures data"
def handle(self, *args, **options):
app_name = "module_iam"
try:
self.stdout.write(self.style.SUCCESS("IAM fixtures data loading started..."))
# Ensure the fixture directory exists
fixture_directory = os.path.join(app_name, "fixtures")
if not os.path.exists(fixture_directory):
os.makedirs(fixture_directory)
# Generate IAM category fixture data
principal_type_fixture_data = IAMPrincipalType.create_iam_principal_type_fixture_data()
# Specify the app name and fixture filename for category fixtures
categories_fixture_filename = os.path.join(fixture_directory, "iam_principal_type_fixture.json")
principal_type_fixture_data_list = []
with tqdm(total=len(principal_type_fixture_data), desc="Loading IAM principal type fixture") as pbar:
for item in principal_type_fixture_data:
principal_type_fixture_data_list.append(item)
pbar.update(1)
# Dump category fixture data as JSON
with open(categories_fixture_filename, "w") as fixture_file:
json.dump(principal_type_fixture_data, fixture_file, indent=4)
self.stdout.write(
self.style.SUCCESS(f"IAM category fixture data has been loaded successfully. Fixture file location: {categories_fixture_filename}")
)
principal_source_fixture_data = IAMPrincipalSource.create_iam_principal_source_fixture_data()
# Specify the app name and fixture filename for source fixtures
source_fixture_filename = os.path.join(fixture_directory, "iam_principal_source_fixture.json")
principal_source_fixture_data_list = []
with tqdm(total=len(principal_source_fixture_data), desc="Loading IAM principal source fixture") as pbar:
for item in principal_source_fixture_data:
principal_source_fixture_data_list.append(item)
pbar.update(1)
# Dump category fixture data as JSON
with open(source_fixture_filename, "w") as fixture_file:
json.dump(principal_source_fixture_data, fixture_file, indent=4)
self.stdout.write(
self.style.SUCCESS(f"IAM category fixture data has been loaded successfully. Fixture file location: {categories_fixture_filename}")
)
# Generate IAM action fixture data
action_fixture_data = IAMActions.create_iam_action_fixture_data()
# Specify the fixture filename for action fixtures
action_fixture_filename = os.path.join(fixture_directory, "iam_actions_fixture.json")
action_fixture_data_list = []
with tqdm(total=len(action_fixture_data), desc="Loading IAM action fixture") as pbar:
for item in action_fixture_data:
action_fixture_data_list.append(item)
pbar.update(1)
# Dump action fixture data as JSON
with open(action_fixture_filename, "w") as fixture_file:
json.dump(action_fixture_data, fixture_file, indent=4)
self.stdout.write(
self.style.SUCCESS(f"IAM action fixture data has been loaded successfully. Fixture file location: {action_fixture_filename}")
)
# Generate IAM resource fixture data
resource_fixture_data = IAMResources.create_iam_resource_fixture_data()
# Specify the fixture filename for resource fixtures
resource_fixture_filename = os.path.join(fixture_directory, "iam_resources_fixture.json")
resource_fixture_data_list = []
with tqdm(total=len(resource_fixture_data), desc="Loading IAM resource fixture") as pbar:
for item in resource_fixture_data:
resource_fixture_data_list.append(item)
pbar.update(1)
# Dump resource fixture data as JSON
with open(resource_fixture_filename, "w") as fixture_file:
json.dump(resource_fixture_data, fixture_file, indent=4)
self.stdout.write(
self.style.SUCCESS(f"IAM resource fixture data has been loaded successfully. Fixture file location: {resource_fixture_filename}")
)
# Run the loaddata command to load the created fixtures
loaddata_command_categories = f"python manage.py loaddata {categories_fixture_filename}"
subprocess.run(loaddata_command_categories, shell=True)
loaddata_command_categories = f"python manage.py loaddata {source_fixture_filename}"
subprocess.run(loaddata_command_categories, shell=True)
loaddata_command_actions = f"python manage.py loaddata {action_fixture_filename}"
subprocess.run(loaddata_command_actions, shell=True)
loaddata_command_resources = f"python manage.py loaddata {resource_fixture_filename}"
subprocess.run(loaddata_command_resources, shell=True)
self.stdout.write(
self.style.SUCCESS("IAM fixtures data loading completed successfully.")
)
except Exception as e:
# Handle exceptions here
self.stderr.write(
self.style.ERROR(f"IAM fixtures data loading failed: {str(e)}")
)

View File

@@ -0,0 +1,22 @@
# Generated by Django 5.0.2 on 2024-03-11 07:22
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('module_iam', '0003_alter_iamprincipal_gender'),
]
operations = [
migrations.CreateModel(
name='AppVersion',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('version', models.CharField(max_length=10)),
('force_upgrade', models.BooleanField(default=False, help_text='Indicates whether a force upgrade is needed for this app version.')),
('recommend_upgrade', models.BooleanField(default=False, help_text='Indicates whether a recommend upgrade is needed for this app version.')),
],
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 5.0.2 on 2024-03-11 07:23
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('module_iam', '0004_appversion'),
]
operations = [
migrations.AlterModelTable(
name='appversion',
table='app_version',
),
]

View File

@@ -0,0 +1,19 @@
# Generated by Django 5.0.2 on 2024-03-11 08:18
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('module_iam', '0005_alter_appversion_table'),
]
operations = [
migrations.AlterField(
model_name='appversion',
name='version',
field=models.CharField(max_length=10, validators=[django.core.validators.RegexValidator('^\\d+\\.\\d+\\.\\d+$')]),
),
]

View File

@@ -2,17 +2,28 @@ from collections.abc import Iterable
import datetime
import random
import string
# from manage_wallets.models import Wallet, Transaction, TransactionStatus, TransactionType
from django.conf import settings
from django.core.cache import cache
from django.contrib.auth import get_user_model
from django.contrib.auth.models import AbstractUser, BaseUserManager
from django.db import models
from django.utils import timezone
from django.utils.text import slugify
# from phonenumber_field.modelfields import PhoneNumberField
from module_project.utils import RandomGenerator
from .resource_action import PRINCIPAL_TYPE_USER, PRINCIPAL_TYPE_ADMIN
from .iam_constant import (
PRINCIPAL_TYPE_USER,
PRINCIPAL_TYPE_ADMIN,
PRINCIPAL_TYPE_SUBADMIN,
PRINCIPAL_SOURCE_APP,
PRINCIPAL_SOURCE_APPLE,
PRINCIPAL_SOURCE_GOOGLE,
PRINCIPAL_SOURCE_WEB,
)
# from .utils import UserContext
from django.core.validators import MaxValueValidator, MinValueValidator, RegexValidator
@@ -102,14 +113,60 @@ class IAmPrincipalType(MasterModel):
db_table = "iam_principal_type"
@classmethod
def get_principal_type(cls, type):
return cls.objects.filter(name=type).first()
def get_principal_type(cls, name):
cache_key = f"principal_{name}"
principal = cache.get(cache_key)
if not principal:
principal = cls.objects.filter(name=name).first()
cache.set(cache_key, principal, timeout=60 * 15) # Cache for 15 minutes
return principal
@classmethod
def get_principal_user(cls):
return cls.get_principal_type(PRINCIPAL_TYPE_USER)
@classmethod
def get_principal_admin(cls):
return cls.get_principal_type(PRINCIPAL_TYPE_ADMIN)
@classmethod
def get_principal_subadmin(cls):
return cls.get_principal_type(PRINCIPAL_TYPE_SUBADMIN)
class IAmPrincipalSource(MasterModel):
class Meta:
db_table = "iam_principal_source"
@classmethod
def get_principal_source(cls, name):
cache_key = f"principal_{name}"
principal = cache.get(cache_key)
if not principal:
principal = cls.objects.filter(name=name).first()
cache.set(cache_key, principal, timeout=60 * 15) # Cache for 15 minutes
return principal
@classmethod
def get_principal_web(cls):
return cls.get_principal_source(PRINCIPAL_SOURCE_WEB)
@classmethod
def get_principal_app(cls):
return cls.get_principal_source(PRINCIPAL_SOURCE_APP)
@classmethod
def get_principal_google(cls):
return cls.get_principal_source(PRINCIPAL_SOURCE_GOOGLE)
@classmethod
def get_principal_apple(cls):
return cls.get_principal_source(PRINCIPAL_SOURCE_APPLE)
class IAmAppAction(MasterModel):
class Meta:
@@ -239,7 +296,7 @@ class IAmPrincipalManager(BaseUserManager):
extra_fields.setdefault("is_staff", True)
extra_fields.setdefault("is_superuser", True)
extra_fields.setdefault("phone_no", "+919978895465")
extra_fields.setdefault("gender", "M")
extra_fields.setdefault("gender", "Male")
extra_fields.setdefault("date_of_birth", timezone.now())
extra_fields.setdefault("created_by", None)
extra_fields.setdefault("created_on", timezone.now())
@@ -298,7 +355,12 @@ class IAmPrincipal(AbstractUser):
related_name="principal_groups",
)
register_complete = models.BooleanField(default=False)
player_id = models.CharField(max_length=255, null=True, blank=True, help_text="OneSignal player id for push notification")
player_id = models.CharField(
max_length=255,
null=True,
blank=True,
help_text="OneSignal player id for push notification",
)
USERNAME_FIELD = "email"
REQUIRED_FIELDS = []
@@ -367,3 +429,15 @@ class IAmPrincipalBiometric(BaseModel):
def __str__(self):
return f"{self.principal.first_name}:{self.biometric_type}"
class AppVersion(models.Model):
version = models.CharField(max_length=10, validators=[RegexValidator(r'^\d+\.\d+\.\d+$')])
force_upgrade = models.BooleanField(default=False, help_text='Indicates whether a force upgrade is needed for this app version.')
recommend_upgrade = models.BooleanField(default=False, help_text='Indicates whether a recommend upgrade is needed for this app version.')
class Meta:
db_table = "app_version"
def __str__(self):
return self.version

View File

@@ -4,5 +4,32 @@ from . import views
app_name = "module_iam"
urlpatterns = [
path('dashboard/', views.DashboardView.as_view(), name="dashboard")
path('dashboard/', views.DashboardView.as_view(), name="dashboard"),
# path('principal/', views.PrincipalListView.as_view(), name="principal_list"),
# path('principal/add/', views.PrincipalCreateOrUpdateView.as_view(), name="principal_add"),
# path('principal/edit/<int:pk>', views.PrincipalCreateOrUpdateView.as_view(), name="principal_edit"),
# path('principal/delete/<int:pk>', views.PrincipalDeleteView.as_view(), name="principal_delete"),
path('principal/group/link/', views.PrincipalGroupLinkView.as_view(), name="principal_group_link"),
path('principal/group/link/', views.PrincipalGroupLinkAdminListJsonView.as_view(), name="principal_group_link_list"),
# path('principal/group/link/edit/<int:pk>/', views.PrincipalGroupLinkEditView.as_view(), name="principal_group_link_edit"),
path('principal/group/', views.PrincipalGroupView.as_view(), name="principal_group"),
path('principal/group/list', views.PrincipalGroupListJsonView.as_view(), name="principal_group_list"),
path('principal/group/add/', views.PrincipalGroupCreateOrUpdateView.as_view(), name="principal_group_add"),
path('principal/group/edit/<int:pk>/', views.PrincipalGroupCreateOrUpdateView.as_view(), name="principal_group_edit"),
path('principal/group/action//', views.PrincipalGroupActionView.as_view(), name="principal_group_action"),
path('principal/role/', views.AppRoleView.as_view(), name="role"),
path('principal/role/list/', views.AppRoleListJsonView.as_view(), name="role_list"),
path('principal/role/add/', views.AppRoleCreateOrUpdateView.as_view(), name="role_add"),
path('principal/role/edit/<int:pk>/', views.AppRoleCreateOrUpdateView.as_view(), name="role_edit"),
path('principal/role/action/', views.AppRoleActionView.as_view(), name="role_action"),
path("profile/", views.PrincipalProfileView.as_view(), name="profile_details"),
path("profile/edit/", views.PrincipalProfileEditView.as_view(), name="profile_details_edit")
]

View File

@@ -1,7 +1,374 @@
from django.shortcuts import render
from typing import Any
from django.db.models.base import Model as Model
from django.db.models.query import QuerySet
from django.views import generic
import logging
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.db.models import Q
from django.http import JsonResponse
from django.shortcuts import render, redirect, get_object_or_404
from django.urls import reverse_lazy
from module_iam import iam_constant
from module_project.mixins import DatatablesMixin
from django_datatables_view.base_datatable_view import BaseDatatableView
from module_project.mixins import ActionMixin
from .forms import (
CustomAuthenticationForm,
IAmPrincipalForm,
IAmPrincipalGroupRoleLinkForm,
IAmPrincipalRoleAppResourceActionLinkForm,
IAmPrincipalGroupLinkForm,
ProfileEditForm
)
from .models import (
IAmPrincipal,
IAmPrincipalType,
IAmAppResourceActionLink,
IAmPrincipalGroup,
IAmRole,
)
from module_project import constants
logger = logging.getLogger(__name__)
# Create your views here.
class DashboardView(generic.TemplateView):
template_name = "base_structure/layout/dashboard.html"
page_name = iam_constant.RESOURCE_MANAGE_DASHBOARD
template_name = "base_structure/layout/dashboard.html"
def get_user_count(self):
obj = IAmPrincipal.objects.all()
# Count active users
active_user_count = obj.filter(is_active=True).count()
# Count total users
total_user_count = obj.count()
return active_user_count, total_user_count
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
active_user_count, total_user_count = self.get_user_count()
context['active_user_count'] = active_user_count
context['total_user_count'] = total_user_count
context['page_name'] = self.page_name
return context
class PrincipalGroupLinkView(LoginRequiredMixin, generic.TemplateView):
page_name = iam_constant.RESOURCE_IAM_PRINCIPAL_GROUP
model = IAmPrincipal
template_name = "module_iam/iam_principal_group_link.html"
def get_context_data(self, **kwargs) -> dict[str, Any]:
context = super().get_context_data(**kwargs)
context["page_name"] = self.page_name
return context
class PrincipalGroupLinkAdminListJsonView(BaseDatatableView):
model = IAmPrincipal
columns = ["id", "first_name", "email", "principal_type__name", "is_active"],
order_columns = ["id", "first_name", "email"]
def get_initial_queryset(self):
deleted_flag = self.request.GET.get('deleted_flag', False)
return self.model.objects.filter(deleted=deleted_flag).exclude(principal_type__name=iam_constant.PRINCIPAL_TYPE_USER)
class PrincipalGroupView(LoginRequiredMixin, generic.TemplateView):
page_name = iam_constant.RESOURCE_IAM_GROUP
model = IAmPrincipalGroup
template_name = "module_iam/iam_group.html"
def get_context_data(self, **kwargs) -> dict[str, Any]:
context = super().get_context_data(**kwargs)
context["page_name"] = self.page_name
return context
def filter_queryset(self, qs):
search_value = self.request.GET.get("search[value]", None)
if search_value:
qs = qs.filter(
Q(id__icontains=search_value)
| Q(name__icontains=search_value)
)
return qs
class PrincipalGroupListJsonView(BaseDatatableView):
model = IAmPrincipalGroup
columns = ["id", "name", "active"]
order_columns = ["id", "name", "active"]
def get_initial_queryset(self):
deleted_flag = self.request.GET.get('deleted_flag', False)
return self.model.objects.filter(deleted=deleted_flag)
def filter_queryset(self, qs):
search_value = self.request.GET.get("search[value]", None)
if search_value:
qs = qs.filter(
Q(id__icontains=search_value)
| Q(name__icontains=search_value)
)
return qs
def generate_role_data(self, queryset):
roles_data = []
for obj in queryset:
roles = [{'name': role.name} for role in obj.role.all()]
print(f"role data is this {roles}")
roles_data.append({
'id': obj.id,
'name': obj.name,
'active': str(obj.active),
'roles': roles
})
return roles_data
def get_context_data(self, *args, **kwargs):
roles = self.filter_queryset(self.get_initial_queryset())
role_data = self.generate_role_data(roles)
context = super().get_context_data(*args, **kwargs)
context['recordsTotal'] = len(role_data)
context['recordsFiltered'] = len(role_data)
context['data'] = role_data
context['result'] = 'ok'
return context
class PrincipalGroupCreateOrUpdateView(LoginRequiredMixin, generic.View):
page_name = iam_constant.RESOURCE_IAM_GROUP
page_title = "Principal Group"
model = IAmPrincipalGroup
template_name = "module_iam/iam_group_add.html"
form_class = IAmPrincipalGroupRoleLinkForm
success_url = reverse_lazy("module_iam:principal_group")
error_message = "An error occurred while saving the data."
def get_success_message(self):
self.success_message = constants.RECORD_CREATED if not self.object else constants.RECORD_UPDATED
return self.success_message
def get_object(self):
pk = self.kwargs.get("pk")
return get_object_or_404(self.model, pk=pk) if pk else None
def get_context_data(self, **kwargs):
context = {
"page_name": self.page_name,
"operation": "Add" if not self.object else "Edit",
}
context.update(kwargs) # Include any additional context data passed to the view
return context
def get(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.form_class(instance=self.object)
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.form_class(request.POST, instance=self.object)
if not form.is_valid():
print(form.errors)
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
form.save()
messages.success(self.request, self.get_success_message())
return redirect(self.success_url)
class PrincipalGroupActionView(ActionMixin):
model = IAmPrincipalGroup
class AppRoleView(LoginRequiredMixin, generic.TemplateView):
page_name = iam_constant.RESOURCE_IAM_ROLE
model = IAmRole
template_name = "module_iam/iam_role.html"
def get_context_data(self, **kwargs) -> dict[str, Any]:
context = super().get_context_data(**kwargs)
context["page_name"] = self.page_name
return context
class AppRoleListJsonView(BaseDatatableView):
model = IAmRole
columns = ["id", "name", "active", "resources"]
order_columns = ["id", "name"]
def get_initial_queryset(self):
deleted_flag = self.request.GET.get('deleted_flag', False)
return (
super(AppRoleListJsonView, self)
.get_initial_queryset()
.prefetch_related(
"app_resource_action",
"app_resource_action__app_resource",
"app_resource_action__app_action",
)
.filter(deleted=deleted_flag)
)
def filter_queryset(self, qs):
search_value = self.request.GET.get("search[value]", None)
if search_value:
qs = qs.filter(
Q(id__icontains=search_value)
| Q(name__icontains=search_value)
| Q(app_resource_action__app_resource__name__icontains=search_value)
| Q(app_resource_action__app_action__name__icontains=search_value)
)
return qs
def generate_resource_data(self, roles):
role_data = []
for role in roles:
role_info = {
"id": role.id,
"name": role.name,
"active": str(role.active),
"resources": {},
}
for link in role.app_resource_action.all():
resource = link.app_resource.name
action = link.app_action.name
if resource in role_info["resources"]:
role_info["resources"][resource].append(action)
else:
role_info["resources"][resource] = [action]
role_data.append(role_info)
return role_data
def get_context_data(self, *args, **kwargs):
roles = self.filter_queryset(self.get_initial_queryset())
role_data = self.generate_resource_data(roles)
context = super().get_context_data(*args, **kwargs)
context['recordsTotal'] = len(role_data)
context['recordsFiltered'] = len(role_data)
context['data'] = role_data
context['result'] = 'ok'
return context
class AppRoleCreateOrUpdateView(LoginRequiredMixin, generic.View):
page_name = iam_constant.RESOURCE_IAM_ROLE
model = IAmRole
template_name = "module_iam/iam_role_add.html"
form_class = IAmPrincipalRoleAppResourceActionLinkForm
success_url = reverse_lazy("module_iam:role")
success_message = "Saved Successfully"
error_message = "An error occurred while saving the data."
def get_success_message(self):
self.success_message = (
f"Record {'Created' if not self.object else 'Updated'} Successfully"
)
return self.success_message
def get_object(self):
pk = self.kwargs.get("pk")
return get_object_or_404(self.model, pk=pk) if pk else None
def get_context_data(self, **kwargs):
context = {
"page_name": self.page_name,
"operation": "Add" if not self.object else "Edit",
"app_resource_action": IAmAppResourceActionLink.objects.generate_app_resource_action_data(),
}
context.update(kwargs) # Include any additional context data passed to the view
return context
def get(self, request, *args, **kwargs):
try:
self.object = self.get_object()
form = self.form_class(instance=self.object)
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
except Exception as e:
messages.error(request, str(e))
return redirect(self.success_url)
def post(self, request, *args, **kwargs):
try:
self.object = self.get_object()
form = self.form_class(request.POST, instance=self.object)
if not form.is_valid():
print(form.errors)
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
form.save()
messages.success(self.request, self.get_success_message())
return redirect(self.success_url)
except Exception as e:
messages.error(self.request, str(e))
return redirect(self.success_url)
class AppRoleActionView(LoginRequiredMixin, ActionMixin):
model = IAmRole
class PrincipalProfileView(LoginRequiredMixin, generic.TemplateView):
page_name = iam_constant.RESOURCE_MANAGE_DASHBOARD
model = IAmPrincipal
template_name = "module_iam/profile_details.html"
def get_object(self, queryset=None):
user = self.request.user.id
return get_object_or_404(self.model.objects.select_related("principal_type", "principal_source"), pk=user)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["page_name"] = self.page_name
context["data_obj"] = self.get_object()
return context
class PrincipalProfileEditView(generic.View):
page_name = iam_constant.RESOURCE_MANAGE_DASHBOARD
model = IAmPrincipal
template_name = "module_iam/profile_details_edit.html"
form_class = ProfileEditForm
success_url = reverse_lazy("module_iam:profile_details")
success_message = "Saved Successfully"
error_message = "An error occurred while saving the data."
def get_success_message(self):
self.success_message = (
f"Record {'Created' if not self.object else 'Updated'} Successfully"
)
return self.success_message
def get_object(self):
return self.request.user
def get_context_data(self, **kwargs):
context = {
# "page_name": self.page_name,
"operation": "Edit",
"page_name": self.page_name
}
context.update(kwargs) # Include any additional context data passed to the view
return context
def get(self, request, *args, **kwargs):
# try:
self.object = self.get_object()
form = self.form_class(instance=self.object)
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.form_class(request.POST, request.FILES, instance=self.object)
if not form.is_valid():
print(form.errors)
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
form.save()
messages.success(self.request, self.get_success_message())
return redirect(self.success_url)