Creating list of sub-objects where...

55 views
Skip to first unread message

softie...@gmail.com

unread,
Jul 1, 2017, 3:27:27 AM7/1/17
to Django users
Hi!

Maybe I did something wrong when trying to program with Django in my first thread here. Maybe I did the relationship the wrong way, maybe the docs are containing the wrong words because of my poor database knowledge. But now I came quite far (and hopefully someone can use that code below as example for better understanding of Django) :-)
models.py (don't wonder why multiple colors are allowed):

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")
    for object in Export.objects.all():
        autobuild_binaries = object.filter(AdditionalBinariesGroup)
    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.

Thanks!

Derek

unread,
Jul 2, 2017, 6:09:55 AM7/2/17
to Django users
There is almost too much information here, but not enough actual details on your errors to help someone help you debug your logic.

One thing I can suggest is that the admin functionality should look more like:

class ExportFunction(admin.ModelAdmin):
    ...
    actions = ['export_all_as_yaml', ]  # name is a string

    def export_all_as_yaml(self, request, queryset):  # nest inside the class
       ...

At least, that is how I use actions.  Hope this helps somewhat.

softie...@gmail.com

unread,
Jul 2, 2017, 9:05:01 AM7/2/17
to Django users


Am Sonntag, 2. Juli 2017 12:09:55 UTC+2 schrieb Derek:
There is almost too much information here, but not enough actual details on your errors to help someone help you debug your logic.
 
Thanks for your answer. But I'm afraid that if I post queryset lines I tryed, it will be more misleading than helpful (my knowledge concerning this is currently too poor, maybe I misunderstood what I found on the internet) :-(


One thing I can suggest is that the admin functionality should look more like:

class ExportFunction(admin.ModelAdmin):
    ...
    actions = ['export_all_as_yaml', ]  # name is a string

    def export_all_as_yaml(self, request, queryset):  # nest inside the class
       ...

At least, that is how I use actions.  Hope this helps somewhat.

 Ok, I did. I also tried:


    def export_all_as_yaml(modeladmin, request, queryset):
        response = HttpResponse(content_type="application/yaml")
        for fac in FactoryName.objects.all():
            serializers.serialize("yaml", Export.interior_package.options.objects.filter(FactoryName__name=fac).all(), stream=response)
        return response

Result:
'ForwardManyToOneDescriptor' object has no attribute 'options'
[...]
in line
serializers.serialize("yaml", Export.interior_package.options.objects.filter(FactoryName__name=fac).all(), stream=response)

Thanks for any suggestions!
Reply all
Reply to author
Forward
0 new messages