m_n create/update works UNLESS update is none

This commit is contained in:
Daniel Tsvetkov 2020-06-08 12:19:28 +02:00
parent a567739eaf
commit 4ef7da556c
8 changed files with 105 additions and 19 deletions

View File

@ -48,6 +48,16 @@
font-family: Open Sans, Arial sans-serif;
font-size: 1em;
box-sizing: border-box;
min-width: 300px;
}
input[type=number] {
min-width: 70px;
width: 70px;
}
select {
min-width: 300px;
}
.full-width {

View File

@ -1,3 +1,4 @@
import importlib
from functools import wraps
import inflect
@ -6,15 +7,21 @@ from flask import flash, render_template, redirect, request, url_for, jsonify
from oshipka.persistance import db
from oshipka.util.strings import camel_case_to_snake_case
webapp_models = importlib.import_module("webapp.models")
MODEL_VIEWS = dict()
def default_get_args_func(view_context):
view_context.serialized_args = request.args
def default_get_form_func(vc):
vc.redirect_next = request.form.get('_next')
vc.serialized_args = dict(filter(lambda k: not k[0].startswith("_"), dict(request.form).items()))
for k in request.form:
if k.startswith('_m_n_'):
vc.serialized_args[k] = request.form.getlist(k)
vc.serialized_args.update(dict(filter(lambda k: not k[0].startswith("_"), dict(request.form).items())))
to_delete = []
for key, value in vc.serialized_args.items():
if key.endswith('_id'):
@ -61,16 +68,43 @@ def default_search_func(vc):
vc.instances = vc.model_view.model.search_query("{q}".format(q=q)).all()
def _filter_m_n(vc):
m_ns, to_delete = {}, []
for k in vc.serialized_args:
if k.startswith('_m_n_'):
m_n_name = k.split('_m_n_')[1]
m_ns[m_n_name] = vc.serialized_args[k]
to_delete.append(k)
for key in to_delete:
del vc.serialized_args[key]
return m_ns
def _update_m_ns(vc, m_ns):
instance = vc.instance
for key, ids in m_ns.items():
child_rel = getattr(vc.instance, "_m_n_table_{}".format(key))
child_table = getattr(webapp_models, child_rel)
children = db.session.query(child_table).filter(child_table.id.in_(ids)).all()
setattr(instance, key, children)
def default_create_func(vc):
m_ns = _filter_m_n(vc)
instance = vc.model_view.model(**vc.serialized_args)
db.session.add(instance)
vc.instance = instance
vc.instances = [instance]
_update_m_ns(vc, m_ns)
db.session.add(instance)
def default_update_func(vc):
m_ns = _filter_m_n(vc)
instance = vc.instances[0]
vc.instance = instance
for k, v in vc.serialized_args.items():
setattr(instance, k, v)
_update_m_ns(vc, m_ns)
db.session.add(instance)

View File

@ -1,9 +1,13 @@
[%- if not column.secondary %]
[%- if not column.multiple %]
[[ column.name ]]_id = db.Column(db.Integer, db.ForeignKey('[%- if column.to %][[ column.to|camel_to_snake ]][%- else %][[ column.name ]][% endif %].id'))
[%- endif %]
[[ column.name|pluralize if column.secondary else column.name ]] = db.relationship('[%- if column.to %][[ column.to ]][%- else %][[ column.name|snake_to_camel ]][% endif %]',
[%- if column.secondary %]secondary=[[ column.secondary ]], [%- endif %]
[[ column.name|pluralize if column.multiple else column.name ]] = db.relationship('[%- if column.to %][[ column.to ]][%- else %][[ column.name|snake_to_camel ]][% endif %]',
[%- if column.multiple %]secondary=[[ column.secondary.name ]], [%- endif %]
backref=db.backref("[%- if column.backref %][[ column.backref ]][%- else %][[ name|camel_to_snake|pluralize ]][%- endif %]"),
[%- if column.foreign_keys %]foreign_keys=[ [[ column.foreign_keys ]]_id],[%- endif %]
)
[%- if column.multiple %]
_m_n_table_[[ column.name|pluralize ]] = '[%- if column.to %][[ column.to ]][%- else %][[ column.name|snake_to_camel ]][% endif %]'
[%- endif %]

View File

@ -3,13 +3,22 @@
[%- for column in columns %]
<label for="input-[[ name|camel_to_snake ]]-[[ column.name ]]">[[ column.name ]]</label>:
[%- if column.type in ['relationship'] %]
<select id="input-[[ name|camel_to_snake ]]-[[ column.name ]]" [%- if column.secondary %]multiple[%- endif %]
name="[[ column.name ]]_id">
<select id="input-[[ name|camel_to_snake ]]-[[ column.name ]]" [%- if column.multiple %]multiple
name="_m_n_[[ column.name|pluralize ]]"[% else %]name="[[ column.name ]]_id"[%- endif %]>
[%- if not column.secondary %]
<option selected="selected">Choose...</option>
[%- endif %]
{%- for sub_instance in model_views.[[ column.name ]].model.query.all() %}
<option value="{{ sub_instance.id }}" {% if instance and instance.id == sub_instance.id %}selected="selected"{% endif %}>{{ sub_instance.name }}</option>
{%- endfor %}
</select>
[%- elif column.type in ['choice', ] %]
<select id="input-[[ name|camel_to_snake ]]-[[ column.name ]]"
name="[[ column.name ]]_id">
[%- for value, display in column.choices.items() %]
<option value="[[ value ]]" {% if instance and instance.[[ column.name ]] == "[[ value ]]" %}selected="selected"{% endif %}>[[ display ]]</option>
[%- endfor %]
</select>
[%- elif column.type in ['number', 'int', 'integer', ] %]
<input id="input-[[ name|camel_to_snake ]]-[[ column.name ]]"
type="number" name="[[ column.name ]]"
@ -19,6 +28,7 @@
type="text" name="[[ column.name ]]" autocomplete="off"
/>
[%- endif %]
<br>
[%- endfor %]
<input type="submit">
</form>

View File

@ -6,7 +6,11 @@
<source src="{{ url_for('oshipka_bp.get_media', filepath=instance.[[ column.name ]]) }}" type="video/webm">
</video>
[%- elif column.type in ['relationship'] %]
[%- if column.multiple %]
<li id="display-[[ name|camel_to_snake ]]-[[ column.name|pluralize ]]"><strong>[[ column.name|pluralize ]]</strong>: {{ instance.[[ column.name|pluralize ]] }}</li>
[%- else %]
<li id="display-[[ name|camel_to_snake ]]-[[ column.name ]]"><strong>[[ column.name ]]</strong>: {{ instance.[[ column.name ]] }}</li>
[%- endif %]
[%- else %]
<li id="display-[[ name|camel_to_snake ]]-[[ column.name ]]"><strong>[[ column.name ]]</strong>: {{ instance.[[ column.name ]] }}</li>
[%- endif %]

View File

@ -14,7 +14,17 @@
<tr>
[%- for column in columns %]
{% if "[[ column.name ]]" not in skip_columns %}
<td>{{ instance.[[ column.name ]] }}</td>
<td>
[%- if column.type in ['relationship'] %]
[%- if column.multiple %]
{{ instance.[[ column.name|pluralize ]] }}
[%- else %]
{{ instance.[[ column.name ]] }}
[%- endif %]
[%- else %]
{{ instance.[[ column.name ]] }}
[%- endif %]
</td>
{% endif %}
[%- endfor %]
<td>

View File

@ -4,12 +4,23 @@
<label for="input-[[ name|camel_to_snake ]]-[[ column.name ]]">[[ column.name ]]</label>:
[%- if column.type in ['relationship'] %]
<select id="input-[[ name|camel_to_snake ]]-[[ column.name ]]"
name="[[ column.name ]]_id">
[%- if column.multiple %]multiple name="_m_n_[[ column.name|pluralize ]]"[% else %]name="[[ column.name ]]_id"[%- endif %]>
{%- for sub_instance in model_views.[[ column.name ]].model.query.all() %}
<option value="{{ sub_instance.id }}"
[%- if column.multiple %]
{% if sub_instance in instance.[[ column.name|pluralize ]] %}selected="selected"{% endif %}>{{ sub_instance.name }}</option>
[%- else %]
{% if instance.[[ column.name ]]_id == sub_instance.id %}selected="selected"{% endif %}>{{ sub_instance.name }}</option>
[%- endif %]
{%- endfor %}
</select>
[%- elif column.type in ['choice', ] %]
<select id="input-[[ name|camel_to_snake ]]-[[ column.name ]]"
name="[[ column.name ]]_id">
[%- for value, display in column.choices.items() %]
<option value="[[ value ]]" {% if instance.[[ column.name ]] == "[[ value ]]" %}selected="selected"{% endif %}>[[ display ]]</option>
[%- endfor %]
</select>
[%- elif column.type in ['number', 'int', 'integer', ] %]
<input id="input-[[ name|camel_to_snake ]]-[[ column.name ]]"
value="{{ instance.[[ column.name ]] }}"
@ -21,6 +32,7 @@
type="text" name="[[ column.name ]]" autocomplete="off"
/>
[%- endif %]
<br>
[%- endfor %]
<input type="submit">
</form>

View File

@ -24,14 +24,15 @@ def _process_choice(column):
}
def process_secondary(secondary):
col1, col2 = secondary.split('_')
def process_secondary(view_model, column_name):
model_name = camel_case_to_snake_case(view_model.get('name'))
secondary = "{}__{}".format(model_name, column_name)
return {
'name': secondary,
'columns': [{
'name': col1
'name': model_name
}, {
'name': col2
'name': column_name
}]
}
@ -49,11 +50,12 @@ def enrich_view_model(view_model):
_column_type = 'db.Boolean'
elif column_type in ['relationship', ]:
_column_type = 'relationship'
secondary = column.get('secondary')
if secondary:
multiple = column.get('multiple')
if multiple:
if '_secondaries' not in view_model:
view_model['_secondaries'] = []
secondary_model = process_secondary(secondary)
secondary_model = process_secondary(view_model, column_name)
column.update({'secondary': secondary_model})
view_model['_secondaries'].append(secondary_model)
elif column_type in ['choice', ]:
if '_choice_types' not in view_model: