generate flutter forms and models

autogenerate_flutter
Mustafa Yontar 3 years ago
parent 8da4aed715
commit 5994f2a155
  1. 3
      .gitignore
  2. 5
      internal_lib/EncryptedField.py
  3. 22
      main.py
  4. 8
      models/Group.py
  5. 12
      models/Payment.py
  6. 7
      models/Union.py
  7. 4
      models/User.py
  8. 0
      scripts/__init__.py
  9. 146
      scripts/generate_flutter_forms.py
  10. 212
      scripts/generate_flutter_model.py

3
.gitignore vendored

@ -24,4 +24,5 @@ var/
*test.py
trash
mongo_data_dir/*
.directory
.directory
flutter_out/

@ -13,7 +13,10 @@ class EncryptedStringField(BaseField):
def __init__(self, **kwargs):
import os
priv_key = os.environ.get('ADUNATIO_PRIV_KEY')
self.keyPair = RSA.importKey(open(priv_key).read())
try:
self.keyPair = RSA.importKey(open(priv_key).read())
except:
pass
super().__init__(**kwargs)

@ -2,10 +2,12 @@ from flask import Flask, request, jsonify
from flask_admin.contrib.mongoengine import ModelView
from flask_jwt_extended import JWTManager, create_access_token
from mongoengine import connect
from werkzeug.security import check_password_hash
from werkzeug.security import check_password_hash ,generate_password_hash
from internal_lib.AuthMethots import AuthJWT
from models.Group import Group
from models.Account import Account
from models.Group import Group, PaymentGroup
from models.Payment import Payments
from models.Union import Union
from models.User import User
from restapi import MongoApi
@ -31,8 +33,12 @@ jwt = JWTManager(app)
flask mongorester register
"""
api = MongoApi(app, authentication_methods=[AuthJWT])
api.register_model(User, uri="/api/user")
api.register_model(Union, uri="/api/union")
api.register_model(User, uri="/api/user/")
api.register_model(Union, uri="/api/union/")
api.register_model(Group, uri="/api/group/")
api.register_model(PaymentGroup, uri="/api/payment_group/")
api.register_model(Account, uri="/api/accounts/")
api.register_model(Payments, uri="/api/payments/")
"""
flask admin register
@ -66,7 +72,13 @@ def login():
app.logger.error(e)
return jsonify({"message": "Bad username or password", "error": "Unauthorized", "status": False}), 401
if not check_password_hash(user.password,password):
app.logger.error(password)
app.logger.error(username)
app.logger.error(generate_password_hash(password))
app.logger.error(user.password)
app.logger.error(check_password_hash(pwhash=user.password,password=password))
if check_password_hash(pwhash=user.password,password=password) == False:
return jsonify({"message": "Bad username or password", "error": "Unauthorized", "status":False}), 401
# Identity can be any data that is json serializable

@ -5,8 +5,8 @@ from models.Union import Union
class Group(Document):
union = ReferenceField(Union)
name = StringField()
rights = ListField(StringField())
name = StringField(required=True)
rights = ListField(StringField(),required=True)
deleted = BooleanField(default=False)
def __unicode__(self):
return "{} {}".format(self.union.name,self.name)
@ -14,9 +14,9 @@ class Group(Document):
class PaymentGroup(Document):
union = ReferenceField(Union)
name = StringField()
name = StringField(required=True)
deleted = BooleanField(default=False)
discount_percent = IntField()
discount_percent = IntField(required=True)
def __unicode__(self):
return "{} {}".format(self.union.name, self.name)

@ -11,19 +11,17 @@ class Payments(Document):
all payments income and outcome together!
"""
union = ReferenceField(Union)
user = ReferenceField(User)
user = ReferenceField(User, required=True)
income = BooleanField(default=False)
date = DateTimeField()
regular = BooleanField(default=False)
regular_type = StringField(choices=('Weekly','Monthly','Yearly'))
price = DecimalField()
regular_type = StringField(choices=('Weekly', 'Monthly', 'Yearly'))
price = DecimalField(required=True)
deleted = BooleanField(default=False)
description = StringField()
reference_no = StringField()
file = ReferenceField(File)
account = ReferenceField(Account)
account = ReferenceField(Account, required=True)
due_date = DateTimeField()
is_paid = BooleanField(default=False)
is_paid = BooleanField(default=False, required=True)
is_donate = BooleanField(default=False)

@ -20,7 +20,7 @@ class Union(Document):
"indexes": [
('name'),
("-name"),
]
],
}
name = StringField(required=True)
logo = ImageField(thumbnail_size=(120, 120))
@ -55,7 +55,8 @@ class Union(Document):
user.union = self
from flask import current_app
password = ''.join(choices(ascii_letters + digits, k=10))
current_app.logger.info("New union password : {}".format(password))
user.password = generate_password_hash(password)
passhash = generate_password_hash(password,salt_length=20)
current_app.logger.info("New union password : '{}'".format(password))
user.password = passhash
# TODO: send password via mail or sms or nothing
user.save()

@ -29,7 +29,9 @@ class User(Document):
('union'),
('username', 'union'),
('accept_date')
]
],
"auto_generated": ['union','deleted','member_no']
}
deleted = BooleanField(default=False)
union = ReferenceField(Union)

@ -0,0 +1,146 @@
from models.Account import Account
from models.Payment import Payments
from models.User import User
from scripts.generate_flutter_model import build_class
def mainBuilder(classlist):
blist = []
for cls in classlist:
data = build_class(cls,blist)
blist = blist + data[1]
clstypeList = [i.__class__.__name__ for i in blist]
for classItem in data[0]:
imports = "import 'package:flutter/material.dart';\n"
imports += "import 'package:flutter/services.dart';\n"
controller = ""
controllerInit = ""
controllerDispose = ""
textFields = ""
for field in classItem.get('fields'):
if field.get('name') == "id":
continue
if field.get('autogen'):
continue
controller += "\tTextEditingController _{};\n".format(field.get('name'))
controllerInit += "\t\t_{} = new TextEditingController();\n".format(field.get('name'))
controllerDispose += "\t\t_{}.dispose();\n".format(field.get('name'))
req = ""
if field.get('required'):
req = """
validator: (value) {
if (value.isEmpty) {
return 'Please enter some text';
}
return null;
},
"""
if field.get("is_class"):
imports += "import 'package:adunationfe/data/forms/Form{}.dart';\n".format(field.get('class_name'))
imports += "import 'package:adunationfe/data/models/{}.dart';\n".format(field.get('class_name'))
if field.get('islist'):
controller += "\t\tList<{classname}> item{name};\n".format(classname=field.get('class_name'),
name=field.get('name'))
controllerInit += "\t\t\titem{name} = [];\n".format(name=field.get('name'))
else:
controller += "\t\t{classname} item{name};\n".format(classname=field.get('class_name'),
name=field.get('name'))
controllerInit += "\t\t\titem{name} = {classname}();\n".format(classname=field.get('class_name'),
name=field.get('name'))
elif field.get('choices'):
imports += "import 'package:dropdown_search/dropdown_search.dart';\n"
textFields += """
DropdownSearch<String>(
mode: Mode.BOTTOM_SHEET,
showClearButton: true,
showSearchBox: true,
label: '{name}',
showSelectedItem: true,
items: ['{items}'],
hint: "country in menu mode",
onChanged: print,
selectedItem: "")
,
SizedBox(
height: 15,
),
""".format(items = "','".join(field.get('choices')),name=field.get('name'))
elif field.get('type') == 'String':
textFields +="""
new TextFormField(
decoration: new InputDecoration(labelText: "Enter your {name}"),
controller: _{name},
{req}
),
SizedBox(
height: 15,
),
""".format(name=field.get('name'),req=req)
elif field.get('type') == 'int':
textFields += """
new TextFormField(
decoration: new InputDecoration(labelText: "Enter your {name}"),
controller: _{name},
keyboardType: TextInputType.number,
inputFormatters: < TextInputFormatter > [
FilteringTextInputFormatter.digitsOnly
],
{req}
),
SizedBox(
height: 15,
),
""".format(name=field.get('name'),req=req)
# elif field.get('is_class'):
# print(field)
# # exit()
cls_text = """
{imports}
class Form{classname} extends StatefulWidget {{
@override
_Form{classname} createState() => _Form{classname}();
}}
class _Form{classname} extends State<Form{classname}> {{
{controller}
final _{classname} = GlobalKey<FormState>();
@override
void initState() {{
{initdata}
super.initState();
}}
@override
void dispose() {{
{dispose}
super.dispose();
}}
@override
Widget build(BuildContext context) {{
return new Form(
key:_{classname},
child:new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
{textfield}
])
);
}}
}}
""".format(imports=imports,classname=classItem.get('class'),controller=controller,initdata=controllerInit,dispose=controllerDispose,textfield=textFields)
f = open("flutter_out/Form{}.dart".format(classItem.get('class')),"w+")
f.write(cls_text)
f.close()
import os
os.chdir('../')
print(os.getcwd())
mainBuilder([User, Payments, Account])

@ -0,0 +1,212 @@
import mongoengine
import os
from models.Account import Account
from models.Payment import Payments
from models.User import *
from mongoengine import fields
types = {
mongoengine.fields.StringField: "String",
IntField: 'int',
BooleanField: 'bool',
FloatField: 'Float',
DictField: 'Map<String,dynamic>'
}
def to_camel_case(snake_str):
components = snake_str.split('_')
# We capitalize the first letter of each component except the first one
# with the 'title' method and join them together.
return components[0] + ''.join(x.title() for x in components[1:])
def buildReferenceField(field_object, builded):
if isinstance(field_object, (ReferenceField, EmbeddedDocumentField)):
if field_object.document_type not in builded:
builded.append(field_object.document_type)
return build_class(field_object.document_type, builded)
return None, builded
else:
return None, builded
def buildFields(field_object):
type = ""
if isinstance(field_object, mongoengine.fields.LongField):
type = "long"
elif isinstance(field_object, EncryptedStringField):
type = "String"
elif isinstance(field_object, fields.ImageField):
type = "String"
elif isinstance(field_object, EncryptedStringField):
type = "String"
elif isinstance(field_object, StringField):
type = "String"
elif isinstance(field_object, ObjectIdField):
type = "String"
elif isinstance(field_object, DateTimeField):
type = "DateTime"
elif isinstance(field_object, IntField):
type = "int"
elif isinstance(field_object, BooleanField):
type = "bool"
elif isinstance(field_object, FloatField):
type = "double"
elif isinstance(field_object, DictField):
type = "Map<String,dynamic>"
elif isinstance(field_object, DynamicField):
type = "dynamic"
else:
type = "String"
return type
def build_class(mongoClass, builded):
if builded is None:
builded = []
mClass = mongoClass
builded.append(mClass)
rClass = mongoClass()
builded.append(rClass)
class_list = []
field_list = []
for field in rClass._fields_ordered:
field_object = getattr(mClass, field)
ignore_fields = mClass._meta.get('ignore_fields')
autogen_fields = mClass._meta.get('auto_generated')
if not ignore_fields:
ignore_fields = []
if not autogen_fields:
autogen_fields = []
if isinstance(field_object, (ReferenceField, EmbeddedDocumentField)):
_, builded = buildReferenceField(field_object, builded)
if _ is not None:
class_list = class_list + list(_)
pn = field_object.document_type()
if field not in ignore_fields:
field_list.append(
{"type": pn._class_name, "origin_name": field, "name": to_camel_case(field), "islist": False,
"is_class": True, "required":field_object.required, "class_name": pn._class_name, "autogen": field in autogen_fields})
elif isinstance(field_object, ListField):
if isinstance(field_object.field, (ReferenceField, EmbeddedDocumentField)):
_, builded = buildReferenceField(field_object.field, builded)
if _ is not None:
class_list = class_list + list(_)
pn = field_object.field.document_type()
if field not in ignore_fields:
field_list.append(
{"type": "List<{}>".format(pn._class_name), "origin_name": field, "name": to_camel_case(field),
"islist": True, "is_class": True, "required":field_object.required, "class_name": pn._class_name, "autogen": field in autogen_fields})
else:
type = buildFields(field_object.field)
if field not in ignore_fields:
field_list.append({"type": "List<{}>".format(type), "name": to_camel_case(field), "origin_name": field,
"islist": True, "originType": field_object.field, "required":field_object.required, "autogen": field in autogen_fields,"choices":field_object.field.choices})
else:
type = buildFields(field_object)
if field not in ignore_fields:
chc = None
req = False
if field_object is not None:
chc = field_object.choices
req = field_object.required
field_list.append(
{"type": "{}".format(type), "name": to_camel_case(field), "origin_name": field, "islist": False,
"originType": field_object, "autogen": field in autogen_fields,"choices":chc,"required":req})
class_list.append({'class': rClass._class_name, "fields": field_list})
return class_list, builded
f = None
def print(item):
if f:
f.writelines(str(item) + "\n")
def buildFunctionFromJson(fields):
print("\t void fromJson(data) {")
for i in fields:
if i.get('type') != "DateTime":
if not i.get('islist') and not i.get('is_class'):
print("\t\tthis.{} = data[\"{}\"];".format(i.get('name'), i.get("origin_name")))
elif i.get('islist') and not i.get('is_class'):
print("\t\tthis.{}=[];".format(i.get('name')));
print("\t\tdata[\"{}\"].forEach((element)".format(i.get("origin_name")))
print("\t\t{")
print("\t\t\tthis.{}.add(element);".format(i.get('name')))
print("\t\t}"
");")
elif not i.get('islist') and i.get('is_class'):
print("\t\tthis.{} = {}();".format(i.get('name'), i.get('class_name')))
print("\t\tthis.{}.fromJson(data[\"{}\"]);".format(i.get('name'), i.get('origin_name')))
else:
print("\t\tthis.{}=[];".format(i.get('name')));
print("\t\tdata[\"{}\"].forEach((element)".format(i.get("origin_name")))
print("\t\t{")
print("\t\t\t{cname} cls = {cname}();".format(cname=i.get('class_name')))
print("\t\t\tcls.fromJson(data[\"{}\"]);".format(i.get('origin_name')))
print("\t\t\tthis.{}.add(cls);".format(i.get('name')))
print("\t\t}"
");")
print("\t}")
def exportJson(fields):
print("\tMap<String,dynamic> toJson() {")
print("\t\tMap<String,dynamic> output = {};")
for i in fields:
if i.get('type') != "DateTime":
if not i.get('islist') and not i.get('is_class'):
print("\t\toutput[\"{}\"] = this.{};".format(i.get('origin_name'), i.get("name")))
elif i.get('islist') and not i.get('is_class'):
print("\t\toutput[\"{}\"] = [];".format(i.get('origin_name')))
print("\t\tthis.{}.forEach((element) => output[\"{}\"].add(element));".format(i.get('name'),i.get('origin_name')))
elif i.get('islist') and i.get('is_class'):
print("\t\toutput[\"{}\"] = [];".format(i.get('origin_name')))
print("\t\tthis.{}.forEach((element) => output[\"{}\"].add(element.toJson()));".format(i.get('name'),
i.get('origin_name')))
elif not i.get('islist') and i.get('is_class'):
print("\t\toutput[\"{}\"] = this.{}.toJson();".format(i.get('origin_name'),i.get('name')))
print("\t\treturn output;")
print("\t}")
def mainBuilder(classlist):
global f
blist = []
for cls in classlist:
data = build_class(cls,blist)
blist = blist + data[1]
for i in data[0]:
f = open('flutter_out/{}.dart'.format(i.get('class')),"w")
print("import 'package:scoped_model/scoped_model.dart';")
print("class {} extends Model ".format(i.get('class')))
print("{")
for field in i.get('fields'):
print("\t {} {};".format(field.get('type'), field.get('name')))
print("")
print("\t// Build Functions")
print("\t// ")
buildFunctionFromJson(i.get('fields'))
exportJson(i.get('fields'))
print("}")
if __name__ == '__main__':
import os
os.chdir('../')
print(os.getcwd())
mainBuilder([User, Payments, Account])
Loading…
Cancel
Save