I use class-based views in a Django app. UpdateView works fine with the same template, form and model like CreateView. But CreateView has the problem with submitting a form. I press the submit button and nothing happens. When I remove <script src="http://code.jquery.com/jquery-3.6.0.slim.min.js" charset="utf-8"></script> from <head> tag it submits.
But I need this script for rendering SimpleMDEField.
Note creates and saves good in the admin panel.
Also works this on js console:
let form = document.getElementById('add');
form.submit()
models.py
class Note(models.Model):
title = models.CharField(max_length=100, null=False, blank=False)
slug = models.SlugField(max_length=254, editable=False, unique=True)
author = models.ForeignKey(
User, on_delete=models.SET_NULL, null=True, editable=False
)
source = models.URLField(blank=True, default='')
body_raw = SimpleMDEField()
body_html = models.TextField(max_length=40000, default='', blank=True)
views.py
#method_decorator(login_required, name='dispatch')
class NoteCreateView(CreateView):
model = Note
fields = ['title', 'source', 'body_raw']
template_name = 'notes/create.html'
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
urls.py
urlpatterns = [
path('', NoteList.as_view(), name='home'),
path('view/<str:slug>/', NoteDetailView.as_view(), name='note'),
path('add/', NoteCreateView.as_view(), name='add'),
path('update/<str:slug>/', NoteUpdateView.as_view(), name='update'),
path('delete/<str:slug>/', NoteDeleteView.as_view(), name='delete'),
]
create.html
{% extends 'layouts/base.html' %}
{% block title %}Create Note{% endblock %}
{% block extrahead %}
<script src="http://code.jquery.com/jquery-3.6.0.slim.min.js" charset="utf-8"></script>
{{ form.media }}
{% endblock %}
{% block main %}
<form method="post" id="add">{% csrf_token %}
{{ form.as_p }}
<input type="submit" name="send" value="Save Note">
</form>
{% endblock %}
base.html
<!DOCTYPE html>
{% load static %}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}project name{% endblock %}</title>
{% block extrahead %}{% endblock %}
</head>
</body>
<div style="max-width: 1490px; padding-left: 40px; padding-right: 40px;">
{% block main %}{% endblock %}
</div>
</body>
</html>
I noticed an error An invalid form control with name='body_raw' is not focusable in js console. I found a question after googling the problem. And one answer helped.
I added novalidate to the form.
<form method="post" novalidate>
Everything works fine.
Related
Hej!
I'm having trouble with my django filter.
When I put {{myFilter}} in the template I only get an ObjectNumber and when I put {{myFilter.form}} I get the error:
ValueError at /plants/plants/
too many values to unpack (expected 2)
Does anyone have an idea what's going on?
# views.py
def plants_view(request):
plants = Plant.objects.all()
myFilter = PlantFilter(plants)
context = {"plants": plants, "myFilter": myFilter}
return render(request, 'plants/search_table.html', context)
# filters.py
class PlantFilter(django_filters.FilterSet):
class Meta:
model = Plant
fields = ['name',]
it doesn't matter if I use fields = [ ] or fields = '__all__' .
template.html
{% extends "landing/base.html" %}
{% load static %}
{% load i18n %}
{% load admin_urls %}
{% block page-title %} {%translate "View Plants" %} {% endblock %}
{% block head %}
<link href="{% static 'landing/vendor/tabulator/dist/css/tabulator.min.css' %}" rel="stylesheet">
<link href="{% static 'landing/vendor/tabulator/dist/css/bootstrap/tabulator_bootstrap4.min.css' %}" rel="stylesheet">
{% endblock %}
{% block content %}
<br>
<div class="row">
<div class="col">
<div class="card card-body">
<form method="get">
{{myFilter.form}}
<button class="btn-primary" type="submit">Search</button>
</form>
</div>
</div>
</div>
</br>
# models.py
class Plant(models.Model):
name = models.CharField(
max_length=200
)
def __str__(self):
return f"{self.name}"
def serialize(self):
return {
"Name": self.name
}
Did you follow the documentation on this page ?
views.py
def plants_view(request):
plants = Plant.objects.all()
myFilter = PlantFilter(request.GET, queryset=plants)
context = {"plants": plants, "myFilter": myFilter}
return render(request, 'plants/search_table.html', context)
template.html
<form method="get">
{{ myFilter.form.as_p }}
<button class="btn-primary" type="submit">Search</button>
</form>
I'm trying to build an wiki page, already searched through other posts but couldn't solve my problem, someone can help?
I'm getting the following error: Reverse for 'edit' with no arguments not found. 1 pattern(s) tried: ['wiki/edit/(?P[^/]+)/$']
Basically what it is, is an edit page to edit an wiki entry, the button to edit the entry is located at entry.html, this is supposed to send the entry name as a parameter to edit.url then i edit it and send through POST the new content to override the actual content of the entry.
Here is my views.py
def edit(request, entry):
if request.method == 'POST':
content = request.POST.get('edit')
util.save_entry(entry, content)
return render(request, "encyclopedia/entry.html", {
"entry": markdown2.markdown(util.get_entry(entry)),
"title": entry
})
else :
return render(request, "encyclopedia/edit.html", {
"entry": entry
})
Here is my urls.py
from django.urls import path, re_path
from . import views
app_name = "encyclopedia"
urlpatterns = [
path("", views.redirect, name="redirect"),
path("wiki", views.index, name="index"),
path("wiki/search/", views.search, name="search"),
path("wiki/newentry", views.new, name="new"),
path("wiki/edit/<str:entry>/", views.edit, name="edit"),
path("wiki/<str:entry>", views.entry, name="entry")
]
And my edit.html
{% extends 'encyclopedia/layout.html' %}
{% block title %}
Edit Page
{% endblock %}
{% block body %}
<form action="{% url 'encyclopedia:edit' %}" method="POST">
{% csrf_token %}
<label for="edit">Edit {{ entry }}</label>
<textarea id="edit" name="edit" style="display: block; height: 70%;"></textarea>
<button type="submit">Edit</button>
{% endblock %}
I forgot to put my entry.html, this is the page where the edt4it button is located, who redirects to the edit.html via GET.
{% extends "encyclopedia/layout.html" %}
{% block title %}
{{ title }}
{% endblock %}
{% block body %}
{{ entry|safe }}
<a class="btn btn-primary" href="{% url'encyclopedia:edit'entry=title%}">Edit Entry</a>
{% endblock %}
You should pass a value for the entry parameter, this is likely the entry parameter:
<form action="{% url 'encyclopedia:edit' entry=entry %}" method="POST">
The error says that it can not find a view with the name encyclopedia:edit with no parameters, which is correct, since it has a parameter entry. You thus need to pass this to the {% url … %} template tag [Django-doc].
Note: In case of a successful POST request, you should make a redirect
[Django-doc]
to implement the Post/Redirect/Get pattern [wiki].
This avoids that you make the same POST request when the user refreshes the
browser.
I'm trying to get data on_submit from input fields in multiple form fields. But I want to use one submit button from one of the fields. is this even possible?
class Form1(FlaskForm):
entry1 = StringField(('Entry 1'))
class Form2(FlaskForm):
entry2 = StringField(('Entry 2'))
submit = SubmitField(('Register'))
#app.route('/index', methods=['GET', 'POST'])
def index():
form1= Form1()
form2= Form2()
if form2.validate_on_submit():
entry1 = request.form.get('entry1')
entry2= request.form.get('entry2')
flash((entry1))
flash((entry2))
return redirect(url_for('main.index'))
return render_template('index.html', form1=form1, form2=form2)
{% extends "base.html" %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block app_content %}
<div class="row">
<div class="col-md-4">
{{ wtf.quick_form(form1)}}
{{ wtf.quick_form(form2) }}
</div>
</div>
{% endblock %}
You could move the Submit button to a new class that inherits the other forms. From what I understand, validate_on_submit() processes and validates the fields of the called form, which includes any fields of inherited form classes.
class Form1(FlaskForm):
entry1 = StringField(('Entry 1'))
class Form2(FlaskForm):
entry2 = StringField(('Entry 2'))
class FinalForm(Form1, Form2):
submit = SubmitField(('Register'))
Now you only have to refer to the final form in the call and rendering.
#app.route('/', methods=['GET', 'POST'])
def index():
form = FinalForm()
if form.validate_on_submit():
entry1 = request.form.get('entry1')
entry2 = request.form.get('entry2')
flash((entry1))
flash((entry2))
return redirect(url_for('index'))
return render_template('index.html', form=form)
Here were the basic html templates I tested with success, trying to keep with the format you showed.
base.html :
{% extends 'bootstrap/base.html' %}
{% block content %}
<div class="container">
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
<div class="alert alert-info" role="alert">{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
{% block app_content %}{% endblock %}
</div>
{% endblock %}
index.html :
{% extends "base.html" %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block app_content %}
<div class="row">
<div class="col-md-4">
{{ wtf.quick_form(form) }}
</div>
</div>
{% endblock %}
I am not entirely sure if I understand your problem correctly, but you can use WTForms to build your forms. You'd have to define another class though that holds the both classes with the fields you need to submit.
https://wtforms.readthedocs.io/en/stable/
On the admin site, I create ConclusionName and RetrospectiveField. I need the fields baseText and comments to appear on the site under the word Application 2 'Retrospective'
Conclusion (app)
models.py
class ConclusionName(models.Model):
name = models.CharField(max_length=250)
def __unicode__(self):
return self.name
class RetrospectiveField(models.Model):
user = models.ForeignKey(User)
conclusionName = models.ForeignKey(ConclusionName)
baseText = models.TextField(max_length=255)
comments = models.TextField(max_length=255)
project = models.ForeignKey(Project)
forms.py
class RetrospectiveFieldForm(forms.Form):
project = forms.ModelChoiceField(queryset=Project.objects.all(), label=u'Project')
conclusionName = forms.ModelChoiceField(queryset=ConclusionName.objects.all(), label=u'ConclusionName')
baseText = forms.TextField(max_length=255, label=u'BaseText')
comments = forms.TextField(max_length=255, label=u'Comments')
class Meta:
model = RetrospectiveField
fields = ('project', 'conclusionName', 'baseText', 'comments',)
views.py
def add_form_retrospective_field(request):
if request.method == 'POST':
form = RetrospectiveFieldForm(request.POST)
if form.is_valid():
retro = RetrospectiveField()
retro.user = User.objects.get(username=request.user)
retro.project = form.cleaned_data.get('project')
retro.conclusionName = form.cleaned_data.get('conclusionName')
retro.baseText = form.cleaned_data.get('baseText')
retro.comments = form.cleaned_data.get('comments')
retro.save()
return redirect('/')
else:
form = RetrospectiveForm()
return render(request, 'completeness/forms_retrospective_field.html', {'form': form})
def showRetrospectiveField(request, slug):
projects = Project.objects.filter(id=slug)
retrospectiveFields = RetrospectiveField.objects.get(project=projects)
return render(request, 'completeness/view_retrospectiveField.html', {'retrospectiveFields': retrospectiveFields})
conclusion/example.html
{% extends 'completeness/base.html' %}
{% load staticfiles %}
{% load i18n %}
{% block title %}{% trans 'Network' %}{% endblock %}
{% block head %}
<meta charset="UTF-8">
<title>Conclusion</title>
<script data-require="jquery#*" data-semver="3.0.0" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.js"></script>
<link href="style.css" rel="stylesheet" />
<script src="script.js"></script>
{% block js %}
{{ form.media }}
{% endblock %}
{% endblock head %}
{% block content %}
<div class="parent">
<div class="block">
<h3>Application 2 "Retrospective"</h3>
{% for retro in retrospectiveField %}
<p>{{ retro.baseText }}</p>
<p>{{ retro.comments }}</p>
{% endfor %}
</div>
</div>
{% endblock content %}
You are returning retrospectiveFields in your showRetrospectiveField view, but you're using retrospectiveField in your for loop of conclusion/example.html
I have this code(which doesn't give me expected result)
#subject_content.html
{% block main-menu %}
{% include "subject_base.html" %}
{% endblock %}
#subject_base.html
....
....
<div id="homework" class="tab-section">
<h2>Homework</h2>
{% include "subject_file_upload.html" %}
</div>
child template:
#subject_file_upload.html
<form action="." method="post" enctype="multipart/form-data">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="submit">
</form>
and my view
#views.py
#login_required
def subject(request,username, subject):
if request.method == "POST":
form = CarsForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return HttpResponseRedirect("/")
form = CarsForm()
return render_to_response('subject_content.html', {'form':form}, context_instance=RequestContext(request))
The above code creates HTML in the way I want it to be, however the form does not update database.
BUT,
If I skip the middle template and go directly to the uploading form, it works fine:
#subject_content.html
{% block main-menu %}
{% include "subject_file_upload.html" %}
{% endblock %}
Help me please to make it work with middle template.
I want to do this, because I don't wan't to type the same code more than once.
Like #Besnik suggested, it's pretty simple:
{% include "subject_file_upload.html" with form=form foo=bar %}
The documentation for include mentions this. It also mentions that you can use only to render the template with the given variables only, without inheriting any other variables.
Thank you #Besnik