Saving the order of items - python

My model:
class Category(models.Model):
name = models.CharField(max_length=50, unique=True)
order = models.SmallIntegerField()
My template:
{% for c in categories %}
{{ c }} -- <input type="text" name="order[{{ c.id }}]" value="{{ c.order }}">
Submit Button
{% endfor %}
My view:
def category_order(request):
print request.POST
print request.POST.getlist('order[]')
Output:
<QueryDict: {u'order[3]': [u'1'], u'order[1]': [u'1'], u'order[5]': [u'2'], u'order[4]': [u'33'], u'order[2]': [u'2'], u'order[6]': [u'3'], u'csrfmiddlewaretoken': [u'4XjehEwMdNK032342JkYJvBJabunKB'], u'order-btn': [u'order']}>
[]
So my question is how can I loop over every order[N] and get the category ID and its new order value to save it to the database?

Using dict comprehension:
orders = {name.split('[')[1].split(']')[0]: request.POST[name]
for name in request.POST if name.startswith('order[')}
# `orders` is not a dictionary maps `id`s to `order`s.
# Do something with `orders`.
Or using simple for loop:
for name in request.POST:
if not name.startswith('order['): continue
id_ = name.split('[')[1].split(']')[0]
order = request.POST[name]
# Do something with `id_`, `order`

If you are looking at having ordered objects, there is a library, django-ordered-model , that can take care of that. That includes a good, drag-and-drop admin view. For example:
from django.db import models
from ordered_model.models import OrderedModel
class Category(OrderedModel):
name = models.CharField(max_length=50, unique=True)
class Meta(OrderedModel.Meta):
pass

Related

Django hide field from forms and add automatically field

I want to add to the cart the actual product I'm in (product_detail.html).
So in the product_unit, is just needed to specify the quantity of the product.
Anyway I can't make the unit_product, automatically add the actual product I'm in.
forms.py
class Product_unitForm(forms.ModelForm):
class Meta:
model = Product_unit
fields = [
'product',
'quantity',
]
widgets = {'product': forms.HiddenInput()}
I hide the product from the template, because it is just the actual product, no need to specify.
views.py
def product_detail(request, id_category=None,id_product=None):
actual_product = Product.objects.get(id = id_product)
#Has an actual customer
#FORM
form_product_unit = Product_unitForm(request.POST or None)
form_product_unit.fields['product'] = actual_product # I try to add the product this way
if form_product_unit.is_valid():
instance_product_unit = form.save(commit=False)
instance_product_unit.product.save()
last_order = Order.objects.last()
is_buying = False
if(last_order.status == "en curso"):
is_buying = True
context = {
"Product" : actual_product,
"Is_buying" : is_buying,
#FORMS
"form_product_unit" : form_product_unit,
}
return render(request, "shopping/product_detail.html", context)
I want to manually from the views, add the product field of product_unit to the actual product it has (actual_product)
template
<img src="{{Product.image.url}}"/>
<h1>{{Product.title}}</h1>
<form method="POST" action="">{% csrf_token %}
{{ form_product_unit.as_p }}
<input type="submit" value="Add" />
</form>
In your views.py file I think you just need to make two changes
def product_detail(request, id_category=None,id_product=None):
actual_product = Product.objects.get(id = id_product)
form_product_unit = Product_unitForm(data=request.POST or None,
initial={'product': actual_product})
And also remove the line form_product_unit.fields['product'] = actual_product. You might need to play around with the initial dictionary a bit to get it to bind the correct value to the field but that's the general idea. The related section in the docs is https://docs.djangoproject.com/en/1.9/ref/forms/api/#dynamic-initial-values

How to parse out {'value__avg': 46.26524716693248} 'value_avg' when using aggregate(Avg()) in django

I am using django here is my model:
class Location(models.Model):
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=50)
altitude = models.IntegerField(max_length=10000)
area = models.ForeignKey('Area')
def __str__(self):
return str(self.area) + ':' + str(self.name)
#measurement.id value date location
class Measurement(models.Model):
id = models.IntegerField(primary_key=True)
value = models.FloatField(max_length=50)
data = models.DateTimeField()
location = models.ForeignKey('Location')
def __str__(self):
return "measurement#"+str(Location.objects.filter(id=self.id))
My HTML page is showing {'value__avg': 46.26524716693248} when it should just show 46.265.
Heres my function:
#property
def average_measurement(self):
locations = Location.objects.filter(area__name=self.name)
return Measurement.objects.filter(location__in=locations).aggregate(Avg('value'))
so how do I get the ugly part out?
aggregate() returns a dictionary where the key is combined from the grouping keys and grouping function name, you can just get the value by key:
return Measurement.objects.filter(location__in=locations).aggregate(Avg('value'))["value__avg"]
Or, if needed, you can also do that in the template using the dot-notation:
{{ obj.average_measurement.value__avg }}
You can also preset the key name with your own value:
return Measurement.objects.filter(location__in=locations).aggregate(my_average=Avg('value'))
Then, you would access it as:
{{ obj.average_measurement.my_average }}
That's not the ugly part, it's expected output and you need to understand what does the output mean. When you do django Aggregation, it returns a dictionary-like object with your aggregation criteria as keys and results as values.
What you need to do is to access it like a dictionary in template to extract the values:
{% for item in items %}
{{ item.value__avg|floatformat:3 }}
{% endfor %}
Check django doc about what is the lookup sequence for dot in template.
Also checkout django doc about aggreate function call.
Also checkout django doc about floatformat template filter.

How do I map WTForms field for a db.Enum model on Flask-SQLAlchemy model?

Working with the following model:
class Recipe(db.Model):
__tablename__ = 'recipe'
__searchable__ = ['description']
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(128), index=True, unique=True, nullable=False)
description = db.Column(db.String(128))
style = db.Column(db.Enum('fried', 'baked', 'roasted', 'mixed', name='cooking_style'))
type = db.Column(db.Enum('breakfast', 'lunch', 'dinner', 'snack', 'sauce', 'bread', 'dessert', name='recipe_type'))
And the following:
form = CreateRecipeForm()
return render_template('create_client_recipe.html', form=form, client=c, recipe=r)
How do I represent style & type (both db.Enum fields) as a select field in the WTForm?
Don't know if you need or not but I'm working with Flask-SQLAlchemy, I'm still a beginner, but I hope this can help you basically I created an Enum called state which has value 'Active' and 'Inactive', and I wanted to put this values in a form but I wanted to get the values from the database.
My model this one:
class StationhasBots(db.Model):
"Many to Many table one raio station will have many functions"
__tablename__ = 'station_has_bots'
fk_radio_station_id = db.Column(db.ForeignKey('radio_station.id'), primary_key=True)
fk_bot_functions_id = db.Column(db.ForeignKey('bot_functions.id'), primary_key=True)
#Function is active or not
state = db.Column(db.Enum('Active','Inactive',name='estado'),nullable=False)
#In which time it will run
run_frequency = db.Column(db.String(STRING_LEN),nullable=False)
next_run = db.Column(db.DateTime(timezone=True),nullable=False)
#Source to fetch information
source = db.Column(db.String,nullable=False)
#path to the file that will be executed to pull info.
path = db.Column(db.String,nullable=True)
function_of_bots = db.relationship("BotsFunctions", backref=db.backref('function_from_bots'))
This is my form:
class AddBotForm(Form):
station = QuerySelectField(query_factory=all_stations, allow_blank=False, blank_text='- select station-')
function = QuerySelectField(query_factory=all_bot_functions, allow_blank=False, blank_text='- select function-')
#state = SelectField(choices=[('active', 'Active'), ('inactive', 'Inactive')])
state = SelectField(choices=[(g, g)for g in StationhasBots.state.property.columns[0].type.enums]) #Get the state from Station_has_Bots Table.
next_run = DurationField(description=_("Duration , in HH:MM(:SS)"))
run_frequency = HiddenField()
source = StringField()
path = StringField()
submit = SubmitField(_('Save'))
In this form you can see that in the state field I run a query, this query will get the Enum called state that was created when I created the database.
To render the form I just did this in my views
#radio.route('/bots/add/', methods=['GET', 'POST'])
#login_required
def bot_function_add():
"""Renders the form"""
form = AddBotForm(request.form)
program = None
return render_template('radio/bot.html', program=program, form=form)
And then in templates did this
<h2>{{ _('Add') }} {{ _('Bot') }}</h2>
<form method="POST" action=""/>
{{ form.hidden_tag() }}
{{ render_field(form, form.station) }}
{{ render_field(form, form.function) }}
{{ render_field(form, form.next_run) }}
{{ render_field(form, form.state) }}
{{ render_field(form, form.source) }}
{{ render_field(form, form.path) }}
{{ render_field(form, form.submit) }}
</form>
I think in your case something like this may work for you.
Type = SelectField(choices=[(g, g)for g in Recipe.type.property.columns[0].type.enums])
First g -> Stays for value (in "HTML code")
Second g -> Is what will be presented to the user.
And then to render the form in your create_client_recipe.html file
you just need to do something like
{{ render_field(form, form.Type) }}
I know that six months have past since your post hope this can help some other people.

Creating a simple django form

I am new to django and and I'm trying to use forms.I want to create a form with two CharFields. Here is where I am so far -
forms.py
from django import forms
class NameForm(forms.Form):
key = forms.CharField(label='Enter Key:', max_length=2)
value = forms.CharField(label='Enter Value:', max_length=4)
template.html
<form action="/new-page/" method="GET">
{{ form }}
<input type="submit" value="Submit" />
</form>
What I want is to take the data in this form and simply use that data in my function myfunc
views.py
def myfunc(request,id):
key = request.GET.get('key')
value = request.GET.get('value')
where id is the id of the page where the form appears like so url/places/1/
I want the action to send the id and the key,value pair to the function to use on submit.Validation is not required. Can someone help me understand the concept here.
Your views.py should look like:
def myfunc(request, id):
form = NameForm(request.GET or None)
if form.is_valid():
key = form.cleaned_data['key']
value = form.cleaned_data['value']
# do something with key and value

setting help_text for each choice in a RadioSelect

I can set the help_text attribute on any form field, but is it possible to set help_text on the choices used for a RadioSelect()?
I'd looking for a clean way to show some help information under each radio button.
Below is the code for the model and the form, I can render the name attribute in a template with the label, input element and help text. I'd also like to be able to render membership_type attribute with a label ('Membership Type'), radio buttons ('open membership' and 'closed membership'), and help text associated to each radio element ('anyone can join this group' and 'only select members can join this group').
class Group(models.Model):
MEMBERSHIP_CHOICES = (
('O', 'Open membership'),
('C', 'Closed membership'),
)
name = models.CharField(max_length=255)
membership_type = models.CharField(max_length=1, choices=MEMBERSHIP_CHOICES, default="O")
class GroupForm(forms.ModelForm):
name = forms.CharField(label="Group name", help_text="Enter a name for your new group")
class Meta:
model = Group
widgets = { "membership_type": forms.RadioSelect }
#Rishabh is correct but I'll elaborate further as, at first glance, it doesn't appear to be the solution, although it is; or, at least, it can be kludged to get a useful effect without having to dive too deep into django forms.
The second element of the tuple is presented inside the "label" tag - so any 'inline elements' are permissible; for example:
The desired result
Or something like it
<ul>
<li><label for="id_ticket_0">
<input type="radio" id="id_ticket_0" value="PARTTIME" name="ticket">
<em>Part Time</em> Valid on Friday Night and Saturday Only
</label></li>
<li><label for="id_ticket_1">
<input type="radio" id="id_ticket_1" value="DAYTIME" name="ticket">
<em>Casual</em> Valid on Saturday Only
</label></li>
<li><label for="id_ticket_2">
<input type="radio" id="id_ticket_2" value="EARLYBIRD" name="ticket">
<em>Early Bird</em> Valid on Friday, Saturday, and Sunday. $15 discount for booking before 1am January 3rd, 2011
</label></li>
</ul>
The simple example
The trick is to "mark_safe" the content of the description then stuff whatever you need into:
from django.utils.safestring import mark_safe
choices = (
('1', mark_safe(u'<em>One</em> | This is the first option. It is awesome')),
('2', mark_safe(u'<em>Two</em> | This is the second option. Good too.'))
)
The complex example
So in this example we:
assemble the choices into a list (any iterable structure will do)
pass the structure to the form's init to create our radio options on the fly
use a comprehension list to create an extended description for each radio option
The data structure:
Tickets are my own classes and they have attributes:
tickets.code - as in a ticket code
label - a pithy short description
help - a longer description
But more about that later. First lets create some instances:
from mymodule import ticket
# so lets create a few
fulltime = ticket('FULLTIME',160,'Full Time',
"Valid Monday to Friday inclusive")
parttime = ticket('PARTTIME',110,'Full Time',
"Valid outside of business hours only")
daytime = ticket('DAYTIME',70,'Day Time',
"Valid only on weekends and public holidays")
# and put them together in a list any way you like
available_tickets = [fulltime, parttime, daytime]
# now create the form
OrderForm(tickets=available_tickets)
That probably happened in your view code. Now to see what happens in the form
class OrderForm(ModelForm):
def __init__(self, *args, **kwargs):
self.tickets = kwargs.pop('tickets')
super(OrderForm, self).__init__(*args, **kwargs)
choices = [(t.code, mark_safe(u'<em>%s</em> %s' % (t.label, t.help)))
for t in self.tickets]
self.fields['ticket'] = forms.ChoiceField(
choices = choices,
widget = forms.RadioSelect()
)
For others coming across this 10+ years later, I was able to do this by creating a custom widget that overrides the default template for radio buttons, and passing custom attributes to it.
# Custom widget
class RadioSelectHelpTextWidget(forms.RadioSelect):
option_template_name = 'custom_templates/forms/radio_option_help_text.html'
# Form class that calls widgets, passed custom attributes to widget
class TemplateCreateForm(ModelForm):
created_by = forms.ModelChoiceField(required=False,queryset=User.objects.none())
class Meta:
model = Template
fields = ['name', 'type', 'created_by']
widgets = {
'name': forms.TextInput(attrs={'class': 'input'}),
'type': RadioSelectHelpTextWidget(
attrs={
'help_text': {
'custom': 'This is custom help text.',
'html': 'This is help text for html.'
}
}
)
}
Template for custom radio buttons (custom_templates/forms/radio_option_help_text.html)
{% load custom_template_filters %}
{% if widget.wrap_label %}
<label{% if widget.attrs.id %} for="{{ widget.attrs.id }}"{% endif %}>
{% endif %}
{% include "django/forms/widgets/input.html" %}
{% if widget.wrap_label %}
{{ widget.label }}
{% if widget.attrs.help_text %}
{% if widget.value in widget.attrs.help_text %}
<p class="is-size-7">
{{ widget.attrs.help_text|dict_get:widget.value }}
</p>
{% endif %}
{% endif %}
</label>
{% endif %}
The result:
Assuming you're using RadioSelect as a widget for forms.ChoiceField, you can do something like:
choices = (('1', 'First help_text here'),
('2', 'Second help_text here'),
('3', 'Third help_text here'),
)
class MyForm(forms.Form):
...
choice = forms.ChoiceField(widget = RadioSelect, choices = choices)
This isn't a strict use of help_text but it should get the job done in most cases.

Categories

Resources