Django form & rendering data from model - django

I am currently struggling with Django forms. Based on the tickets model I generate this formset where users can choose the qty of tickets they want. After they will be redirected to the checkout page.
My problem is, when I use {{ form.ticket }} I get a select field but that's not what I'm looking for. I just want to print out the tickets as seen in the screenshot below.
Can anyone help me on that?
How it should be:
How it currently looks like:
views.py
from django.forms import formset_factory
from django.shortcuts import redirect, render
from .forms import EntryModelForm
from .models import Ticket
from orders.models import Order, Entry
# Create your views here.
def choose_ticket_and_quantity(request):
tickets = []
for ticket in Ticket.objects.all():
tickets.append({'ticket': ticket})
EntryFormSet = formset_factory(EntryModelForm, extra=0)
formset = EntryFormSet(initial=tickets)
if request.POST:
o = Order.objects.create()
request.session['order_id'] = o.order_id
formset = EntryFormSet(request.POST, initial=tickets)
if formset.is_valid():
for form in formset:
if form.cleaned_data['quantity'] > 0:
entry = form.save(commit=False)
entry.order = o
entry.save()
return redirect('http://127.0.0.1:8000/checkout')
return render(request, "tickets/choose_ticket_and_quantity.html", {'formset': formset})
forms.py
from django import forms
from orders.models import Entry
class EntryModelForm(forms.ModelForm):
class Meta:
model=Entry
fields = ['ticket', 'quantity']
choose_ticket_and_quantity.html
<form method="post" action="">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
<ul>
<li>{{ form.ticket }}</li>
<li>{{ form.quantity }}</li>
</ul>
{% endfor %}
<p><input type="submit" value="Checkout"></p>
</form>
What I also tried was this here, but unfortunately, this didn't work either as my form couldn't be validated anymore and all ticket types have been printed together:
{% for choice in form.ticket.field.choices %}
{{choice.1}}
{% endfor %}

Try this
Add a templatetag get_ticket.py in app/templatetags (Add a __init__.py too)
from django import template
register = template.Library()
# import Ticket model
#register.simple_tag
def get_ticket(pk):
ticket = Ticket.objects.get(pk=int(pk))
return ticket.name # is it name?
In your template
{% load get_ticket %}
<form method="post" action="">
{% csrf_token %}
{{ formset.management_form }}
<ul>
{% for form in formset %}
<li>
<strong>{% get_ticket form.ticket.value %}</strong><br>
<input type="hidden" name='{{form.ticket.name}}' value='{{form.ticket.value}}'>
{{ form.quantity }}
</li>
{% endfor %}
</ul>
<p><input type="submit" value="Checkout"></p>
</form>

Looks like you want to display the value of the field:
<li>{{ form.ticket.value }}</li>

Related

django jsignature not saving to database

i am trying to implement a jsignature plug in to my django appplication via django-jsignature3 , however it seems that i am unable to get it to save to my database.
here is my code:
models.py
class JSignatureModel(JSignatureFieldsMixin):
name = models.CharField(max_length=20)
views.py
def my_view(request):
form = SignatureForm(request.POST or None)
print('in view')
if form.is_valid():
signature = form.cleaned_data.get('signature')
print('form is valid')
if signature:
# as an image
print('found sig')
signature_picture = draw_signature(signature)
# or as a file
signature_file_path = draw_signature(signature, as_file=True)
return render(request, 'cash/jsig.html', {'form': form })
jsig.html
{% extends 'base.html' %}
{% load static %}
{%load crispy_forms_tags%}
{% block content %}
<body>
{{ form.media }}
<form action="." method="POST">
{% for field in form %}
{{ field.label_tag }}
{{ field }}
<span style="color:red">{{ field.errors }}</span>
{% endfor %}
<input type="submit" value="Save"/>
{% csrf_token %}
</form>
</body>
{%endblock content%}
url.py
path('jsig/', views.my_view , name='jsig')
forms.py (this is really iffy to me , i don't understand the documentation , there is no place that my model was called , hence i did this my self but it does not work)
class SignatureForm(forms.Form):
signature = JSignatureField()
class Meta:
model = JSignatureModel
fields = ['name','signature']
exclude = []
here is my console
[04/Apr/2020 01:14:43] "GET /jsig/ HTTP/1.1" 200 5593
in view
form is valid
found sig
[04/Apr/2020 01:14:46] "POST /jsig/ HTTP/1.1" 200 5959
Please help , im really confused!

Using redirect sends me to /tag/?search=input instead of /tag/input (Django URL argument from form)

I have a page where there is a path /tag/name_of_tag and you can see all posts tagged with that tag.
Inside the page, you can also select another tag in a form and go to that tag.
The problem is that instead of going to /tag/searched_tag, it goes to /tag/?search=searched_tag
How can I change it doesn't leave the ?search= part?
urls.py:
url(r'tag/(?P<input_tag>\w+)$', views.tag_view, name='tag'),
views.py:
def tag_view(request, input_tag):
form = TagSearchForm()
if request.method == 'GET':
form = TagSearchForm(request.GET)
if form.is_valid():
input = form.cleaned_data['search']
print(input)
return redirect('fortykwords:tag_view', input)
else:
form = SearchForm()
latest_post_list = Post.objects.filter(tags=input_tag, status__exact="published")
paginator = Paginator(latest_post_list, 3)
page = request.GET.get('page')
posts = paginator.get_page(page)
context = {'latest_post_list': latest_post_list, 'page_tag': input_tag, 'form': form}
return render(request, 'fortykwords/tag.html', context)
forms.py:
class TagSearchForm(forms.Form):
search = tagulous.forms.SingleTagField(
tag_options=tagulous.models.TagOptions(
autocomplete_view='fortykwords:post_tags_autocomplete'
),
label='Tags',
required=True,
help_text=_('Filter by lead tags. You can organize leads by any tag you want.'),
)
tag.html:
{% extends "base_generic.html" %}
{% block content %}
<form action="." method="get">
{{ form }}
<input type="submit" value="Submit" />
</form>
<h3>Posts with the tag {{ page_tag }}</h3>
{% if latest_post_list %}
<ul>
{% for post in latest_post_list %}
<li> {{ post.author }} {{ post.pub_date }}
<br>
{{ post.title }}</li>
{% for tag in post.tags.all %}
{{ tag.name }}
{% endfor %}
{% endfor %}
</ul>
{% else %}
<p>No posts are available.</p>
{% endif %}
{% endblock %}
You need to provide the argument input to redirect method as input_tag=input.
Example:
return redirect('fortykwords:tag_view', input_tag=input)
It's showing as /tag/?search=searched_tag because your form is submitting by GET but never getting to the redirect. It seems is_valid() is returning False.
I've tested a very similar version of your code and don't think it's a bug in tagulous, but would still be interested to know what had gone wrong (I wrote tagulous). Spotted a couple of places you can streamline your code a bit, so try::
def tag_view(request, input_tag):
# Can't see any POSTs in your example, so you can pass the form GET here
# Might also be nice to pass the original tag in so it shows in the form
form = TagSearchForm(request.GET, initial={'search': input_tag})
# The form already has the GET, so you can go straight into the is_valid
if form.is_valid():
input = form.cleaned_data['search']
print('Valid: ', input)
return redirect('fortykwords:tag_view', input)
else:
print('Invalid: ', form.errors, form.non_field_errors)
# You can remove the else for if not GET, which would never be reached
# on to pagination as before
(although fwiw I'd recommend ipdb instead of print)

Model Formset - By Default model formset is rendering one extra field (2 fields in total)

My model formset without even defining "extra" parameters in modelformset_factory is rendering one extra field in the template. I have tried many variations but it didn't work. If I print the form (the model form) on the command line it just prints a single form field as required but on model formset it prints 2 by default.
Here is my code.
models.py
class Direction(models.Model):
text = models.TextField(blank=True, verbose_name='Direction|text')
forms.py
class DirectionForm(forms.ModelForm):
class Meta:
model = Direction
fields = ['text',]
views.py
def myview(request):
Dirset = modelformset_factory(Direction, form=DirectionForm)
if request.method == "POST":
dir_formset = Dirset(request.POST or None)
if dir_formset.is_valid():
for direction in dir_formset:
text = direction.cleaned_data.get('text')
Direction.objects.create(text=text)
return render(request, "test/test.html", {'DirFormSet':Dirset})
template
{% block content %}
<form method="POST">{% csrf_token %}
<div id="forms">
{{DirFormSet.management_form}}
{% for form in DirFormSet %}
{{form.text}}
{% if error in form.text.errors %}
{{error|escape}
{% endif %}
{% endfor %}
</div>
<button id="add-another">add another</button>
<input type="submit" />
</form>
{% endblock %}
As a side note, if I submit data on this form it gives the following error.
Error
Exception Type: MultiValueDictKeyError
Exception Value:"u'form-0-id'"
By default, modelformset_factory creates one extra form. If you don't want any extra forms, set extra=0.
Dirset = modelformset_factory(Direction, form=DirectionForm, extra=0)
The KeyError is because you have not included the form's id field in your template. You should have something like:
{% for form in dir_formset %}
{{ form.id }}
{{ form.text }}
...
{% endfor %}
Note that you should be passing the formset instance dir_formset when rendering the template, not the class DirFormSet. Your view should be something like
return render(request, "test/test.html", {'dir_formset': dir_formset})
then the template should be updated to use dir_formset instead of DirFormSet.

How to change the value of ENDLESS_PAGINATION_PER_PAGE from template side?

I use Django Endless Paginator plugin.
I try to change the value of ENDLESS_PAGINATION_PER_PAGE from template side.
As default is 10.
I want to realize some dropbox where the user can change between (Example: 10,20,50,100 Objects).
Thanks for answer, but something not work property.
1. I have view.py
def adv_search(request):
objects = None
if request.GET.get('key'):
form = AdvancedSearchForm(request.GET)
if form.is_valid():
repo = Repository()
objects = list(repo.find_objects('*'+form.cleaned_data['key'] +'*', type=FileObject, chunksize=20))
return render(request, 'templates/adv_search.html', {'form': form, 'objects': objects })
return render(request, 'templates/adv_search.html', {'form': AdvancedSearchForm(), 'objects': objects})
2. Then forms.py
class AdvancedSearchForm(forms.Form):
key = forms.CharField(max_length=500, label="", widget= forms.TextInput(attrs={'class': 'label'}))
show_props = forms.MultipleChoiceField(choices = (("pid", "pid"),("title", "title"),("type","type"),("source","source"),("date","date"),("publisher","publisher"),("subject","subject"),("label","label"),("cDate","cDate"),("mDate","mDate")),required=False, widget=forms.CheckboxSelectMultiple(attrs={'class': 'my-class'}))
paginator = forms.ChoiceField(choices =(('10', '10'),('20','20'), ('50','50'), ('100','100')) ,required=False, )
3. adv_search.html
{% paginate paginator objects %}
{% for obj in objects %}
...
<div class="paginator">
{% get_pages %}
{{ pages.first_as_arrow }}
{% show_pages %}
{{ pages.last_as_arrow }}
<form method="get">
{{ form.paginator }}
<input type="submit" Value="Go">
</form>
{{ pages.total_count }} total objects
</div>
Everything works except select
Thanks Andrey
You can have a form which will set pagination per page and then use that submitted value in template. Here is an example:
View
from django.shortcuts import render
from .models import Entry
def endless_view(request):
pagination_per_page = request.GET.get('per_page', 10)
entries = Entry.objects.all()
return render(request, 'some_template.html', {'pagination_per_page':
pagination_per_page, 'entries': entries})
Template
{% extends 'base.html' %}
{% load endless %}
{% block content %}
{# #}
<form action="" method="get">
<select name="per_page">
<option value="10">10 per page</option>
<option value="20">20 per page</option>
<option value="50">50 per page</option>
<option value="100">100 per page</option>
</select>
<input type="submit" Value="Go">
</form>
{% paginate pagination_per_page entries %}
{% for entry in entries %}
{# your code to show the entry #}
{% endfor %}
{% show_pages %}
{% endblock content %}
Reference
http://django-endless-pagination.readthedocs.org/en/latest/templatetags_reference.html

Completely stripping certain HTML Tags in Django forms

I have a ModelForm that posts news items to a database, and it uses a javascript textarea to allow the authorized poster to insert certain pieces of HTML to style text, like bold and italics. However, since I have the template output using the "safe" filter, it outputs all the HTML the form widget tries to pass on. This includes a bothersome <br> tag that never goes away, making it so you can submit without form validation reading the field as empty and stopping you. How can I make that I can not only filter the <br> tag, but completely remove it from the data? Here is relevant code:
Models.py:
from django.db import models
from django.forms import ModelForm, forms
from django.contrib.auth.models import User
# Create your models here.
class NewsItem(models.Model):
user = models.ForeignKey(User)
date = models.DateField(auto_now=True)
news = models.TextField(max_length=100000, blank=False, help_text='HELP TEXT')
def __unicode__(self):
return u'%s %s %s' % (self.user, self.date, self.news)
class NewsForm(ModelForm):
class Meta:
model = NewsItem
exclude=('user','date',)
Views.py:
from news.models import NewsForm, NewsItem
from django.shortcuts import render
from django.http import HttpResponseRedirect, HttpResponse
def news(request):
if request.method == 'POST':
item = NewsItem(user=request.user)
form = NewsForm(request.POST, instance=item)
if form.is_valid():
form.save()
return HttpResponseRedirect('/news/')
else:
form = NewsForm()
news_list = NewsItem.objects.all()
return render(request, 'news_list.html', {'news_list': news_list, 'form': form})
news_list.html:
{% extends "base.html" %}
{% block title %}News in the Corps{% endblock %}
{% block content %}
<h2 id="page_h">News in the Corps</h2>
{% if user.is_authenticated %}
<h3>Post News</h3>
<script src="{{ STATIC_URL }}nicEdit.js" type="text/javascript"></script>
<script type="text/javascript">bkLib.onDomLoaded(nicEditors.allTextAreas);</script>
<div id="news_poster">
<form id="news_poster" action="/news/" method="POST">{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
</div>
{% endif %}
<ul id="events_list">
{% if news_list %}
<div id="news_list">
{% for news in news_list %}
{% if news.id == 1 %}
<hr />
{% endif %}
<div id="{{ news.id }}" class="news_item">
<p class="poster">Posted By: {{ news.user }} | Posted On: {{ news.date }} | Link</p>
<div id="news_item">
{{ news.news|safe }}
</div>
</div>
<hr />
{% endfor %}
</div>
{% endif %}
</ul>
{% endblock %}
You can try the removetags template filter:
{{ news.news|removetags:"br"|safe }}
I can't help but thinking that the "removetags" as Timmy O'Mahony suggested might work if it was structured like this:
{{ news.news|safe|removetags:"br"}}
Give it a shot and see if it works. I would reply, but my karma's not height enough to directly reply to an answer with a suggestion.