英文:
Automating the creation of a Django model with `IntegerField()` fields from a list of attribute names
问题
以下是您要翻译的内容:
I do have a list of attributes (field names) a model should have. This list contains about 170 entries. The field type of all of them will be IntegerField()
.
I now want to generate a model from this list. So something like:
class MyModel(models.Model):
field_name1 = IntegerField()
field_name2 = IntegerField()
...
but automated by code.
For this I tried the following code:
a_list_of_attr_names = ["field1", "field2", "field3"]
MyModel = type("My Model", (models.Model,), {attr_name: models.IntegerField() for attr_name in a_list_of_attr_names})
which gave me following error:
File "D:\Users\Me\Documents\dev\project\venv\Lib\site-packages\django\db\models\base.py", line 105, in __new__
module = attrs.pop("__module__")
^^^^^^^^^^^^^^^^^^^^^^^
KeyError: '__module__'
So is there another way to create a model from a list of field names?
The background of my question is, that I want to replicate the scheme of the Bundeslebensmittelschlüssel. Basicly this is a database containing hundreds of food items with their corresponding nutritions, vitamins and so on. The nutritions stored in this database for each food item are listed in the linked table. Each entry in this table has the following fields:
short, description, type, length and unit.
Example for the energy of an food item:
short= "GCAL", description= "Energie (Kilokalorien)", type= "Nu", length= 3, unit= "kcal/100 g"
So when I add a new FoodItem
to my database I want it to have fields for all of the nutritions, and I want to be able to give them values. So as the database sheme of the Bundeslebensmittelschlüssel is more or less fixed I first thought about just adding all the nutritions as IntegerFileds
to my FoodItem
model. As I did not want to do it all by hand, I made a list off all the nutritions and asked for the locals()
method. Also, my list actually is a list of dicts for all nutritions so that I can reference for example the unit
of an nutrition from my views
aswell.
[{"id": 4, "short": "GCAL", "description": "Energie (Kilokalorien)", "type": "Nu", "length": 3, "unit": "kcal/100 g"},
{"id": 5, "short": "GJ", "description": "Energie (Kilojoule)", "type": "Nu", "length": 4, "unit": "kJ/100 g"},]
But thinking of it I am not sure if this is the right way to do this. So I also tried to do it all by models.
class FoodItem(models.Model):
name = models.CharField(max_length=255)
class Nutrition(models.Model):
short = models.CharField(max_length=255)
description = models.CharField(max_length=255)
type = models.CharField(max_length=255)
length = models.IntegerField()
unit = models.CharField(max_length=255)
class NutritionDetail(models.Model):
nutrition = models.ForeignKey(
Nutrition, on_delete=models.CASCADE, related_name='nutritions_details')
composition = models.ForeignKey(
FoodItem, on_delete=models.CASCADE, related_name='nutritions_details')
value = models.IntegerField()
I created all the nutrition entrys from the Bundeslebensmittelschlüssel as Nutrition
objects in my database. But then when I create a new FoodItem
, I need to create a new NutritionDetail
object for every Nutrition
object in my database. And if the Bundeslebensmittelschlüssel would change, maybe they drop a nutrition or add alergenes or anything, I can add those entries to my Nutritions
but I would need to add all new entries to my existing FoodItem
manually.
And at the moment I am just confused if I would need to create the NutritionDetails
in my views.py
or admin.py
when creating a new FoodItem
or can I automaticly create NutritionDetails
for each Nutrition
in my database in my models throug an __init__
function in FoodItem
? Or is the method with the static fields in FoodItem
the way to go?
I am confused...
英文:
I do have a list of attributes (field names) a model should have. This list contains about 170 entries. The field type of all of them will be IntegerField()
.
I now want to generate a model from this list. So something like:
class MyModel(models.Model):
field_name1 = IntegerField()
field_name2 = IntegerField()
...
but automated by code.
For this I tried the following code:
a_list_of_attr_names = ["field1", "field2", "field3"]
MyModel = type("My Model", (models.Model,), {attr_name: models.IntegerField() for attr_name in a_list_of_attr_names})
which gave me following error:
File "D:\Users\Me\Documents\dev\project\venv\Lib\site-packages\django\db\models\base.py", line 105, in __new__
module = attrs.pop("__module__")
^^^^^^^^^^^^^^^^^^^^^^^
KeyError: '__module__'
So is there another way to create a model from a list of field names?
The background of my question is, that I want to replicate the scheme of the Bundeslebensmittelschlüssel. Basicly this is a database containing hundreds of food items with their corresponding nutritions, vitamins and so on. The nutritions stored in this database for each food item are listed in the linked table. Each entry in this table has the following fields:
short, description, type, length and unit.
Example for the energy of an food item:
short= "GCAL", description= "Energie (Kilokalorien)", type= "Nu", length= 3, unit= "kcal/100 g"
So when I add a new FoodItem
to my database I want it to have fields for all of the nutritions, and I want to be able to give them values. So as the database sheme of the Bundeslebensmittelschlüssel is more or less fixed I first thought about just adding all the nutritions as IntegerFileds
to my FoodItem
model. As I did not want to do it all by hand, I made a list off all the nutritions and asked for the locals()
method. Also, my list actually is a list of dicts for all nutritions so that I can reference for example the unit
of an nutrition from my views
aswell.
[{"id": 4, "short": "GCAL", "description": "Energie (Kilokalorien)", "type": "Nu", "length": 3, "unit": "kcal/100 g"},
{"id": 5, "short": "GJ", "description": "Energie (Kilojoule)", "type": "Nu", "length": 4, "unit": "kJ/100 g"},]
But thinking of it I am not sure if this is the right way to do this. So I also tried to do it all by models.
class FoodItem(models.Model):
name = models.CharField(max_length=255)
class Nutrition(models.Model):
short = models.CharField(max_length=255)
description = models.CharField(max_length=255)
type = models.CharField(max_length=255)
length = models.IntegerField()
unit = models.CharField(max_length=255)
class NutritionDetail(models.Model):
nutrition = models.ForeignKey(
Nutrition, on_delete=models.CASCADE, related_name='nutritions_details')
composition = models.ForeignKey(
FoodItem, on_delete=models.CASCADE, related_name='nutritions_details')
value = models.IntegerField()
I created all the nutrition entrys from the Bundeslebensmittelschlüssel as Nutrition
objects in my database. But then when I create a new FoodItem
, I need to create a new NutritionDetail
object for every Nutrition
object in my database. And if the Bundeslebensmittelschlüssel would change, maybe they drop a nutrition or add alergenes or anything, I can add those entries to my Nutritions
but I would need to add all new entries to my existing FoodItem
manually.
And at the moment I am just confused if I would need to create the NutritionDetails
in my views.py
or admin.py
when creating a new FoodItem
or can I automaticly create NutritionDetails
for each Nutrition
in my database in my models throug an __init__
function in FoodItem
? Or is the method with the static fields in FoodItem
the way to go?
I am confused...
答案1
得分: 0
以下是翻译好的部分:
可能的想法是与以下内容一起工作:
<pre><code>a_list_of_attr_names = ['field1', 'field2', 'field3']
class MyModel(models.Model):
for item in a_list_of_attr_names:
<b>locals()[item]</b> = models.IntegerField()</code></pre>
话虽如此,如果您需要使用字段名称列表,通常意味着出现了问题,因此可能建模不正确。
请注意,这不会动态更改,因此每次添加项目时,您都需要进行迁移并正确迁移。
英文:
an idea might be to work with:
<pre><code>a_list_of_attr_names = ['field1', 'field2', 'field3']
class MyModel(models.Model):
for item in a_list_of_attr_names:
<b>locals()[item]</b> = models.IntegerField()</code></pre>
That being said, if you need to work with a list of field names, you usually do something wrong, and thus likely the modeling is incorrect.
Note that this will not change dynamically, so each time you add an item, you will need to make a migration and properly migrate.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论