Django Model - special characters in field name - django

I'm creating model for my app. Unfortunately I'm working with measurements units like km/h, kg CO2/ton, heat content (HHV) - 30 different units at all. I don't know how to save it properly in django model or maybe in serializer to make it display proper unit name, including "/", " ", "(" in REST Responses. Also I will be importing data through django-import-export module so it should recognize excel columns which will be named like actual unit name.
For example:
class Units(models.Model):
km_h = models.FloatField(default=-1, null=True)
kg_co2ton = models.FloatField(default=-1, null=True)
and I would like to have this data available in the following form:
class Units(models.Model):
km/h = models.FloatField(default=-1, null=True)
kg co2/ton = models.FloatField(default=-1, null=True)
How to write model and/or serializer to make it work and look good?

For django-import-export, you can use the column_name of the Field class to declare the column name to match your Excel import spreadsheet:
class UnitsResource(resources.ModelResource):
km_h = Field(attribute='km_h', column_name='km/h')

Related

Lookup that spans across 3 tables in Django

I want to do a lookup that spans three model classes. I want to find all the PartListings that match the Specific_part in the ListItem. Say Specific part = Radio, there could be several Radios in the PartListings and I want to return the PartListing id of all of them so that I can get other attributes like quantity.
I have these models:
class SpecificPart(BaseModel):
class PartListing(BaseModel):
specific_part = models.ForeignKey(
SpecificPart, on_delete=models.CASCADE, blank=True, null=True,
related_name="part_listing")
class ListItem(BaseModel):
specific_part = models.ForeignKey(SpecificPart, on_delete=models.CASCADE,
related_name="listitem")
I'm trying to put the lookup under the ListItem class like this:
def item_match(self):
part = self.specific_part
return PartListings.filter(specific_part__specific_part=part)
I tried to set it up as a Lookup that spans relationshipsbut am getting an error that PartListing is not defined. I also suspect that I'm referencing the foreign keys incorrectly. I'm also ok with redefining the models if a One to One would be better.
I am a Django newbie so thanks so much for your help!
You can try like this using reverse relation between SpecificPart and PartListing models:
class ListItem(BaseModel):
...
def item_match(self):
return self.specific_part.part_listing.all()

Import CSV to Postgresql

I am working on a Django based web application.
I am going to import a csv to postgresql database, which has over 100,000 lines, and use it as a database for the Django application.
Here, I've faced two problems.
The field name includes special characters like this:
%oil, %gas, up/down, CAPEX/Cash-flow, D&C Cape,...
1st, How should I define the field name of Postgresql database to import csv?
2nd, After import, I am going to get data through django model. Then how can I define the Django model variable name that includes special characters?
Of course, It's possible if I change the column name of the csv which includes special characters, but I don't want to change it. I want to import original csv without any changes.
Is there any solution to solve this problem?
There are no special characters in your example. At least not any that would be problematic from the python or database point of view.
First of, avoid dubious field names, especially in finance. %oil can mean either oil share, oil margin or something else. Define a model with meaningful names like
class FinancialPeformanceData(models.Model):
oil_share = models.DecimalField(max_digits=5, decimal_places=2)
gas_share = models.DecimalField(max_digits=5, decimal_places=2)
growth = models.DecimalField(max_digits=10, decimal_places=2)
capex_to_cf = models.DecimalField(max_digits=7, decimal_places=2)
... etc.
Then you use copy to import data from CSV as #Hambone suggested. You don't need headers in CSV files.
def import_csv(request):
file = './path/to/file'
with open(file, 'rb') as csvfile:
with closing(connections['database_name_from_settings'].cursor()) as cursor:
cursor.copy_from(
file=csvfile,
table='yourapp_financialperformancedata', #<-- table name from db
sep='|', #<-- delimiter
columns=(
'oil_share',
'gas_share',
'growth',
'capex_to_cf',
... etc.
),
)
return HttpResponse('Done!')

Embed product-variance logic into Django models

I wonder how I would model my Products model to auto-create (and that the admin-App would also understand it) variants of a Product based on it's variant-parts.
My Products have;
Colors
Sizes
and can probably get more features in the future.
How would I model my Product class to generate all variants of the Product?
Say I would create a new Product in Colors Red Blue Green and in Sizes XS S M L XL.
class Product(models.Model):
name = models.CharField(max_length=200)
class Color(models.Model):
product = models.ForeignKey(Product)
name = models.CharField(max_length=200)
class Size(models.Model):
product = models.ForeignKey(Product)
name = models.CharField(max_length=200)
class FutureVariant(models.Model):
product = models.ForeignKey(Product)
name = models.CharField(max_length=200)
# etc.
Now when I would need a smart method that when I would auto-create all color-size-[FUTURE VARIANT] for that product.
So I would tell Django;
Create new Product
In the colors Red Blue Green
In the sizes XS S M L XL
And the Product class would go and produce Products with all possible combinations in the products_product table.
I'm almost sure that this has design flaws. But I'm just curious how to put this logic in the ORM, and not to write weird procedural code, which would probably go against the DRY principal.
In Database logic I would think of something like this;
PRODUCTS
- id
- name
PRODUCTS_VARIANTS_COLORS
- id
- name
- html_code
PRODUCTS_VARIANTS_SIZES
- id
- name
PRODUCTS_VARIANTS_TABLES
- table_name
- table_id
PRODUCTS_VARIANTS
- product_id
- variant_table
- variant_id
This way I could make endless variant tables, as long as I would register them in my PRODUCTS_VARIANTS_TABLES and store their name as relevant. PRODUCTS_VARIANTS would hold all the the variants of the product, including combinations of them all. I am also aiming to have a selection-phase where the user can chose (in a HTML checkbox-list) which variants it does and doesn't want.
The problem (I think) is that this would not really comply with a logic in the ORM.
I don't know if you are asking about alternatives or just looking to make your way work, but what about splitting a product from it's attributes?
So instead of having separate models for attributes, you just have an Attribute model. This way you are future-proofing your database so you can easily add more attributes (like if you have products with a height and width instead of just color or size).
class AttributeBase(models.Model):
label = models.CharField(max_length=255) # e.g. color, size, shape, etc.
...
class Attribute(models.Model):
base = models.ForeignKey('AttributeBase', related_name='attributes')
value = models.CharField(max_length=255) # e.g. red, L, round, etc.
internal_value = models.CharField(max_length=255, null=True, blank=True) # other values you may need e.g. #ff0000, etc.
...
class ProductAttribute(Attribute):
product = models.ForeignKey('Product', related_name='attributes')
It now becomes very easy to create all attributes for a product...
class Product(models.Model):
...
def add_all_attributes(self):
for attribute in Attribute.objects.all():
self.attributes.add(attribute)
now when you use product.add_all_attributes() that product will contain every attribute. AND you can even make it add attributes of a certain AttributeBase
def add_all_attributes_for_base(self, label):
base = AttributeBase.objects.get(label=label)
for attribute in base.attributes.all():
self.attributes.add(attribute)
You could write something as:
class Product(models.Model):
#classmethod
def create_variants(cls):
# compute all possible combinations
combinations = ...
for combination in combinations:
Product.objects.create(**combination)
Creating all the combinations would indeed happen through registering the possible variants and their possible values.
Note that ORM is there to help you map Django objects to database records, it doesn't help you with producing the database records (read: Django models) that you wish to save.

Django admin, many to many field, several duplicate entries

I have a situation where I'm trying to create a quick and easy admin interface for composers to list the instruments in a piece of music. What I am looking for is a single entity, an Instrumentation, which defines a particular combination of instruments. For example, a saxophone quartet might consist of:
Soprano sax
Alto sax
Tenor sax
Baritone sax
but it also might consist of two altos, tenor and bari instread. The problem gets worse when you try to add an entire section (like 1st violins--as many as 18 members).
The initial model I came up with looks like this:
class Work(Post):
authors = models.ManyToManyField(Individual)
title = models.CharField(max_length=255)
subtitle = models.CharField(max_length=255, blank=True)
program_notes = models.TextField(blank=True)
notes = models.TextField(blank=True)
media = models.ManyToManyField('Upload')
class Composition(Work):
instrumentation = models.ForeignKey('Instrumentation')
class Instrumentation(models.Model):
forces = models.ManyToManyField(Instrument)
types = models.ManyToManyField('InstrumentationType')
class InstrumentationType(models.Model):
type = models.CharField(max_length=255)
variation = models.SmallIntegerField(default=0)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
I plan to later map each instrument in the piece to a performer in a rehearsal, concert, etc., so it's more than a simple count that I need. If I were doing this without django (i.e. just SQL and database design), I would have a mapping table with
Instrumentation :
id (int serial PK),
type (FK),
composition_id (FK),
instrument_id (FK)
It looks like Django is creating this exact situation for me in the database, but for some reason the framework needs type, composition_id and instrument_id to be unique together. The admin interface (multiselect box) also makes it clear that having multiple similar entries isn't how the many to many field was designed to work. So how do I achieve this? Is there an established workaround for this?
The chosen answer to this question solves it. I needed to explicitly define the mapping table and then use the admin inline feature to fix the interface.
models.py:
class Instrumentation(models.Model):
forces = models.ManyToManyField(Instrument, through='InstrumentationForces')
types = models.ManyToManyField('InstrumentationType')
class InstrumentationForces(models.Model):
instrument = models.ForeignKey(Instrument)
instrumentation = models.ForeignKey(Instrumentation)
admin.py:
class InstrumentInline(admin.TabularInline):
model = InstrumentationForces
extra = 3
class InstrumentationAdmin(admin.ModelAdmin):
filter_horizontal = ('types',)
inlines = (InstrumentInline,)
admin.site.register(Instrumentation, InstrumentationAdmin)

Figuring out how to design my model and using "through"

I'm trying to figure out how to design my model. I've been going over the documentation, and it ultimately seems like I should be using the "through" attribute, but I just can't figure out how to get it to work how I want.
If someone could take a look and point out what I'm missing, that would be really helpful. I have pasted my model below.
This is what I am trying to do:
1) Have a list of server types
2) Each server type will need to have different parts available to that specific server type
3) The asset has a FK to the servermodel, which has a M2M to the parts specific to that server type.
My question is, how can each "Asset" store meta data for each "Part" specific to that "Asset"? For example, each "Asset" should have it's own last_used data for the part that's assigned to it.
Thanks! :)
class Part(models.Model):
part_description = models.CharField(max_length=30,unique=1)
last_used = models.CharField(max_length=30)
def __unicode__(self):
return self.part_description
class ServerModel(models.Model):
server_model = models.CharField(max_length=30,unique=1)
parts = models.ManyToManyField(Part)
def __unicode__(self):
return self.server_model
class Asset(models.Model):
server_model = models.ForeignKey(ServerModel)
serial_number = models.CharField(max_length=10,unique=1)
def __unicode__(self):
return self.server_model.server_model
EDIT:
Thank you for the help!
I may have not explained myself clearly, though. It's probably my confusing model names.
Example:
ServerModel stores the type of server being used, say "Dell Server 2000".
The "Dell Server 2000" should be assigned specific parts:
"RAM"
"HARD DISK"
"CDROM"
Then, I should be able to create 10x Assets with a FK to the ServerModel. Now, each of these assets should be able to mark when the "RAM" part was last used for this specific asset.
I'm not sure I exactly understand what you want to do, but basically you can solve that with a "through" model, as you expected:
import datetime
class Part(models.Model):
name = models.CharField(max_length=30,unique=1)
class ServerModel(models.Model):
server_model = models.CharField(max_length=30,unique=1)
parts = models.ManyToManyField(Part,through='Asset')
class Asset(models.Model):
server_model = models.ForeignKey(ServerModel)
part = models.ForeignKey(Part)
serial_number = models.CharField(max_length=10,unique=1)
used = models.DateTimeField(default=datetime.datetime.now())
First thing to notice is the relation of the parts to the servermodel using the "through"-model: that way for each Part instance assigned to the "parts"-property of a ServerModel instance a new Asset instance is created (Phew - hope that doesn't sound too complicated). At the time of creation the "used"-property of the Asset instance is set to the current date and time (thats what default=datetime.datetime.now() does).
If you do that, you can then just query the database for the last asset containing your part. That queryset can then be sorted by the "used" property of the Asset model, which is the date when the Asset instance has been created.
ServerModel.objects.filter(parts__name='ThePartYouAreLookingFor').order_by('asset__used')
I'm not absolutely sure if the queryset is correct, so if someone finds huge nonsense in it, feel free to edit ;)
edit:
The models above do not exactly that. But you do not even need a through model for what you want:
class ServerModel(models.Model):
server_model = models.CharField(max_length=30,unique=1)
parts = models.ManyToManyField(Part)
class Asset(models.Model):
server_model = models.ForeignKey(ServerModel)
parts = models.ForeignKey(Part)
serial_number = models.CharField(max_length=10,unique=1)
used = models.DateTimeField(default=datetime.datetime.now())
Basically you can just add assets and then query all assets that have a RAM in parts.
Asset.objects.filter(parts__contains='RAM').order_by('used')
Get the date of the first (or last) result of that queryset and you have the date of the last usage of your 'RAM'-part.