Hi just looking for some help at solving this error in Django whilst trying to call a view that to accept a htmx request. The final result is to display a popup Modal of images from a Gallery when a thumbnail is clicked.
HTMX installed via script in head.
View
if request.htmx:
slug = request.GET.get('slug')
context = {'pictures': Media.objects.filter(slug=slug)}
return render(request, 'main/gallery-detail.html', context=context)
context = {'objects_list': Albums.objects.all()}
return render(request, 'main/gallery.html', context=context)
Relevant html with the button to open gallery of images.
<a class="btn btn-primary" hx-post="{{ request.path }}?slug={{ img.slug }}" hx-target="#modal">
{{ img.slug }}</a>
{% endfor %}
<div id="modal">{% include "main/gallery-detail.html" %}</div>
This error mostly occurs if you haven't included django-htmx in the settings.py.
Try making the below changes and see if it works :
Add "django_htmx.middleware.HtmxMiddleware" to the MIDDLEWARE.
Add "django_htmx" to the INSTALLED_APPS.
Related
Can we display a map on a template using django PointField?
I have a model with one PointField and then after creating a model form, I want to display the map in my template using that form.
View
def map_view(request):
form = ShopForm()
context = {
'form' : form
}
return render(request, 'ads/map.html', context)
Template
<html>
<head>
</head>
<body>
<div>
<form method="post">
{{ form }}
<input type="submit" >
</form>
</div>
</body>
</html>
I was wondering is it possible to display the map using that or do I need to something extra.
I was also having the same question and thankfully I got the right way of doing it.
Anyone who's facing this issue can follow this link
The tutorial is divided into three parts.
REMEMBER:
When you reach to the 2nd part and everything is done and you're writing python manage.py runserver
-in your template include all these
{% load leaflet_tags %}
{% leaflet_css %}
{% leaflet_js %}
Place this within your {% block content %} {% endblock content %} otherwise you'll end up rendering nothing
Have you tried using the following part of the documentation on your form?
https://docs.djangoproject.com/en/2.2/ref/contrib/gis/forms-api/#widget-classes:
from django.contrib.gis import forms
class ShopForm(forms.Form):
point = forms.PointField(widget=
forms.OSMWidget(attrs={'map_width': 800, 'map_height': 500})
)
I'm working on a Django site that displays a list of projects. You go to a page, you see a project, you click it, and you can then see project details and have the option to edit the page.
For each individual project, I use a template called project.html. Then on that page, I have a link to edit_project.html
Edit Project
Whenever I try to load the project page to view, I get this error:
Reverse for 'edit_project' with arguments '('',)' not found. 1
pattern(s) tried: ['edit_project/(?P\d+)/$']
I checked the urls, and they seemed fine. So, I tried hard-coding a project id that I knew was in the database. For example, I called:
Edit Project
instead of calling that same thing with "project.id". When I did that, the error went away.
Why does this work with a hard-coded value instead of a project.id variable?
I also tried deleting the database and all the migrations in case something strange was happening there. I got the same issue though.
Here is the code I used to set everything up in case it is helpful.
project.html
{% extends "profile/base.html" %}
{% block content %}
<p>
Edit Project
</p>
<p>Status: {{ status }}</p>
{% endblock content %}
edit_project.html
{% block content %}
<p>{{ project }}</p>
<p>Edit project:</p>
<form action="{% url 'profile:edit_project' project.id %}" method='post'>
{% csrf_token %}
{{ form.as_p }}
<button name="submit">Save Changes</button>
</form>
{% endblock content %}
views.py
#login_required
def edit_project(request, project_id):
"""Edit an existing project"""
project = Project.objects.get(id=project_id)
#Make sure the project belongs to the owner
if project.owner != request.user:
return Http404
if request.method != 'POST':
#Initial request; pre-fill form with the current entry
form = ProjectForm(instance=project)
else:
#POST data submitted; process data
form = ProjectForm(instance=project, data=request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('profile:project',args=[project.id]))
context = {'project':project, 'form':form}
return render(render, 'profile/edit_project.html', context)
(project) forms.py
class DateInput(forms.DateTimeInput):
input_type = 'date'
class ProjectForm(forms.ModelForm):
class Meta:
model = Project
fields = ['name','description','status', 'project_type', 'start_date','end_date', 'due_date']
labels = {'name':'Name', 'description':'Description:', 'status':'Status', 'project_type':'Project Type',
'start_date':'Start Date', 'end_date':'End Date', 'due_date': 'Due Date',}
widgets ={'description':forms.Textarea(attrs={'cols':80}),'start_date':DateInput(),
'end_date':DateInput(),'due_date':DateInput()}
urls.py
urlpatterns = [
#Home page
url('^$', views.index, name='index'),
#Show all projects
url('projects/$', views.projects, name='projects'),
#Details for single project
url('^projects/(?P<project_id>\d+)/$', views.project, name='project'),
#Page for editing a single project
url('^edit_project/(?P<project_id>\d+)/$', views.edit_project, name='edit_project'),
]
I got an error,
TemplateDoesNotExist at /app/detail/3/ app/post_detail.html.
I wrote the following:
def top(request):
content = POST.objects.order_by('-created_at')[:5]
page = _get_page(blog_content, request.GET.get('page'))
return render(request, 'top.html',{'content':content,"page":page})
class DetailView(generic.DetailView):
model = POST
def detail(request, pk):
content = POST.objects.get(id=pk)
return render(request, 'detail.html',{'content': content})
in top.html
<div>
{% for content in page %}
<h2>{{ content.title }}</h2>
<p>SHOW DETAIL</p>
{% endfor %}
</div>
in detail.html
<h2>{{ content.title }}</h2>
<p>{{ content.text }}</p>
When I access top.html, ordinary web site is shown, so it is ok. But when I put SHOW DETAIL links the error happens.
I did not write post_detail.html anywhere in my code, so I really cannot understand why post_detail.html causes the mistake.
As a test,I made post_detail.html in same directory with top.html and detail.html, but the same error happens. I want to make a system when I put SHOW DETAIL links, the content's detail is shown.
How should I fix this? What is wrong in my code?
After reading answer,I rewrote DetailView of views.py
class DetailView(generic.DetailView):
model = POST
template_name = 'detail.html'
but when I put SHOW DETAIL links, nothing is shown there.I wrote in detail.html
<h2>{{ post.title }}</h2>
<p>{{ post.text }}</p>
Am I wrong to write the way of detail.html or views.py?How can I show detail's content?
You are using a generic detail view for the POST detail. Generic views do not expect or use a detail() method, and either look for a template as specified in the template_name class attribute or the default which is modelname_detail.html.
You should either make your view a standard function view - like the "top" one - by moving the detail method out of that class; or, remove the method altogether (because it just does what the generic view does already) and either rename your template to post_detail.html or set template_name = 'detail.html'.
Is there any way to add form (for example feedback form) to every page in CMS? I really like to use Wagtail FormBuilder so Editor guy can change fields.
My first idea is to create custom form page (inherited from AbstractEmailForm) as site root child and load it to base.html trough template tag. I can access page properties this way but I cant render the form.
Here is my template tag:
#register.assignment_tag(takes_context=True)
def get_feedback_form(context):
return context['request'].site.root_page.get_children().type(FeedbackFormPage).first()
And this is how I use it from base.html:
{% get_feedback_form as feedback_form %}
...
{{ feedback_form.specific.title }} <-- this works
{{ feedback_form.specific.form.as_p }} <-- this doesnt work
It would be nice somehow to create a form as snippet or add it to Site Settings, but I didnt find how to do that.
The main issue is how you are generating the form in the template with .form.as_p.
You will need to generate the form with the .get_form function, but you are best to do it within your template as the current user and page needs to be past in as arguments like this.
form = feedback_form_page.get_form(
page=feedback_form_page, user=request.user)
You can see how the form is built for the AbstractForm model here:
https://github.com/wagtail/wagtail/blob/master/wagtail/wagtailforms/models.py#L278
Full detailed example below, along with how you could work the form selection into the Site Settings module.
Link to a Form in Site Settings
Assuming you are referring to the Site Settings contrib module:
http://docs.wagtail.io/en/v1.13/reference/contrib/settings.html
The 'Edit Handlers' section of the documentation explains a great way to link to a page inside of your site settings.
http://docs.wagtail.io/en/v1.13/reference/contrib/settings.html?highlight=site%20settings#edit-handlers
Example (in models.py):
from wagtail.contrib.settings.models import BaseSetting, register_setting
# ...
#register_setting
class MyCustomSettings(BaseSetting):
feedback_form_page = models.ForeignKey(
'wagtailcore.Page', null=True, on_delete=models.SET_NULL)
panels = [
# note the page type declared within the pagechooserpanel
PageChooserPanel('feedback_form_page', ['base.FormPage']),
]
Once you set this model up, you will need to do makemigration and migrate for the changes to work in admin. You will then see inside the settings menu a sub-menu titled 'My Custom Settings'
Adding linked Form to every page
Add a block (so it can be overridden in templates) that has an include in your base template (eg. myapp/templates/base.html).
<!-- Footer -->
<footer>
{% block feedback_form %}{% include "includes/feedback_form.html" %}{% endblock feedback_form %}
{% include "includes/footer.html" %}
</footer>
Create an include template (eg. myapp/templates/includes/feedback_form.html)
{% load feedback_form_tags wagtailcore_tags %}
{% get_feedback_form as feedback_form %}
<form action="{% pageurl feedback_form.page %}" method="POST" role="form">
<h3>{{ feedback_form.page.title}}</h3>
{% csrf_token %}
{{ feedback_form.form.as_p }}
<input type="submit">
</form>
Build a Template Tag to get the form and page
Your template tag needs to build the form with the page's self.get_form() function. Eg. you your template tag (base/templatetags/feedback_form)
from django import template
from myapp.models import MyCustomSettings
register = template.Library()
# https://docs.djangoproject.com/en/1.9/howto/custom-template-tags/
#register.assignment_tag(takes_context=True)
def get_feedback_form(context):
request = context['request']
my_custom_settings = MyCustomSettings.for_site(request.site)
feedback_form_page = my_custom_settings.feedback_form_page.specific
form = feedback_form_page.get_form(
page=feedback_form_page, user=request.user)
return {'page': feedback_form_page, 'form': form}
This still works in wagtail 2.3 just need to replace
#register.assignment_tag(takes_context=True)
with
#register.simple_tag(takes_context=True) to conform with django 2.2
Also {% load feedback_form_tags wagtailcore_tags %} assumes your file inside of templates tags is named feedback_form_tags.py. I also added an __init__.py in the template tags folder although I'm not sure that was actually necessary.
I have a base template which contains header, footer and a block "content" which then I override in different CBVs.
There is little "user-space" divinside a header where I want to keep user's info in case he is logged in and a login form if he is a guest.
Right now the only way that comes in mind is to create a django app and use it as a tag. But I think there is a better solution. Because as far as I know tags can slow down django project in future.
Also I think that maybe I would like to manipulate this div from a view which renders a child template. For example I calculate and display some value on a page but also I want to display it in a "user-space" div as well. I think this can be achieved by pushing data to the user's session and then using this while rendering "user-space" div from another code.
Assuming you have django.contrib.auth.user in your INSTALLED_APPS, you can access the user's login status using user.is_authenticated():
{% if user.is_authenticated %}
<div>Welcome back, {{ user.username }} | <a href='/logout/'>Logout</a></div>
{% else %}
<div>
<form action='/login/' method='POST'>
{{ csrf_token }}
{{ login_form }}
<input type='submit'>
</form>
</div>
{% endif %}
Edit:
In response to your comment:
Let's suppose client does a POST request by which we calculate some number - total price. And I need to display it in that div.
As documented
Define your view:
from django.shortcuts import render
from .forms import MyForm
def simple_view(request):
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = MyForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
result = form.cleaned_data['some_input'] * 50
return render(request, 'my_template.html', {'result': result})
# if a GET (or any other method) we'll create a blank form
else:
form = MyForm()
return render(request, 'my_other_template.html', {'form': form})
Display result in your template:
<!-- my_template.html -->
<div>{{ result }}</div>
Maybe you need to be more specific with your question, this is what I think you are looking for though. You should put logic like you are describing into a view, not a template.