1

I'm trying to create a YAML file in a certain format. A already tried the official Django forum. But in the meantime I have the feeling here are more people who could help :-)

from django.db import models

# Create your models here.

# class NameManager(models.Manager):
    # def get_by_natural_key(self, name):
        # return self.get(name=name)

class FactoryName(models.Model):
    name = models.CharField(max_length=100, unique=True)

    def __str__(self):
        return self.name

class Option(models.Model):
    name = models.CharField(max_length=100, unique=True)
    factory = models.ForeignKey(FactoryName, on_delete=models.CASCADE)

    def __str__(self):
        return self.name

class AbstractOptionPackage(models.Model):
    name = models.CharField(max_length=100, unique=True)
    description = models.TextField()
    options = models.ManyToManyField(Option)
    class Meta:
        abstract = True

    def __str__(self):
        return self.name

class InteriorPackage(AbstractOptionPackage):
    def __str__(self):
        return self.name

class ExteriorColor(models.Model):
    name = models.CharField(max_length=100, unique=True)

    def __str__(self):
        return self.name

class Export(models.Model):
    name = models.CharField(max_length=100, unique=True)
    exterior_colors = models.ManyToManyField(ExteriorColor)
    interior_package = models.ForeignKey(InteriorPackage, on_delete=models.CASCADE)

    def __str__(self):
        return self.name

Now I would like to create a YAML file which looks roughly like this (it will be processed in other software, "# ..." are just comments here in this posting):

Filename: {{Export.name}}.yaml # I think I already found "open(...)" example code also for serialization.


{{Factory[0].name}}: # Name of first factory
    - {{ options[0] from any class derived from AbstractOptionPackage where Option.factory = Factory[0].name }}
    - {{ options[1] from any class derived from AbstractOptionPackage where Option.factory = Factory[0].name }}
    - [...]
{{Factory[1].name}}: # Name of second factory
    - {{ options[0] from any class derived from AbstractOptionPackage where Option.factory = Factory[1].name }}
    - {{ options[1] from any class derived from AbstractOptionPackage where Option.factory = Factory[1].name }}
    - [...]
Colors:
    {{ Export.exterior_colors }}:
        - selected_exterior_colors[0]
        - selected_exterior_colors[1]
        - [...]
    # to be extended with interior_colors.

or as example (should be quite valid YAML):

Filename: vehicle_model_A.yaml

Factory_A:
    - basic_air_conditioning
    - more_chrome
Factory_B:
    - leather_seats
    - best_radio
Colors:
    exterior_colors:
        - green
        - yellow

I can already create some sort of YAML file for download via browser (PyYAML installed :-)): admin.py

from django.contrib import admin
from django.http import HttpResponse
from django.core import serializers

# Register your models here.

from .models import Export, FactoryName, Option, InteriorPackage, ExteriorColor

# admin.site.register(Export)
admin.site.register(FactoryName)
admin.site.register(Option)
admin.site.register(InteriorPackage)
admin.site.register(ExteriorColor)


def export_all_as_yaml(modeladmin, request, queryset):
    response = HttpResponse(content_type="application/yaml")
    //[...]
    serializers.serialize("yaml", to_export, stream=response)
    return response

class ExportFunction(admin.ModelAdmin):
    def exterior_colors_list(self, obj):
        return "\n".join([o.name for o in obj.exterior_colors.all()])

    list_display = [
        'name',
        'exterior_colors_list',
        'interior_package',
        ]
    ordering = ['name']
    actions = [export_all_as_yaml]

admin.site.register(Export, ExportFunction)

But now there're problems. I searched much on the internet but somehow it didn't work.

  1. Couldn't manage to create the queryset/filter. Always error messages that this and that doesn't exist.
  2. When there's a database relationship, only the id of the entry/entries is shown but not the actual name. I tryed that models.Manager class thing but it didn't work somehow (still ids). Of course there were more code lines concerning this than shown here.
  3. "Wrong" YAML format ([0, 1, 2, [...] ...]. That block style would be better for usage with diff etc. There seems to be a PyYAML option but I can't use that in Django without more complicated changes?! Maybe a specially created export function is necesseray? (no re-import into the Django app necessary)
  4. I always want to export all Export entries. But Django avoids calling the function if not at least one entry is selected. To add something like the "add ..." button seems to be more complicated with a custom HTML file? Currently it works for me as it is. So it's not that important.
  • 1
    Welcome to stack overflow! It's hard to answer a question when there's a lot to go through. Could you please trim your question to a minimal complete verifiable example? https://stackoverflow.com/help/mcve – Gavin Achtemeier Jul 15 '17 at 17:34
  • I'd start by [reading the serialization docs](https://docs.djangoproject.com/en/1.11/topics/serialization/) if you haven't already – airstrike Jul 15 '17 at 18:01
  • "Now I would like to create a YAML file which looks roughly like this" that is not a valid YAML file you'll have to quote strings that start with `{{` otherwise the other software will think that are (flow-style) mappings. The other example is quite different. Is the first (non-YAML) supposed to go through a template engine to generate the second? That is quite inflexible when you have to deal with more than just adding a few items to a sequence or key-values to a mapping. – Anthon Jul 16 '17 at 09:36
  • If you want fine control over the output don't use PyYAML, use ruamel.yaml (disclaimer: I am the author of that package), so you can override the style for each individual mapping/sequence/string. – Anthon Jul 16 '17 at 09:38
  • @mini totent I think I already created a minimum example. – softie.coder Jul 16 '17 at 12:02
  • @Andre Terra Without reading the serialization docs I wouldn't came to that code I wrote above :-) – softie.coder Jul 16 '17 at 12:03
  • @Anthon: The YAML file with {{ }} should only explain (to people like you trying to help me) which piece of information should be put where in the YAML file. That's why I also made the YAML example with real content. Ok, maybe I made typos there. But I hope it's possible to understand the general idea :-) I think I'll have a look at ruamel.yaml. Thanks :-) – softie.coder Jul 16 '17 at 12:07
  • @softie.coder Sorry, what got me confused is that it really look a lot like jinja2 file that is pre-processed into YAML. E.g. as in [this](https://stackoverflow.com/q/42083616/1307905) question. Your serializer is primarily meant to create a response, if you want a file then the "normal" PyYAML/ruamel.yaml `dump` routines should be enough for you. – Anthon Jul 16 '17 at 20:42
  • What's `autobuild_binaries` doing in `export_all_as_yaml()` if it never gets used anywhere else? – airstrike Jul 19 '17 at 15:21
  • @AndreTerra Argh, copied from the wrong file. But in the meantime... – softie.coder Jul 22 '17 at 07:50
  • @Anthon In the meantime I looked at it, but didn't understand "you should pin the version being used with “ruamel.yaml<=0.15" (probably because that Python stuff is too new for me). Now I wrote some code by hand which creates that YAML for me. Probably a very ugly solution, but I'll try it that way. Thanks to all here! – softie.coder Jul 22 '17 at 07:52

0 Answers0