Django form not showing up - django

I am new to django and trying to show a form in an html file and I don't see the fields .
I can see everything except the form.
Task:
Allow the user to type a query into the search box in the sidebar to
search for an encyclopedia entry.
views.py
def index(request):
entries = util.list_entries()
searched = []
if request.method == "POST":
form = Search(request.POST)
if form.is_valid():
item = form.cleaned_data["item"]
for i in entries:
if item in entries:
page = util.get_entry(item)
page_converted = markdowner.convert(page)
context = {
'page': page_converted,
'title': item,
'form': Search()
}
return render(request, "encyclopedia/entry.html", context)
if item.lower() in i.lower():
searched.append(i)
context = {
'searched': searched,
'form': Search()
}
return render(request, "encyclopedia/search.html", context)
else:
return render(request, "encyclopedia/index.html", {"form": form})
else:
return render(request, "encyclopedia/index.html", {
"entries": util.list_entries(), "form":Search()
})
layout.html
<div class="sidebar col-lg-2 col-md-3">
<h2>Wiki</h2>
<form method="post" action="{% url 'index' %}">
{% csrf_token %}
{{form.item}}
</form>
<div>
Home
</div>
<div>
Create New Page
</div>
<div>
Random Page
</div>
{% block nav %}
{% endblock %}
</div>
Search class
class Search(forms.Form):
items = forms.CharField(widget=forms.TextInput(attrs={'class': 'myfieldclass', 'placeholder': 'search'}))

Try {{ form.as_p }} or just {{ form }} instead of {{ form.item }}.
I think item doesn't refer to anything.
Update:
There is a typo in your Search form class. The field name should be item not items.

Related

Django crispy forms - bootstrap4 table_inline_formset template rendering extra row on top

I am using the bootstrap4/table_inline_formset.html template in a FormHelper from django-crispy-forms. The table is rendered correctly in the template, but an extra form always appears at the beginning of the table, which is not visible when submitting the form.
forms.py:
class MetricForm(forms.ModelForm):
class Meta:
model = Metric
exclude = ['auto_value','occurrence']
class MetricFormSetHelper(FormHelper):
def __init__(self, *args, **kwargs):
super(MetricFormSetHelper, self).__init__(*args, **kwargs)
self.add_input(Submit('submit', 'Submit', css_class="btn btn-success"))
self.template = 'bootstrap4/table_inline_formset.html'
views.py:
#login_required
def create_occurrence(request, pk):
try:
site = Site.objects.get(id=pk)
except Site.DoesNotExist:
raise Http404("Site does not exist")
form = OccurrenceForm(request.POST or None, initial={'site':site})
MetricFormset = modelformset_factory(Metric, form=MetricForm, extra=3)
formset = MetricFormset(queryset=Metric.objects.none())
helper = MetricFormSetHelper()
if form.is_valid():
occurrence = form.save(commit=False)
occurrence.added_by = request.user
occurrence.site = site
occurrence.save()
form.save_m2m()
metric_formset = MetricFormset(request.POST)
if metric_formset.is_valid():
for metric_form in metric_formset.forms:
if all([metric_form.is_valid(), metric_form.cleaned_data != {}]):
metric = metric_form.save(commit=False)
metric.occurrence = occurrence
metric.save()
messages.success(request, "Occurrence created successfully.")
execute_from_command_line(["../manage_dev.sh", "updatelayers", "-s", "archaeology"])
return redirect(occurrence.get_absolute_url())
context = {
'form': form,
'site':site,
'formset':formset,
'helper': helper,
}
return render(request, "archaeology/occurrence_form.html", context=context)
template:
...
<form action="" method="post">
{% csrf_token %}
{{ form|crispy }}
<h4>Metrics</h4>
{{ formset.management_form }}
{% crispy formset helper %}
{% if form.instance.pk != None %}
<a class="btn btn-danger" href="{% url 'delete_occurrence' occurrence.id %}">{% trans "Delete" %}</a>
{% endif %}
</form>
...
Any idea how to remove the extra row?
I had to change the template and remove the lines that printed an empty form at the beginning.
table_inline_formset.html:
<tr class="d-none empty-form">
{% for field in formset.empty_form %}
{% include 'bootstrap4/field.html' with tag="td" form_show_labels=False %}
{% endfor %}
</tr>

Django: How to add another form to my homepage when the homepage already has a template

On my homepage(http://127.0.0.1:8000/) I created a template and its function in views.py and the URL of the homepage directs to it, however, there is a form that I want also to show on the homepage.
views.py:
def index(request):
template = loader.get_template('tracker/index.html')
hours_grouped_project =
LogHours.objects.all().order_by('proj_assignment__project__name', 'day')
context = {
'hours_grouped_project':hours_grouped_project,
}
return HttpResponse(template.render(context,request))
def form(request):
if request.method== 'POST':
form = LogHoursForm(request.POST)
if form.is_valid():
day = form.cleaned_data['day']
hours = form.cleaned_data['hours']
developer = form.cleaned_data['developer']
project = form.cleaned_data['project']
proj_assignment=ProjectAssignment.objects.create(
developer=developer,project=project)
LogHours.objects.create(day=day,hours=hours,
proj_assignment= proj_assignment)
else:
form = LogHoursForm()
return render(request, 'tracker/form.html',{'form': form})
the index is for the template displayed on the homepage, and the form is for the form.py.
form.py
class LogHoursForm(forms.Form):
day = forms.DateField()
hours = forms.DecimalField(max_digits=10, decimal_places=2)
developer = forms.ModelChoiceField(queryset=Developer.objects.all())
project = forms.ModelChoiceField(queryset=Project.objects.all())
and here is the URL: urlpatterns = [
path('', views.index, name='index'),]
the form.html is
<h1> LogHours Form</h1>
<hr>
<form action="" method="post">
{% csrf_token %}
{{form}}
<input type="submit">
</form>
and the index.html:
<ul>
<b>Logged hours grouped by project:</b>
{% for obj in hours_grouped_project %}
<li>
{% ifchanged obj.proj_assignment %}
<b>Project name:</b>
{{obj.proj_assignment|linebreaks}}
{% endifchanged %}
<i>Sorted Date: </i>
{{obj}}
</li>
{% endfor %}
</ul>
In your function index(request):
def index(request):
if request.method=='POST':
form(request)
else:
template = loader.get_template('tracker/index.html')
hours_grouped_project = LogHours.objects.all().order_by('proj_assignment__project__name', 'day')
form = LogHoursForm()
context = {
'hours_grouped_project': hours_grouped_project,
'form': form,
}
return HttpResponse(template.render(context, request))
Then, you can render the form from your index.html like this.
...
<form action="" method="post">
{% csrf_token %}
{{form}}
<input type="submit">
...

django + ajax send form

and at page i'm not see csrdI try after receiving one form to get another
views.py
def get_name(request):
if request.method == 'POST':
user_code = generate_code(8)
subject = 'ver code'
message = user_code
phone = request.POST['phone']
form = NameForm(request.POST)
if form.is_valid():
Registration.objects.create(fio=request.POST['fio'],mail=request.POST['mail'])
send_mail(subject, message,settings.EMAIL_HOST_USER,[mail],fail_silently=False)
return JsonResponse({ 'form1': render_to_string( 'registers/endreg.html', {'form': NameForm1() } ) })
else:
form = NameForm()
return render(request, 'registers/detail.html', {'form': form})
def endreg(request):
if request.method == 'POST':
form = NameForm1(request.POST)
if form.is_valid():
code_use = form.cleaned_data.get("key")
try:
user = Registration.objects.get(code=code_use)
user.verification = True
user.save()
messages.warning(request, u'thanks.')
except:
messages.warning(request, u'error.')
else:
form = NameForm1()
return render(request, 'registers/endreg.html', {'form': form})
and ajax
$(document).ready(function()
{ $("#my_form").submit(function(event)
{ event.preventDefault();
$this = $(this);
$.ajax({
type: "POST",
data: $this.serialize(),
success: function(data)
{ console.log(data);
$this.html(data.form1);
},
error: function(data)
{ console.log(data);
}
});
});
});
I am facing a CSRF token missing or incorrect problem. Because it is not transferred to form 2. how can I transfer this token to a new form
detatil.html it's html first page
{% extends 'base.html' %}
{% load i18n %}
{% block content%}
<div class="main-form">
<form action="" method="post" autocomplete="off" id="my_form">
{% csrf_token %}
<div class="contact-form" >
<h1>{%trans 'Регистрация' %}</h1>
<div class="txtb">{{form.fio.label}} {{form.fio}}{{form.fio.help_text}}</div>
<div class="txtb"> {{form.purpose.label}}{{form.purpose}}</div>
<div class="container" id="none">{{form.tso.label}}{{form.tso}}</div>
<div class="txtb">{{form.phone.label}} {{form.phone}}{{form.phone.help_text}}{{form.phone.errors}}</div>
<div class="txtb"> {{form.number_car.label}}{{form.number_car}}</div>
<div class="txtb"> {{form.date_visit.label}}{{form.date_visit}}</div>
<div class="txtb"> {{form.captcha.label}}<br>{{form.captcha}}{{form.captcha.errors}}</div>
<input type="submit" value="{%trans 'send' %}" class="btn" id="btn">
</div>
</form>
</div>
{% endblock %}
it's html secon page endreg.html
{% load i18n %}
{% block content%}
<form action="" method="post" autocomplete="off" >
{% csrf_token %}
<div class="verification" >
<div class="ver">
{{form}}
</div>
<input type="submit" value="{%trans 'send' %}" class="btn1" >
</div>
</form>
{%endblock%}
csrf token is on two pages, but when I look at the code in the browser, it does not appear when I add 2 forms using ajax
since you are using render_to_string, you need to pass request object to render_to_string. You can acheive it by:
def get_name(request):
if request.method == 'POST':
user_code = generate_code(8)
subject = 'ver code'
message = user_code
phone = request.POST['phone']
form = NameForm(request.POST)
if form.is_valid():
Registration.objects.create(fio=request.POST['fio'],mail=request.POST['mail'])
send_mail(subject, message,settings.EMAIL_HOST_USER,[mail],fail_silently=False)
return JsonResponse({ 'form1': render_to_string('registers/endreg.html', {'form': NameForm1()}, request=request) })
else:
form = NameForm()
return render(request, 'registers/detail.html', {'form': form})

Delete model instance button

I have a for loop that lists all the testimony instances in my model. I'd like to have the button in the code below delete the related instance when clicked.
html
{% block content %}
{% for testimony in testimonies %}
<a href="{% url "main:update_testimony_view" slug=testimony.slug %}">
<h3>{{testimony.name}}</h3>
<button type="button" class="btn btn-danger">Delete</button>
</a>
{% endfor %}
****
{% endblock content %}
views.py
def create_testimony_view(request):
if request.method == "POST":
form = CreateTestimonyForm(request.POST)
if form.is_valid():
testimony = form.save(commit=False)
testimony.save()
return redirect('main:homepage_view')
else:
form = CreateTestimonyForm
context = {
"title": "Create - Testimony",
"form": form,
"testimonies": Testimony.objects.all(),
}
return render(request=request, template_name="main/create/create_testimony.html", context=context)
def update_testimony_view(request, slug):
instance = get_object_or_404(Testimony, slug=slug)
if request.method == 'POST':
form = CreateTestimonyForm(
request.POST, request.FILES, instance=instance)
if form.is_valid():
testimony = form.save(commit=False)
testimony.save()
return redirect('main:homepage_view')
else:
form = CreateTestimonyForm(instance=instance)
context = {
"title": "Update - Testimony",
"form": form,
"instance": instance,
}
return render(request=request, template_name="main/create/create_testimony.html", context=context)
Thanks for any help
You need to make a POST request to the server which will delete the instance.
Please have a look at Form documentation. https://docs.djangoproject.com/en/3.0/topics/forms/
You need to add simple form and view to delete testimony.
html,
{% for testimony in testimonies %}
<a href="{% url "main:update_testimony_view" slug=testimony.slug %}">
<h3>{{testimony.name}}</h3>
<form action="{% url 'main:delete_testimony' testimony.pk %}" method="POST">
<button type="button" class="btn btn-danger">Delete</button>
</form>
</a>
{% endfor %}
view,
def delete_testimony(request, pk):
deleted = False
try:
Testimony.objects.delete(pk=pk)
deleted = True
except Testimony.DoesNotExist:
pass
return JsonResponse({'deleted':deleted})

TinyMCE submitting raw text with HTML tags

I'm using a TinyMCE text area in a form to create a new blog post; when I hit "Submit" I should get redirected to a new blog page with the formatted content I typed into the text area. What I actually get is raw content complete with <p>, <strong>, etc. tags.
Is something not configured properly? Here is the code:
TinyMCE config in my template <head>:
<script src="//cdn.tinymce.com/4/tinymce.min.js"></script>
<script type="text/javascript">
tinymce.init({
selector:'textarea'
});
</script>
Form with TinyMCE text area:
<h1>New post</h1>
<form method="POST" class="progresstracker-form">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default">Save</button>
</form>
View with relevant code to process the new blog post:
def pt_detail(request, slug):
ptpost = get_object_or_404(Post, slug=slug)
return render(request, 'blog/pt_detail.html', {'ptpost': ptpost})
def progresstracker(request):
posts = Post.objects.order_by('published_date')
return render(request, 'blog/progresstracker.html', {'posts': posts})
def progresstracker_new(request):
if request.method == "POST":
form = PostForm(request.POST)
if form.is_valid():
ptpost = form.save(commit=False)
ptpost.author = request.user
ptpost.published_date = timezone.now()
ptpost.save()
return redirect('pt_detail', slug=ptpost.slug)
else:
form = PostForm()
return render(request, 'blog/post_edit.html', {'form': form})
def post_edit(request, slug):
ptpost = get_object_or_404(Post, slug=slug)
if request.method == "POST":
form = PostForm(request.POST, instance=ptpost)
if form.is_valid():
ptpost = form.save(commit=False)
ptpost.author = request.user
ptpost.published_date = timezone.now()
ptpost.save()
return redirect('pt_detail', slug=ptpost.slug)
else:
form = PostForm(instance=ptpost)
return render(request, 'blog/post_edit.html', {'form': form})
I went down a rabbit hole with tinyMCE and Javascript functions, media references and the like, and in the end solved my problem when I (1) went back to very simple tinyMCE code (per below), and (2) added "|safe" to the actual references to the tinyMCE text.
template
<header>
.
.
<script src="//tinymce.cachefly.net/4.3/tinymce.min.js"></script>
<script type="text/javascript">
tinymce.init({
selector: 'textarea'
});
</script>
</header>
<body>
.
.
{% for post in posts %}
<h3>{{ post.title }}</h3>
<p style="font-size: 16px">{{ post.published_date|date:'M d, Y' }}</p>
{{ post.body|truncatewords:50|safe }}
<hr></hr>
{% endfor %}
.
.
</body>
To get contents from TinyMCE you must use editor function getContent(). I don't know Django but maybe you should use a hidden text input in which contents of TinyMCE are saved:
<script type="text/javascript">
tinymce.init({
selector:'textarea.my_css'
});
function saveContent() {
var ed = tinymce.activeEditor;
$('#hidContents').val(ed.getContent());
}
</script>
<h1>New post</h1>
<form method="POST" class="progresstracker-form">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default" onclick="saveContent">Save</button>
<input id="hidContents" type="hidden" name="hidContents">
</form>
Recommendations:
use the latest version (v4.4.3) of TinyMCE
always use more specific selector so that you are sure you are using the right textarea - example: selector: 'textarea.my_css'