Get related ID through formset - python

I have an inline formset which is working fine. There are a number of select boxes in the formset that lets you pick from various options in related tables.
QuantityFormSet = inlineformset_factory(Option, Quantity, fields=('item', 'number','area'),extra=1)
Item and Area are related tables.
I want to set up a button inline with the form that let's the user click through to edit these two objects.
So, for example, I want to achieve something like.
{% for form in quantityForm %}
{{ form.item }}
<i class="fas fa-edit"></i>
{{ form.number }}
{{ form.area }}
{{ form.DELETE }}
{% endfor %}
However form.item.id isn't valid.
How do I get the ID for form.item (which is a select box)?

Have you tried {{ form.instance.item.id }}?

Related

Single FlaskForm rendered multiple times on one page using FOR loop

I'm making an application where I need to render identical forms multiple times on one page (number of forms might be from 1 to 20). In the video below I'm using simple for loop over a range from 0 to 5, just for a test. When I input data into the first form and submit it, all data duplicates to other forms but I need the user to submit data of each form independently from others. In other words, the user can fill in data in some forms (in 1, in 2 or in all forms) and submit those data separately.
Youtube video showing my problem
I have tried to change submit buttons manually with unique ids and names for each form but this didn't help.
I also tried to use Field Enclosures from WTForms but this also didn't help.
Here is my FlaskForm I haven't included all fields to save space
class EnvelopeForm(FlaskForm):
vme_name = StringField('VME')
outside_diameter = DecimalField('OD', validators=[DataRequired()])
submit = SubmitField('build envelope')
Here is my view handler
#app.route('/bokeh', methods=['GET', 'POST'])
def nonuniform_ellipse():
form = EnvelopeForm()
if form.validate_on_submit():
envelope = Envelopes(vme_name=form.vme_name.data,
outside_diameter=form.outside_diameter.data)
db.session.add(envelope)
db.session.commit()
return render_template('vme.html', form=form)
Here is HTML I haven't included all fields to save space.
{% for i in range(0, 5) %}
<form method="POST" action="" name="{{ i }}">
{{ form.hidden_tag() }}
<div>
{{ form.vne_name.label }}
{{ form.vme_name }}
</div>
<div>
{{ form.outside_diameter.label }}
{{ form.outside_diameter }}
</div>
<div>
{{ form.submit) }}
</div>
</form>
{% endfor %}
Here is a solution as per #ser-zhm comment. Now I can render whatever forms I have in DB separately on each other as it is shown on this image.
But when I submit data from one of the forms it is always updates the last record in DB and not the particular row. Lets say I have three empty forms rendered on the page and three records (rows) in my DB with NULL data in each column name referring to each form fields like it is shown here. When I fill in form #2, all the data is saved in row #3 instead of the row #2. So whatever form I fill in it is always the last record is updated.
How can I updated the particular row which is referring to the form ID?
View handler
#app.route('/envelope_forms_test', methods=['GET', 'POST'])
def nonuniform_ellipse():
form_ids = list(map(str, [id[0] for id in
Envelopes.query.with_entities(Envelopes.id).all()]))
forms = []
for form_id in form_ids:
form = EnvelopeForm(prefix=form_id)
forms.append(form)
for form in forms:
if form.submit.data and form.validate_on_submit():
Envelopes.query.filter_by(id=form_id).\
update({'vme_name': form.vme_name.data,
'outside_diameter': form.outside_diameter.data})
db.session.commit()
Here is HTML
{% for form in forms %}
<form method="POST" action="">
{{ form.csrf_token() }}
<div>
{{ form.vne_name.label }}
{{ form.vme_name }}
</div>
<div>
{{ form.outside_diameter.label }}
{{ form.outside_diameter }}
</div>
<div>
{{ form.submit) }}
</div>
</form>
{% endfor %}

Convert user.id to user.username in Django template

I am implementing the very cool third party package Django-Simple-History into a project. Per the documentation I'm using the middleware to store which user makes changes to an object. This makes it easy to iterate over in the template like:
{% for x in object.history.all %}
{{ x.history_date }}, {{ x.history_user_id }} <br />
{% endfor %}
I am trying to use the available user.id to get the correlating user.username in the template. Any suggestions? (I'm still pretty new to Django/Python) Thanks!
history_user holds the ForeignKey for the related user.
You can use: {{ x.history_user.username }}

Django: How to associate a comment to its corresponding OP in the HTML template?

I have designed a simplistic posting and comment system where each postcomment object is associated with its corresponding newpost object using foreign key. My problem is that the comments in the template aren’t showing under their corresponding newpost object. For example, if there are a total of 3 newposts and 3 comments under each post for a total of 9 comments, the template displays all 9 comments under each 3 posts (for a total of 27 comments). I need help figuring out how to correctly associate each comment with its corresponding post and not just loop through my ‘allcomments’ field under each post. Thanks for any help and hints.
postset = pagename.newpost_set.all().order_by('-postdate') #i use this to get a queryset of all posts on the selected page and order them so newest posts show up at the top
allposts = newpost.objects.filter(newposttag=‘userpage’) #i use this to get a queryset of all posts on the corresponding user’s page for the next line, this might seem redundant after the above, but it works because the postset is what I end up using in the template.
allcomments = postcomment.objects.filter(commenttag=allposts) #i use this to get a queryset of all the comments from each post in the ‘allposts’ queryset
Here is my template for displaying the above information that I have acquired
{% for postset in postset %}
<br>{{ postset.postcontent }} {{postset.postdate }} - {{ postset.postlikes }} likes Comment</br>
{% for allcomments in allcomments %}
<br> {{ allcomments.comment }} {{allcomments.postcommentdate }} - {{ allcomments.commentlikes}}
{% endfor %}
{% endfor %}
How about updating your template as follows:
{% for post in postset %}
<br>{{ post.postcontent }} {{post.postdate }} - {{ post.postlikes }} likes Comment</br>
{% for comment in post.postcomment_set.all %}
<br> {{ comment.comment }} {{comment.postcommentdate }} - {{ comment.commentlikes}} </br>
{% endfor %}
{% endfor %}
This way, you iterate over your posts and for each post, you retrieve the comments related to that post through the post.postcomment_set.all expression.
Please let me know if that helps you.
ps: I don't think that you need those three queries in your view though.

How to send hiddenfield in wtf flask form for database insert

How do i do specify the many database field when in a wtf form, so i can insert a row in the database correctly. I need something like this in my template
{{ wtf.form_field(gform.GHF(value="{{ project.name }}")) }}
because I'm iterating over one (Projects) to many (Goals)
Project-(has many goals)
-goal-
and my goal form shows up multiple times.
{% for project in P %}
{% for pgoal in project.goals.all() %}
<li>
Goal: {{ pgoal.goal }}<br>
{% if loop.last %}
<form class="form form-horizontal" method="post" role="gform">
{{ gform.hidden_tag() }}
{{ wtf.form_errors(gform) }}
{{ wtf.form_field(gform.goal) }}
Help here? do i need a hiddenfield to know which project?
{{ wtf.form_field(gform.submit) }}<br>
and so on...
Once I have the correct project, I will use it in my view here
u=models.Projects.query.get(correct project?)
p=models.Goals(goal=gform.goal.data,proj=u)
I wouldn't do it with a hidden field. I'd make each form submit a little differently.
You should have something like
<form class="form form-horizontal" method="post" role="gform"
action="{{ url_for('add_goal_to_project', project_id=project.id) }}">
And the route would be
#app.route('.../<int:project_id>', methods=['POST'])
def add_goal_to_project(project_id):
gform = GForm(....)
if gform.validate_on_submit():
project = models.Projects.query.get(project_id)
goal = models.Goals(gform.goal.data, proj=project)
# Do anything else you need to do, such as adding and committing
# the new object
return redirect(...)
return render_template(...)
I'm skipping the details in the form creation, redirect and render_template calls, but this should get the idea across. Each goal form's action points to a route built from the project id.
You could extend this to allow for the editing of goals, and you'd be able to make it a lot better with some nice ajax posts as well.

Displaying custom checkboxes with Django and ManyToManyField

I'm having trouble wiring my checkboxes together with the template to make a good user experience. I'm sending my form to the view which contains the following MyType which is described as:
models
class A(models.Model):
MyType = models.ManyToManyField(P)
forms
MyType = forms.ModelMultipleChoiceField(queryset=P.objects.all(), required=False, widget=forms.CheckboxSelectMultiple)
and the view is being sent as:
return render(request, "static/about.html", {'form': form})
and in the template, I have the following kind of structure
<li class="option table">
<div class="cell" id="center">
<div class="option-text">Option 1</div>
</div>
<div class="cell" id="right">
<div class="option-checkbox">
<div class="check"></div>
<input id="myid1" name="myname1" value="1" type="checkbox">
</div>
</div>
Now I can use answer: On a django form, how do I loop through individual options per field? to loop through, but this only gives the description. How do I recreate the actual HTML that deals with the options in the smartest way?
I've tried the shell to look at the objects, but I really don't see what I should be pulling in. i.e. in the template to recreate. What fields of each option should I pull in? or how do I get at the right info to build up my HTML such that the saving aspect of the form will work.
In a template I cannot do:
{% for field in form["MySmoking"] %}
{% endfor %}
so how could I modify the following:
{% for option in form.MyType.field.choices.queryset %}
{{ option.image }}
{{ option.title }}
{{ option.description }}
{% endfor %}
so, how would I spit out the HTML that builds the checkbox.
Thanks.

Categories

Resources