I am trying to implement django-autocomplete-light in my projects but cannot figure out why it does not show me the autocomplete widget, but keeps showing an empty dropdown.
I followed the tutorial: https://django-autocomplete-light.readthedocs.io/en/3.1.3/tutorial.html.
I found that this problem has occurred in other stackoverflow questions, but none of those answers have helped me so far.
I have the following model:
class Vilt(models.Model):
vilt_title = models.CharField(max_length=200, unique=True)
I created this autocomplete view:
class ViltAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
# Don't forget to filter out results depending on the visitor !
# if not self.request.user.is_authenticated():
# return Vilt.objects.none()
qs = Vilt.objects.all().order_by('vilt_title')
if self.q:
qs = qs.filter(vilt_title__istartswith=self.q)
return qs
I use this ModelForm where I specify the widget.
from .models import Vilt
from dal import autocomplete
class ViltSearchForm(forms.ModelForm):
vilt_title = forms.ModelChoiceField(
queryset = Vilt.objects.all(),
widget = autocomplete.ModelSelect2(url='vilt-autocomplete')
)
class Meta:
model = Vilt
fields = ('vilt_title',)
from .views import (ViltAutocomplete,
)
urlpatterns = [
#other paths
path('vilt/autocomplete/', ViltAutocomplete.as_view(), name='vilt-autocomplete'),
#other paths
]
{% extends "bierviltje/base.html" %}
{% load static %}
{% load crispy_forms_tags %}
{% block content %}
<div class="container">
#other forms
<div>
<form action="" method="post">
{% csrf_token %}
{{ vilt_search_form|crispy }}
<input type="submit" />
</form>
</div>
#other forms
</div>
{% endblock content %}
{% block javascript %}
{{ vilt_search_form.media }}
{% endblock javascript %}
This is the Javascript that is loaded in before the javascript block in base.html:
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
{% block javascript %}
{% endblock javascript %}
It's been sometime since you posted your query. But in case you have not found the answer yet, here is the solution:
In your ModelForm "ViltSearchForm", please change the widget from:
widget = autocomplete.ModelSelect2(url='vilt-autocomplete')
to:
widget = autocomplete.ListSelect2(url='vilt-autocomplete')
However, if I may add here, I can't fathom the reason for using "autocomplete" on a stand alone model.
A feedback would be much appreciated.
Related
I'm trying to create a frontend data entry page for an existing model. However, when clicking the link, I get an error:
crispy_forms.exceptions.CrispyError: |as_crispy_field got passed an invalid or inexistent field
Just to be clear, adding the data from Django Admin works with no issues at all.
Having looked through a number of answered questions here, one did highlight what I believe could be problem, but it was out of context and did not provide much of an explanation.
I am trying to create a frontend entry form for users that corresponds with a foreign key.
models.py
class NewHandoff(models.Model):
handoff_pk = models.AutoField(primary_key=True)
handoff_date = models.DateField(auto_now_add=True,verbose_name="Handoff Date")
shift1_pri = models.ForeignKey(Engineer,on_delete=models.CASCADE,verbose_name="Shift 1 Primary")
shift1_sec = models.ForeignKey(Engineer,on_delete=models.CASCADE,verbose_name="Shift 1 Secondary")
def __str__(self):
return f"{self.handoff_date}"
class Meta:
verbose_name_plural = 'Handoffs'
# New Handoff Form
class NewHandoffForm(forms.ModelForm):
class Meta:
model = NewHandoff
fields = ['shift1_pri','shift1_sec']
views.py
from django.shortcuts import redirect, render
from django.views import View
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http.response import HttpResponse
from django.contrib import messages
from .models import AttentionForm, NewHandoffForm
# Handoff View Page
class NewHandoffView(LoginRequiredMixin,View):
def get(self, request):
greeting = {}
greeting['heading'] = "New Handoff"
greeting['pageview'] = "Handoff"
return render (request,'handoff/handoff-new.html')
def post(self, request):
if request.method == "POST":
if "add-new-handoff-button" in request.POST:
create_new_handoff_form = NewHandoffForm(request.POST)
create_new_handoff_form.save()
return redirect("/handoff/handoff-create")
handoff-new.html
{% extends 'partials/base.html' %}
{% load static %}
{% load humanize %}
{% load crispy_forms_tags %}
{% block extra_css %}
<link href="{% static 'libs/bootstrap-datepicker/dist/css/bootstrap-datepicker.min.css' %}" rel="stylesheet">
{% endblock %}
{% block contents %}
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-body">
<!-- New Form -->
<form method="POST">
{% csrf_token %}
<div class="row">
<div class="row-fluid pb-1">
<!-- Field 1 -->
<div class="mb-3">
{{ form.shift1_pri|as_crispy_field }}
</div>
<!-- End of Field 1 -->
</div>
</div>
<div class="d-flex flex-wrap gap-2">
<button type="submit" class="btn btn-primary waves-effect waves-light" name="add-new-handoff-button">Create New Handoff</button>
</div>
</form>
<!-- End of New Form -->
</div>
</div>
</div>
</div>
{% endblock %}
{% block extra_javascript %}
{% endblock %}
Someone mentioned in another post that forms should correlate with the declared form name {{ form.shift1_mod|as_crispy_field }} so it should actually be {{ create_new_handoff_form.shift1_mod|as_crispy_field }} but I have tried changing this and still get the same problem, plus, another model form works fine with just form despite the name of the form being attention_form.
Does anyone have any idea or can point me in the right direction? :)
You are not passing the form through the context in the template. As you are inheriting View, Add the following line in the get() and afterwards in the post() method appropriately:
form = NewHandoffForm()
# and then change return
return render(request,'handoff/handoff-new.html', {'form': form })
Also, you have a space after render in the get function. I hope this is a typo here, but not in your code.
bookinstance_form.html
{% extends "catalog/base_generic.html" %}
{% block content %}
<form action="" method="post">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<input type="submit" value="Submit" />
</form>
{% endblock %}
urls.py
path('bookinstance/create/', views.BookInstanceCreate.as_view(), name='bookinstance_create'),
path('bookinstance/<uuid:pk>/update/', views.BookInstanceUpdate.as_view(), name='bookinstance_update'),
path('bookinstance/<uuid:pk>/delete/', views.BookInstanceDelete.as_view(), name='bookinstance_delete'),
views.py
class BookInstanceCreate(CreateView):
model = BookInstance
fields = '__all__'
class BookInstanceUpdate(UpdateView):
model = BookInstance
fields = '__all__'
class BookInstanceDelete(DeleteView):
model = BookInstance
success_url = reverse_lazy('catalog:books')
https://developer.mozilla.org/zh-CN/docs/Learn/Server-side/Django/Forms has all course
How to use int:pk in class-based general views, adding bookinstance needs to be associated with Book, so I need to know book.id, but I don't know how to write it in views.BookInstanceCreate.
If i understand your question. Every time you fill some model Django automaticly create ID for him. You can call this using int:pk tag. Use classic href
{{ url "bookinstance_update" BookInstance.id }} and make query of your books - >
{% for something in BookInstamce%} i Hope thats what you asked for.
I'm working on a django bookstore website and there seems to be an error with stripe integration. I have an orders page that asks for payment information (I'm using the test API for now). I get the same error "You did not set a valid publishable key. Call Stripe.setPublishableKey() with your publishable key."
orders/views.py
from django.conf import settings
from django.views.generic.base import TemplateView
class OrdersPageView(TemplateView):
template_name = 'orders/purchase.html'
def get_context_data(self, **kwargs):
##Stripe.setPublishableKey('PUBLISHABLE_KEY')
context = super().get_context_data(**kwargs)
context['stripe_key'] = settings.STRIPE_TEST_PUBLISHABLE_KEY
return context
templates/orders/purchase.html
{% extends '_base.html' %}
{% block title %}Orders{% endblock title %}
{% block content %}
<h1>Orders page</h1>
<p>Buy for $39.00</p>
<script src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="{{ stripe_key }}"
data-description="All Books"
data-amount="3900"
data-locale="auto">
</script>
{% endblock content %}
In your forms you need a {% csrf_token %} and form action that takes you to the charge page.
<form action="{% url 'charge' %}" method="post">
{% csrf_token %}
<h1>Orders page</h1>
<p>Buy for $39.00</p>
<script src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="{{ stripe_key }}"
data-description="All Books"
data-amount="3900"
data-locale="auto">
</script>
</form>
Also unless never set your pricing in your templates, this is asking for trouble. Set them in your view.
In short - I have a bootstrap carousel and it works nicely, however I can't get it to display only fields with 'featured' set to 'true'
I have tried doing for post in posts.objects.featured (the carousel literally does not show up at all then) and variations like posts.objects.filter(featured=True) (it says it can't parse the remainder).
Here's the code from the template where I am trying to display the carousel image only with items with featured=True
{% for post in posts.objects.featured %}
<div class="carousel-item {% if forloop.first %}active{% endif %} ">
{% image post.image fill-1920x500 %}
<div class="carousel-caption d-none d-md-block">
<h2 id="inner-carousel-title">{{post.title}}</h2>
<h4><a href="{% pageurl post %}" style="color:white;text-shadow:2px 2px 4px #000000" >something</a></h4>
</div>
</div>
{% endfor %}
Again, I just want the carousel to show up only with featured posts
As a side note- it'd be awesome if it only showed 3 posts.
EDIT - Here's my model.py for the page
class BlogPage(RoutablePageMixin, Page):
description = models.CharField(max_length=240, blank=True)
content_panels = Page.content_panels + \
[FieldPanel("description", classname="full")]
def get_context(self, request, *args, **kwargs):
context = super(BlogPage, self).get_context(request, *args, **kwargs)
context['posts'] = self.posts
context['blog_page'] = self
return context
If you really want to do this in the template do:
{% for post in posts %}
{% if post.featured %}
<div> ... <div/>
{% endif %}
{% endfor %}
But you can also pass only the featured posts to your template in your view. Just add:
...
featured_posts = Post.objects.filter(featured=True)[:4]
return render('post_list.html', {'featured_posts': featured_posts, ...})
If you’re using Django’s generic ListView and you’re only showing the featured posts, you can set the queryset property to filter only the featured posts. If you’re also showing the other posts in your ListView, add the featured_posts to your context by overriding get_context_data().
You can try this if the way I suggested in the comment doesn't work
{% for post in posts %}
{% if post.featured %}
// write down your stuff
{% endif %}
{% endfor %}
I wrote a simple app that is a custom DateField widget for mezzanine. Afaik it's, it's a simple case and besides overextending a template it would be the same in pure django or django-cms (feel free to correct me if I'm wrong).
The widget:
class DatePickerInput(forms.DateInput):
def __init__(self, attrs = None, format = None):
super(DatePickerInput, self).__init__(attrs, format)
self.attrs["class"] = "datepicker"
class Media:
css = { "all": ('css/ui-lightness/jquery-ui-1.10.3.custom.min.css',) }
js = (
"mezzanine/js/" + getattr(settings, "JQUERY_UI_FILENAME", "jquery-ui-1.9.1.custom.min.js"),
"js/datepicker_setup.js",)
I overextend base.html template to insert form.media:
{% overextends "base.html" %}
{% load pages_tags mezzanine_tags i18n future staticfiles %}
{% block extra_head %}{{ block.super }}
{{ form.media }}
{% endblock %}
Now, I create a form for my model class.
Here's the class:
class PlayerProfile(models.Model):
user = models.OneToOneField("auth.User")
# Can be later changed to use a setting variable instead of a fixed date
date_of_birth = models.DateField(default=date(1990, 1, 1))
Here's the model form:
from DateWidgets.widgets import DatePickerInput
from PlayerProfiles.models import PlayerProfile
class EditPlayerProfileForm(Html5Mixin, forms.ModelForm):
class Meta:
model = PlayerProfile
fields = ("date_of_birth", )
widgets = { 'date_of_birth': DatePickerInput }
def __init__(self, *args, **kwargs):
super(EditPlayerProfileForm, self).__init__(*args, **kwargs)
Here's the view:
#login_required
def profile_update(request, template="accounts/account_profile_update.html"):
"""
Profile update form.
"""
pform = forms.EditPlayerProfileForm
player_form = pform(request.POST or None, request.FILES or None, instance=request.user.playerprofile)
context = {"pform": player_form, "title": _("Update Profile"), "profile_user": request.user}
return render(request, template, context)
Here's the template:
{% overextends "accounts/account_profile_update.html" %}
{% load i18n mezzanine_tags %}
{% block main %}
<fieldset>
<legend>{{ title }}</legend>
<form method="post"{% if pform.is_multipart %} enctype="multipart/form-data"{% endif %}>
{% fields_for pform %}
<div class="form-actions">
<input class="btn btn-primary btn-large" type="submit" value="{{ title }}">
</div>
</form>
</fieldset>
{% endblock %}
Now if I view the form in a browser, the custom widget is there (I can tell because the input html tag has my custom class attribute value) but it doesn't inject the form media, it's missing. Any idea what's going on here? Thanks in advance! Cheers :-)
form isn't available in the template, because you've called your form variable pform.
Try {{ pform.media }}.
I was googled here with the same problem under different conditions and spotted another error that may appear under other conditions (my case is extending change_form.html in Django 2.1): I had to use extrahead instead of extra_head
{% block extrahead %}{{ block.super }}
{{ form.media }}
{% endblock %}