mein Name ist Andre. Euer Forum hat mir schon sehr oft mit Topics anderer User weitergeholfen, jetzt habe ich aber eine Frage, dessen Antwort ich bisher noch nicht gefunden habe.
Ich nutze Python 2.7 mit Django 1.9
Ich bin gerade dabei auf Basis von Jinja2 ein templatebasierten ConfigurationGui für Router und andere Netzwerkkomponenten zu bauen.
Mittels Jinja MetaAPI und JinjaSchema analysiere ich die Templates und möchte nun die notwendigen Datenbankeinträge vornehmen. Funktioniert auch soweit alles gut.
Folgende Models habe ich dafür erstellt:
Code: Alles auswählen
class Config(BaseModel):
# Foreign Keys
customer = models.ForeignKey('customer.Customer', related_name="customer_Customers_related", on_delete = models.CASCADE)
site = models.ForeignKey('customer.Site', related_name="customer_sites_related", on_delete = models.CASCADE)
product = models.ForeignKey('product.Product', related_name="product_products_related", on_delete = models.CASCADE)
hardware = models.ForeignKey('product.Hardware', related_name="product_hardwares_related", on_delete = models.CASCADE)
code_tree = TreeForeignKey('Code', null=True, related_name="confgen_codes_related", on_delete = models.CASCADE)
# Info
hostname = models.CharField(max_length=100, blank=False, null=False, unique=True)
description = models.TextField(default="", blank=True)
def __unicode__(self):
return self.hostname
###########################################################################################################
# code tree
class Code(MPTTModel):
# Foreign Keys
config = models.ForeignKey('Config', null=True, related_name="confgen_configs_related", on_delete = models.CASCADE)
template = models.ForeignKey('Template', null=True, related_name="confgen_templates_related", on_delete = models.CASCADE)
include_name = models.CharField(max_length=100, blank=True, null=False)
# MPTT Field
parent = TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True)
# Info
name = models.CharField(max_length=50, blank=False, null=False)
code = models.TextField(default='', null=False, blank=True)
active = models.BooleanField(default=False)
customized = models.BooleanField(default=False)
def __unicode__(self):
return self.name
###########################################################################################################
# variable list
# possible values for select and choice fields
class VarValue(BaseModel):
# Foreign Keys
config = models.ForeignKey('Config', null=False, blank=False, related_name="confgen_config_related", on_delete = models.CASCADE)
code = models.ForeignKey('Code', null=False, blank=False, related_name="confgen_code_related", on_delete = models.CASCADE)
var = models.ForeignKey('Var', null=False, blank=False, related_name="confgen_var_related", on_delete = models.CASCADE)
# Info
#index = models.CharField(max_length=50, blank=False, null=False)
value = models.CharField(max_length=512, blank=False, null=False)
#var_type = models.CharField(max_length=10, blank=False, null=True)
def __unicode__(self):
return self.value
##########################################################################################################
# to config saved variables
class Var(BaseModel):
# Foreign Keys
#Info
index = models.CharField(max_length=50, blank=False, null=False)
values = models.CharField(max_length=1024, blank=False, null=True)
var_type = models.CharField(max_length=10, blank=False, null=False)
def __unicode__(self):
return self.index
##########################################################################################################
class VarType(BaseModel):
name = models.CharField(max_length=50, blank=False, null=False)
format_regex = models.CharField(max_length=1024, blank=False, null=True)
example = models.CharField(max_length=512, blank=False, null=False)
###########################################################################################################
class Template(BaseModel):
# Foreign Keys
product = models.ManyToManyField('product.Product',related_name='template_product')
hardware = models.ManyToManyField('product.Hardware',related_name='template_hardware')
folder = TreeForeignKey('Folder', null=False, blank=False, related_name="%(app_label)s_%(class)s_related", on_delete = models.CASCADE)
#Info
name = models.CharField(max_length=50, blank=False, null=False, unique=True)
description = models.TextField()
is_mastertemplate = models.BooleanField(default=False)
path = models.CharField(max_length=1024, blank=False, null=False)
code = models.TextField()
def __unicode__(self):
return self.name
Ich nutze folgende rekursive Funktion, um den MPTT Code zu befüllen. Der Tree enthält quasi als root-Eintrag das Mastertemplate (hier ist die Config-Logik enthalten) und die Config-Snippets als MPTT-children.
_templateTree ist ein nested Ordered Dict, das zuvor schon durch die Jinja include-Anweisungen erzeugt wird.
index = ein TemplateClass Object
value = OrderedDict mit den includierten Templates/Snippets
Code: Alles auswählen
def create_code_tree(self, configObj, parentObj=None, tree=None ):
if tree is None:
tree = self._templateTree
for tmpl, nested_tmpls in tree.items():
print tmpl.get_ID()
# save to CodeTree
codeObj = Code.objects.create(
name=tmpl.get_ModelInstance().name,
config=configObj,
template=tmpl.get_ModelInstance(),
include_name=tmpl.get_IncludeName(),
code=tmpl.get_Code(),
)
if parentObj is not None:
codeObj.parent = parentObj
codeObj.save()
# save to VarValue
for var in tmpl.get_VarList():
varObj = Var.objects.get(index=var)
VarValue.objects.create(
config=configObj,
code=codeObj,
var=varObj,
)
if nested_tmpls is not None:
self.create_code_tree(configObj, codeObj, nested_tmpls)
Da die Templates aber auch teilweise manuell ertellt werden, möchte ich ein ErrorHandling hinzufügen.
z.B. wenn eine im Template angelegte Variable nicht in der Tabelle Var entahlten ist, soll die Config erst gar nicht angelegt werden, sondern stattdessen mit einem Templateerror enden, den ich im Endeffekt als Fehler dem User anzeigen kann.
Bis es aber dazu kommt, dass der Befehl
Code: Alles auswählen
varObj = Var.objects.get(index=var)
Wie bereite ich quasi das Query vor, um zu prüfen ob ein Fehler eintritt, ohne bereits alles in DB zu schreiben?
Ich hoffe ich habe mich verständlich ausgedrückt.
Gruß Schrodi