django filter on max_length - python

Hi is there a way to filter on field attributes instead of field values in Django?
For example, for my GUI layout i want to know the ordering of fields ordered by max_length. My model:
class Person(models.Model):
name1 = models.CharField(max_length=220, default="")
name2 = models.CharField(max_length=90, default="")
name3 = models.CharField(max_length=30, default="")
name4 = models.CharField(max_length=130, default="")
name5 = models.CharField(max_length=10, default="")
I want to be able to find the length of the longest CharField in my model, in this case 220. How can i do that?
This is just an simplified example, but is similar to the functionality i need. To give insight in the real-world situation i am facing: I added a custom attribute to my model "gui_serial_number", I have partially static models with fields like:
a = CharField(gui_serial_number=10...)
b = CharField(gui_serial_number=20...)
....
n = CharField(gui_serial_number=50...)
I made an dynamic interface in which Fields can be dynamically added to the model (with type() and add_to_class() etc), and the user can give the place in the GUI where the field should be placed. I want to be able to automagically define the gui_serial_number to be "max+10" when no gui_serial_number is given.

Maybe it's not beautiful, but to find the length of the longest CharField of Person you can do this:
from operator import attrgetter
sorted([field for field in Person._meta.fields if isinstance(field, models.CharField)],
key=attrgetter('max_length'))[-1].max_length

Related

Getting rid of duplicates when sorting by 2 related fields in Django

I'm having difficulties sorting data from a stock management database in a Django query. The data has to be ordered by 2 related fields, and this results in duplicates. I understand that this is expected behavior, but I can't seem to find an elegant way to get rid of those duplicates.
models.py:
class Attribute(models.Model):
name = models.CharField(max_length=100)
class ProductType(models.Model):
name = models.CharField(max_length=100)
attributes = models.ManyToManyField(Attribute, through='ProductTypesAttributes')
class ProductTypesAttributes(models.Model):
product_type = models.ForeignKey(ProductType, on_delete=models.CASCADE)
attribute = models.ForeignKey(Attribute, on_delete=models.CASCADE)
class AttributePossibleValues(models.Model):
attribute = models.ForeignKey(Attribute, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
sorting_value = models.IntegerField(null=True)
class Meta:
ordering = ('sorting_value', )
class Product(models.Model):
product_type = models.ForeignKey(ProductType, on_delete=models.CASCADE)
attributes = models.ManyToManyField(Attribute, through='ProductAttributes')
price = models.DecimalField(max_digits=8, decimal_places=2)
class ProductAttributes(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
attribute = models.ForeignKey(Attribute, on_delete=models.CASCADE)
value = models.ForeignKey(AttributePossibleValues, on_delete=models.CASCADE, null=True)
The query which is returning duplicates (views.py):
product_type = ProductType.objects.get(pk=data['product_type_id'])
queryset = Product.objects.filter(product_type=product_type)
queryset = queryset.order_by('productattributes__attribute__name','productattributes__value__sorting_value')
For example:
A specific red sweater made out of wool, is represented by a Product instance. This instance is linked to 2 Attribute instances (color and material) through a many-to-many intermediary table. This intermediary table also links the attributes to the correct values for these attributes (red and wool).
Now I want to generate a list with the prices of all sweaters. I want this list to be sorted. I want to see the cotton sweaters first, and then the sweaters made out of wool. And those cotton and wool sweaters should also be sorted by their color, so the user sees prices of the blue sweaters before those of the red sweaters.
So I use the query above, and each sweater is shown twice. This is expected: I'm trying to order a single object with respect to two different values (material and color). But I need each sweater to be shown only once.
I've tried:
I found similar questions (such as this one) in which the issue was fixed by annotating the queryset and then sorting by the annotated value. But I can't think of something to annotate my query with, that would solve my problem.
I can't use .distinct() because I'm using a mySQL database.
I've worked around this issue by manually filtering out duplicate pks. But I'm still interested in a more elegant solution.

Not sure I understand dependancy between 2 django models

I am struggling to understand django models relationship.
I have this arborescence:
A train have cars, and those cars are divided into parts. Then those parts all contains different references.
Like, for exemple, all the trains have the 6 cars, and the cars 6 parts. Each part have x reference to be associated.
I would like to use all of them in a template later on, where the user can select the train, the car and the part he worked on, then generate a table from his selections with only the references associated to the parts he selected.
It should update the train and the car (I'm trying to update a stock of elements for a company)
I dont really understand which model field give to each of them. After checking the doc, Ive done something like this but i am not convinced:
class Train(Car):
train = models.CharField(max_length=200)
id = models.CharField(primary_key='True', max_length=100)
selected = models.BooleanField()
class Meta:
abstract = True
class Car(Part):
car = models.CharField(max_length=200)
id = models.CharField(primary_key='True', max_length=100)
selected = models.BooleanField()
class Meta:
abstract = True
class Part(Reference):
part = models.CharField(max_length=200)
id = models.CharField(primary_key='True', max_length=100)
selected = models.BooleanField()
class Meta:
abstract = True
class Reference(models.Model):
reference = models.CharField(max_length=200)
id = models.CharField(primary_key='True', max_length=100)
selected = models.BooleanField()
def __str__(self):
return self.reference
Can someone please help me understand this so I can do well ? Thanks!!
1-)if you add abstract = True in your Model Meta class, your class doesn't created on database as a table. If you store data for any class, you mustn't define abstract = True.
2-)For relations, you can use models.ForeignKey . If you add a class into brackets of another class, it names: inheritance.(You can think like parent-child relation). In database management, we can use foreignkey for one-to-many relationship.
3-)In Django ORM, id field automatically generated. So you don't need to define id field.
If I understand correctly, also you want to store parts of user's selected.
So, your model can be like that:
class Train(models.Model):
name = models.CharField(max_length=200) # I think you want to save name of train
class Car(models.Model):
train = models.ForeignKey(Train,on_delete=models.Cascade)
name = models.CharField(max_length=200)
class Part(models.Model):
car = models.ForeignKey(Car,on_delete=models.Cascade)
name = models.CharField(max_length=200)
class Reference(models.Model):
part = models.ForeignKey(Part,on_delete=models.Cascade)
name = models.CharField(max_length=200)
def __str__(self):
return self.reference
#addtional table for storing user's references
class UserReference(models.Model):
user = models.ForeignKey(User,on_delete=models.Cascade)
reference = models.ForeignKey(Reference,on_delete=models.Cascade)
name = models.CharField(max_length=200)
With this definitions, you can store user's definition on UserReference table. And with Django Orm, you can access train object from UserReferenceObject.
#user_reference: UserReference object like that result of UserReference.objects.first()
user_reference.reference.part.car.train.name

Using a class field in another fields

I have a field in a class that depends on another field in the same class but I have a problem to code:
class myclass(models.Model):
nation = [('sp', 'spain'), ('fr', 'france')]
nationality = models.CharField(max_length=2, choices=nation)
first_name = models.CharField(max_length=2, choices=name)
I want to put name = [('ro', 'rodrigo'), ('ra', 'raquel')] if nation = spain and name = [('lu', 'luis'), ('ch', 'chantal')] if nation = france.
How I can do that? Thanks!
I think what you want to do is change the view that the user sees. What you have above is the underlying DB model which is the wrong place for this sort of feature.
In addition (assuming this is a web application), you will probably need to do it in Javascript, so you can change the set of allowed names as soon as the user changes the nationality field.

How to create django database model that "knows" what kind of category it is?

In Django, I have the following models.py
class Product(RandomPrimaryIdModel):
title = models.CharField(max_length=20, blank=True, null=True)
price = models.CharField(max_length=20, blank=True, null=True)
condition = models.CharField(max_length=20, blank=True, null=True)
class Mattress(Product):
length = models.CharField(max_length=50)
size = models.CharField(max_length=5)
class Pillow(Product):
shape= models.CharField(max_length=50)
comfort= models.CharField(max_length=5)
The idea is that there's a "product" model and several "product_type" models. I'm trying to create a database scheme that relates the two. The end goal is so that when I given access to a primary id for an object whose product_type is unknown, I can simply query/filter that object to find out what the product_type is of the object.
I know that sounds a bit confusing, but how would I go about implementing the correct way? The current scheme (the one above) is not the correct solution I believe.
According to the docs on multi-table inheritance you can reference the lowercase name of the model. In your case to find out the "product type" you'd do something like:
product = Product.objects.get(id=12)
try:
mattress = product.mattress
is_mattress = True
except Mattress.DoesNotExist:
is_mattress = False
You could abstract this out to a helper method that would do the tests for you and return the type as a string or enum of some sort.
If you have a reference to an object, can't you use something like:
p = Product.objects.get(id=1)
class_of_p = str(p.__class__)
and then parse the resulting string
"<class 'whatever.models.Pillow'>"
to find what you need? Apologies if I'm missing something.

Django - storing logical tests as records

I'm working on a Gran Turismo 5 Django application. Here's a very simplified data model:
class Event(models.Model):
name = models.CharField(max_length=256, unique=True)
class EventCriteria(models.Model):
name = models.CharField(max_length=256, unique=True)
events = models.ManyToManyField(Event)
test = ???
class Country(models.Model):
name = models.CharField(max_length=256, unique=True)
class Make(models.Model):
name = models.CharField(max_length=256, unique=True)
country = models.ForeignKey(Country)
class Car(models.Model):
name = models.CharField(max_length=256, unique=True)
make = models.ForeignKey(Make)
class Setup(models.Model):
name = models.CharField(max_length=256, unique=True)
car = models.ForeignKey(Car)
horsepower = models.IntegerField()
For example, a given event might have the criteria 'Country = Italy'. When applied against the model above, that would require a test like the following:
setup.car.make.country.name == u'Italy'
Does anyone have a good framework for how I might structure the EventCriteria model (especially the 'test' field or fields') to make a) storing these tests and b) applying them as filters in future views possible?
Thanks,
Mike
It's not clear on why your "test" isn't a simple boolean field. The question is confusing.
I'm assuming that really want a persistent filter, since that's often requested.
A Django filter is a dictionary.
SomeModel.objects.filter( column=value, column__contains=value )
SomeModel.objects.filter( **{'column':value, 'column__contains':value} )
You can do this to persist your "test".
Convert your "filter" expression to a dictionary.
JSON-encode the dictionary as a BLOB
Save it.
You can apply your test as follows.
Get the filter BLOB
JSON-decode the dictionary
Use the dictionary in a filter for the appropriate class.

Categories