Handling presentation logic in Django templates - django

The description below is heavily simplified - it's only one part of a bigger problem that we are tackling but the innards can be safely left out for this question.
Suppose we have the following models: -
class Item(models.Model):
name = models.CharField(max_length=150)
value = models.DecimalField(max_digits=12,decimal_places=2)
class Person(models.Model):
name = models.CharField(max_length=150)
items = models.ManyToManyField(Item, through='AssignedItem')
class AssignedItem(models.Model):
person = models.ForeignKey(Person)
item = models.ForeignKey(Item)
value = models.DecimalField(max_digits=12,decimal_places=2)
So basically a person may be assigned zero, one, or more items and each assigned item's value may be overridden for a particular person by specifying the new value in the through model.
What we are aiming to achieve is an html table which has all the Item.name as its header row, with one extra column in that header row for Person.name.
Each Person may have a different set of Person.items assigned to them so it is expected that if a Person has not been assigned an Item, the corresponding cell for that Person will be blank (please see attached image).
The question is how to place the correct AssignedItem value in the corresponding column. We have a Queryset of Items that we are looping over in the template to create the header row, and then we have a list of lists containing each person's items. But how do we ensure that the correct AssignedItem is displayed under the corresponding Item header?

You mentioned you are constructing the list in the view,
We have a Queryset of Items that we
are looping over in the template to
create the header row, and then we
have a list of lists containing each
person's items.
When constructing this list, make the list an ordered list, where if a particular value exists, assign it and if it doesnt, then insert None.
ie, the list for Jake should look like [78, 45, None, 94, 72]
Edit:
Since reordering is an issue, use a dictionary with the item as index
ie, the values for Jake should look like {'Item1':78, 'Item2':45, 'Item4':94, 'Item5':72}

Well, the main issue was to ensure that the correct AssignedItem is displayed under the corresponding Item header.
I tried a lot of things in the template, but it did not offer too much room to maneuver. I ultimately created the "table" in the view then passed the string to the template for rendering.

Related

Finding all objects that have the same type object in a ManyToMany relationship

I have a model that has a ManyToMany relationship with itself (a "following" list).
I can pull the list of people any particular person is following (i.e. obj.following.all() ), but I am trying to figure out how to get a list of objects that contain this particular object within THEIR following list. In other words, I have a following list, and now I want to parse a followers list.
I figured it out. If you want to view an inverse list, just set a 'related_name' and call that.
In the case of:
class Person(models.Model){
following = models.ManyToManyField('self', symmetrical=False, related_name='follow_list')
}
A list of people this person is following:
person.following.all()
A list of people that are following this person;
person.follow_list.all()

How to add an element from a looping list to a name of each function?

I am taking machine learning classes and have some questions about the for loop.
for example, I have a list category =["cat","dog","car"]
I want to loop through this category and create a model with name including the element(i.e. model_cat, model_dog, model_car)
for i in category:
model = graphlab.nearest_neighbors.create(xxxxxxx)
in this case, each model has the same name "model". Is there a way to add unique labels to the model? Thanks.
Not sure what you exactly meant by model but looks like you just need another list. Try this.
category = ["Cat","Dog","Car"]
model = []
for i in category:
if i not in model:
model.append('Model_' + i)
print(model)
Output:
['Model_Cat', 'Model_Dog', 'Model_Car']

Displaying 2-dimensional data array in django template

I have a bunch of woods and a bunch of properties, describing the wood. The property of a specific wood is given by Answer (basically answers = woods x properties):
class Wood(models.Model):
desc = models.CharField(max_length=63)
class Property(models.Model):
desc = models.CharField(max_length=63)
class Answer(models.Model):
desc = models.CharField(max_length=255)
wood = models.ForeignKey('Wood', related_name='answers', null=True, default=None)
property = models.ForeignKey('Property', related_name='answers', null=True, default=None)
Now I want to show my data in a table. There is one row for each wood and one column for each property.
My problem starts when I use the first row as header with all the properties (property.desc) and the first column with all the woods (wood.desc). I couldn't find a way to access an Answer for a given Wood and Property from inside the template. This would be easy, if I could access dictionary values by key with the key being a variable - but that's not possible in templates as far as I know.
I did find a way, which turns out increasingly ugly: I can create nested lists in the view and traverse them in the template. I simply rely on the fact that list items stay in order and thus the answers match the header row. It feels wrong to create this intermediate list structure while the actual data structure is as straightforward as this.
I hope someone knows a way to map my data structure directly in a template.

Clean approach to store Key-Value "properties"?

Let say I have one model for cars. Each car has attributes: color, size, weight, etc... I want users to allow the creation of new attributes for each car objects. However I want to share "attributes" so that the attribute "size" only exists once in the db but values exist for each object where users have added them.
My old approach were two models: Car, KeyValue(key: String, value:String) and Car had a 1:m relationship to KeyValue.
Now, to ensure my above constraint I thought of the following:
Three objects: Car, Key, Value
Value(Key: Key)
Car (1:m relation to Value)
However, this reverse approach works very well but does not look "clean" to me. Therefore, I'd like to ask whether a cleaner approach is possbile.
i read this
http://www.craigkerstiens.com/2012/06/11/schemaless-django/
i haven't used this but i think it's ok.
a less complex approach is
django-picklefield
http://pypi.python.org/pypi/django-picklefield/
i hope this can help you
If your "choices" are malleable, i.e. they can be added to, edited, or deleted from, then the choice should be it's own model. For example:
class Color(models.Model):
name = models.CharField(max_length=50)
class Car(models.Model):
color = models.ForeignKey(Color, related_name='cars')
You should have Cars and CarModels
A CarModel has two list of properties. One that has the "PerModel" attributes for all cars of that models (That means all the cars of that model have the same value), and another one (just the names) of the properties that each car can have a different value "PerCar".
CarModel
{
KeyValue(key: String, value:String) propertyValuesPerModel;
List(String) propertyNamesPerCar;
}
Car
{
CarModel model;
KeyValue(key: String, value:String) propertiesPerCar; //Keys can only be those that appear on model.propertyNamesPerCar
}

Multi field and computed value

I need a solution for this problem:
I would like to have MultiField widget for a "value" field. This field should allow to input two values (two input widgets), and user should choose which of these values is to be saved (two checkbox widgets). However, one of these values must be recalculated with respect to other field's value.
I've taken this approach:
a MultiValueField with 4 fields:
class PriceDetailField(MultiValueField):
use_net = BooleanField(required=False)
net_value = DecimalField(required=False, decimal_places=2)
use_gross = BooleanField(required=False)
gross_value = DecimalField(required=False, decimal_places=2)
a MultiWidget:
class PriceDetailWidget(MultiWidget):
use_net = CheckboxInput()
net_value_widget = TextInput()
use_gross = CheckboxInput()
gross_value_widget = TextInput()
and a custom Form...
class PriceModelForm(ModelForm):
value = PriceDetailField()
...which overrides default model form for a model:
class Price(models.Model):
value = models.DecimalField(
max_digits=19,
decimal_places=2,
default=Decimal(0),
)
However, this solution seems to be messed up. In the form, I need to input all subfields (the MultiValueField subfields), otherwise "Please enter value" error appears (even though those fields are marked as required=False). Also,
I must recalculate the mentioned value upon a save, having returned a tuple from the field with information which checkbox was checked and the corresponding text value, then replace the tuple with the decimal value in clean_value method of form (also, saving the checkboxes state in temporary fields....). I think such a design is very weak.
The form should work both on its own and as inline (this means, the value of the field which is used to calculate the returned value can or cannot change during save).
Is such a thing even possible?
And the root of the problem: I want to store prices of items as net prices, but I would like to allow users to input them as net or gross prices, and then recalculate gross price to net price with respect to product's VAT tax level (since VAT is assigned to product or service, not to the price). A product can have many prices, so a price is backlinked to the product by a foreign key.
Cheers,
Tomek
The feature you're looking for on a MultiValueField (allowing the sub-fields to be required or not individually) is logged as a feature request on Django.
You could probably fix this for now by subclassing MultiValueField with a rewritten clean method based on the original and following suggestions from the bug report. You're not going to have a lot of the original MultiValueField left by that point though, and if you do, you should submit your patch to Django and put a note on the bug.
Ignoring for a moment the requiredness thing, have you written a compress method on your PriceDetailField? What does it look like? This is where you should be doing the work to turn your four sub-fields into a single field to save.