Django Crispy Form & <select> tag - html

Is it possible to use crispy-form for < select > tags?
"|as_crispy_field" doesn't help here
template
<select id="food" name="food">
<option value="" selected="selected">---------</option>
{% for object in form.fields.food.choices %}
<option value="{{ object.0 }}" class="{{ object.1 }}">{{ object.2 }}</option>
{% endfor %}
</select>
edit: added Form.py
class MealForm(ModelForm):
def __init__(self, *args, **kwargs):
super(MealForm, self).__init__(*args, **kwargs)
self.fields['food'].choices = [(food.id, food.food_number, food) for food in Food.objects.all()]
self.fields['drink'].choices = [(drink.id, drink.pid, drink.doi, drink.type) for drink in Drink.objects.all()]
class Meta:
fields = (
'title',
'description',
'food',
'drink',
)
model = Meal

you can render individual fields with crispy forms with the crispy_field tag
{% crispy_field form.food %}
or the as_crispy_field filter
{{ form.food|as_crispy_field }}

If you want to pass id and values than you can do like this
FOOD_OPTIONS = [(food.id, food) for food in Food.objects.all()]
class MealForm(ModelForm):
class Meta:
model=Meal
food = forms.ChoiceField(choices = FOOD_OPTIONS, widget=forms.TextInput(attrs={'class': "form-control"}))) # here you can specify class to your select tag or remove it
and instead of looping in template just do like this
{{ form.food|as_crispy_field }}

Related

Auto complete Flask wtforms

I want to auto-update my total amount field using quantity and item price? is there any way to do it using a flask without javascript? I want the total amount to be updated while typing quantity and item price.
class ItemForm(FlaskForm):
item = StringField('Item')
quantity=IntegerField('Quantity')
item_price=IntegerField('Item Price')
class Meta:
csrf = False
class CostumerForm(FlaskForm):
costumer_name=StringField('Costumer Name: ')
item_detail = FieldList(FormField(ItemForm), min_entries=1)
add_item = SubmitField(label='Add Item')
remove_item = SubmitField(label='Remove Item')
total_amount=IntegerField('Total Amount')
paid_amount=IntegerField('Paid Amount')
submit=SubmitField('Submit')
proceed=SubmitField('Proceed')
#app.route('/costumer',methods=['GET','POST'])
#login_required
def costumer():
form=CostumerForm()
if form.add_item.data:
form.item_detail.append_entry()
return render_template('costumer.html', form=form)
if form.remove_item.data:
form.item_detail.pop_entry()
return render_template('costumer.html', form=form)
if form.validate_on_submit():
item=breakdown(form.item_detail.data)[0]
quantity=breakdown(form.item_detail.data)[1]
item_price=breakdown(form.item_detail.data)[2]
amount=breakdown(form.item_detail.data)[3]
total_amount=breakdown(form.item_detail.data)[4]
remaning_amount=total_amount-form.paid_amount.data
sales=Costumer(admin_id=current_user.id,item_id=item,
costumer_name=form.costumer_name.data,quantity=quantity,
item_price=item_price,amount=amount,total_amount=total_amount,
paid_amount=form.paid_amount.data,remaning_amount=remaning_amount)
db.session.add(sales)
db.session.commit()
return redirect(url_for('salesvoucher'))
return render_template('costumer.html',form=form)
costumer.html
Sales
{{form.hidden_tag()}}
{{form.costumer_name.label}}{{form.costumer_name(class='form-control input-group-ig',placeholder='Costumer Name')}}
Item
Quantity
Item Price
{% for field in form.item_detail %}
{% for f in field%}
{{ f(class='form-control') }}
{% endfor %}
{% endfor %}
{{ form.add_item(class='btn btn-primary') }} {{ form.remove_item(class='btn btn-danger') }}
{{form.proceed(class='btn btn-primary')}}
```
no way. even when you're updating in only on the frontend, you must use javascript.

How to create a form for feeding multiple object entries based on a query in django?

I am currently working on my college management application, where staff can enter internal marks of students and the student can view their marks. What i am stuck with is, i want a populate a list of forms to fill the internal marks of each student and submit it at once.
I tried modelformset with the code below and it work exactly as below
formset = modelformset_factory(Internal, fields=('student','marks1','marks2','marks3'))
if request.method == "POST":
form=formset(request.POST)
form.save()
form = formset()
return render(request, 'console/academics/internals.html',{'form':form})
For the model
class Internal(models.Model):
student = models.ForeignKey(User, on_delete=models.CASCADE)
subject = models.ForeignKey(Subject, on_delete=models.CASCADE)
marks1 = models.IntegerField(default=0)
marks2 = models.IntegerField(default=0)
marks3 = models.IntegerField(default=0)
marks = models.IntegerField(default=100)
marksob = models.IntegerField(default=0)
def save(self):
self.marksob = (self.marks1 + self.marks2 + self.marks3)/15
return super(Internal, self).save()
I want the form to be rendered in html using <input> and not passing {{form}} in html. And moreover I want the form to display only the entries of particular students based on a query. Can anyone help me on this?
I want the form to display only the entries of particular students based on a query.
As stated in the docs, you can specify a queryset for your formset:
formset = modelformset_factory(Internal, queryset=Internal.Objects.filter(...), fields=('student','marks1','marks2','marks3'))
I want the form to be rendered in html using and not passing {{form}} in html
You can do that by iterating over fields, just like normal forms:
<form method="post"> {% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
{% for field in form %}
{{ field.label_tag }} {{ field }}
{% endfor %}
{% endfor %}
</form>
More details at using the formset in the template.
Edit
If you want to use custom css classes for your form fields, you can do:
<form method="post"> {% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
<div class="...">
{{ form.marks1.errors }}
<label for="{{ form.marks1.id_for_label }}">Your email address:</label>
<input type="number" name="{{ form.marks1.name }}" value="{{ form.marks1.value }}" class="css-class">
</div>
<!-- and for other fields as well -->
{% endfor %}
</form>

How to make option tag in HTML display rows of one column but save values of another from the same table

I am trying to make a calorie counter app using flask/python-anywhere, and part of it is making a drop down menu of foods to choose from. I want the user to be able to see the food name, but when they submit the food, it's the food's calories that I want to be added to the database.
This is the python code for the relevant tables:
class Post(db.Model):
__tablename__ = "posts"
id = db.Column(db.Integer, primary_key=True)
calories = db.Column(db.Integer)
timestamp = db.Column(db.DateTime, index=True, default=datetime.now)
consumer_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=True)
consumer = db.relationship('User', foreign_keys=consumer_id)
class Food(db.Model):
__tablename__ = "foods"
id = db.Column(db.Integer, primary_key=True)
food_name = db.Column(db.String(200))
food_cal = db.Column(db.Integer)
This is the python code for the page:
#app.route("/", methods=["GET", "POST"])
#login_required
def index():
if request.method == "GET":
return render_template("main_page.html", foods=Food.query.all(), posts=Post.query.all(), timestamp=datetime.now())
if not current_user.is_authenticated:
return redirect(url_for('index'))
add_food = Post(calories=request.form["calories"], consumer=current_user)
db.session.add(add_food)
db.session.commit()
return redirect(url_for('index'))
and this is my html code:
<div class="container">
{% for post in posts %}
<div class="row" style="margin-bottom: 1ex">
<div>
You added {{ post.calories }} calories
</div>
<div>
<small>
at
{% if post.timestamp %}
{{ post.timestamp.strftime("%A, %d %B %Y at %H:%M") }}
{% else %}
at an unknown time
{% endif %}
</small>
</div>
</div>
{% endfor %}
{% if current_user.is_authenticated %}
<div class="row">
<form action="." method="POST">
<div class="form-group">
<label for="foods">Food:</label>
<select class="form control" name="food_name">
{% for food in foods %}
<option value = "{{ food.food_name }}" selected>{{ food.food_name }}</option>
{% endfor %}
</select>
<input type="submit" class="btn btn-success" value="Add calories">
</div>
</form>
</div>
{% endif %}
</div><!-- /.container -->
Just to clarify, the foods in the Food table have been added on my end, but I want the foods that users select to be saved as 'calories' in my Post table. Thanks in advance :)
<option value = "{{ food.food_name }}" selected>{{ food.food_name }}</option>
should be
<option value = {{ food.food_cal }} selected>{{ food.food_name }}</option>

Get url argument to process generic views

I would like to write a one-template view, which depending on the url path will show different field of the model. So for instance if path is
http://127.0.0.1:8000/trip/2/1/
I will get second trip from my db (that works), and 1 should give (as html is written) a description field. I don't know how to process this to context_processor in my view. Do you have any ideas?
views.py
class TripDescriptionCreate(LoginRequiredMixin, UpdateView):
model = Trip
template_name = 'tripplanner/trip_arguments.html'
fields = ["description", "city", "country", "climate", "currency", "food", "cost", "comment", "accomodation",
"car", "flight", "visa", "insurance", "remarks"]
context_object_name = 'trips'
success_url = '/'
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
trip_arguments.html
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">{{ trips.tripName }}</legend>
{% if field_id == 1 %}
{{ form.description|as_crispy_field }}
{% elif field_id == 2 %}
{{ form.city|as_crispy_field }}
{% endif %}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Update</button>
</div>
</form>
urls.py
path('trip/<int:pk>/<int:field_id>', TripDescriptionCreate.as_view(), name='trip-fullfill'),
So I came up with this idea. In my html I added these lines:
{% url 'trip-fullfill-description' pk=trip.pk as description_url %}
{% url 'trip-fullfill-city' pk=trip.pk as city_url %}
{% if request.get_full_path == description_url %}
{{ form.description|as_crispy_field }}
{% elif request.get_full_path == city_url %}
{{ form.city|as_crispy_field }}

How to access and make use of html data in django?

I am having a hard time figuring out the right logic for my problem, i have 3 models,
class Item(SmartModel):
name= models.CharField(max_length=64,help_text="Name for this item e.g Hamburger")
price=models.DecimalField(max_digits=9,decimal_places=2)
optionalitems = models.ManyToManyField('optionalitems.OptionalItemCategory',null=True,blank=True)
class OptionalItems(SmartModel):
"""Optional items that belong to an item e.g topping that belongs to a pizza"""
name = models.CharField(max_length=20, help_text="Item name.")
price = models.DecimalField(max_digits=9, decimal_places=2, null=True,blank=True)
class OptionalItemCategory(SmartModel):
"""Category to which optional items belong"""
title = models.CharField(max_length=20,help_text="Category name")
optional_items = models.ManyToManyField(OptionalItems)
in my template,
{%for optionalcategory in optionalcategories %}
<h5 id="blah"> {{ optionalcategory.title}} </h5>
{% for optionalitem in optionalcategory.optional_items.all %}
<ul>
<input type="radio" value="radio" name="optional" value="op"><li id="item_appearence">{{optionalitem.name}}<span> {{optionalitem.price}}</span></li><a/>
</ul>
{% endfor %}
{% endfor %}
So for example an Item like a burrito will have an OptionalItem steak or chicken.I am able to access the Item like so item = get_object_or_404(Item, pk=obj.id) but my problem is i cannot figure out how to capture the OptionalItem. I want to be able to access the OptionalItem, i want to obtain the value of the radio button and its attributes. its kind of tricky.
Your code is inconsistent and that makes it hard to read, understand and work with. Some advice, clean it up. Something like this:
class Category(models.Model):
name = models.CharField(max_length=200)
class Option(models.Model):
name = models.CharField(max_length=200)
price = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True)
class Item(models.Model):
category = models.ForeignKey(Category)
name = models.CharField(max_length=200)
price = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True)
options = models.ManyToManyField(Option)
Than you need a from and a view. As I interpret your question: you want a form to select a option for an Item. So the code below will render all options and the widget RadioSelect() lets the user select one item. But why use radiobuttons? If an Item has a relation to one Option, than the Item model should have a foreignKey not M2M!
Form:
class ItemForm(ModelForm):
options = forms.ChoiceField(widget=forms.RadioSelect())
class Meta:
model = Item
fields = ( 'options', )
View:
from django.shortcuts import render
from django.http import HttpResponseRedirect
def your_view(request, id):
item = Item.objects.get(pk=id) # Your item object.
if request.method == 'POST': # If the form has been submitted...
form = ContactForm(request.POST) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
# Process the data in form.cleaned_data
options = form.cleaned_data['options']
# ...
return HttpResponseRedirect('/thanks/') # Redirect after POST
else:
form = ArticleForm(instance=article)
return render(request, 'contact.html', {
'form': form,
})
Template:
{% for obj in item.options_set.all %}
{{ obj.name }} {{ obj.price }}
{% endfor %}
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
I dind't test the code. But this should get you started. The documentation is your friend:
https://docs.djangoproject.com/en/1.5/topics/forms/
https://docs.djangoproject.com/en/1.5/#forms
In your template, you can simply render the price. I'd write a method in the Item model, that formats the OptionalItems the way you like.
i.e.
class Item(SmartModel)
...
def get_optional(self):
return ','.join([a.optionalitems for a in self.optionalitems.all()])
Of course, you should change that method to have it format the way you'd like.
If you pass a queryset of Items to your template, you can do something like the following:
{% for item in items %}
Name: {{ item.name}}
Price: {{ item.price }}
Optional Items: {{ item.get_optional }}
{% endfor %}