I am trying to make a search field on my homepage where you search entries by tag, and within that search field as you type in letters it should suggest you tags that contain what you have typed so far. I am using django-taggit for tags.
I have followed this tutorial :
https://django-autocomplete-light.readthedocs.io/en/master/taggit.html
It has support for django-taggit.
template
<div class="search-container">
<form method="post">
{% csrf_token %}
{% for field in form %}
{{ field.label_tag }}
{{ field }}
{% endfor %}
<button type="submit">Search</button>
</form>
</div>
urls.py
# AUTOCOMPLETE URL
url(r'^tag-autocomplete/$', views.TagAutocomplete.as_view(), name='tag-autocomplete'),
forms.py
class SearchForm(autocomplete.FutureModelForm):
class Meta:
model = Intrare
fields = ('tags',)
widgets = {
'tags': autocomplete.TaggitSelect2('intrari:tag-autocomplete')
}
models.py
class Intrare(models.Model):
tags = TaggableManager()
def __str__(self):
return self.titlu
views.py
class TagAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
intrari = [intrare.tags for intrare in Intrare.objects.filter(public=True)]
tags = reduce(lambda x, y: x | y, [tags.get_queryset() for tags in intrari])
tags = [tag.name for tag in tags]
qs = Tag.objects.filter(name__in=tags)
if self.q:
qs = qs.filter(name__contains=self.q)
return qs
Here is the result. The widget does not show properly
I have found the mistake, I forgot to add {{ form.media }} in template.
<div class="search-container">
{{ form.media }}
<form method="post">
{% csrf_token %}
{% for field in form %}
{{ field.label_tag }}
{{ field }}
{% endfor %}
<button type="submit">Search</button>
</form>
</div>
Related
I'm trying to access the instance of the forms in a formset, but it is not working. I CAN access them using the variable notation, as in {{ form }}, but not in code, as in {% url 'section' form.instance.pk %}. I need to iterate through the forms in the formset along with the corresponding model instance.
My view:
# views.py
def sec(request, companyurl):
company = get_if_exists(Company, author=request.user)
SectionFormSet = modelformset_factory(Section, form=SectionForm, can_delete=True)
sections = Section.objects.filter(company=company).order_by('order')
formset = SectionFormSet(request.POST or None,
initial=[{'company': company}],
queryset=sections
context = {
'sections': sections,
'formset': formset,
}
return render(request, 'questions/sections.html', context)
My model:
# models.py
class Section(models.Model):
section = models.CharField(max_length=100)
company = models.ForeignKey(Company, on_delete=models.CASCADE)
order = models.PositiveIntegerField(default=1000000)
show = models.BooleanField(default=True)
def __str__(self):
return self.section
My Form (I'm using django-crispy forms):
# forms.py
class SectionForm(forms.ModelForm):
class Meta:
model = Section
fields = ['company', 'section', 'show', 'order']
labels = {
'section': '',
'show': 'Show'
}
def __init__(self, *args, **kwargs):
super(SectionForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_tag = False
self.helper.layout = Layout(
Div(
Div(HTML("##"), css_class = 'my-handle col-auto'),
Div('section', css_class='col-3'),
Div('show', css_class = 'col-auto'),
Div('DELETE', css_class = 'col-auto'),
Field('company', type='hidden'),
Field('order', type='hidden'),
css_class='row',
),
)
My template (this is where the problem is seen):
<form action="#" method="post">
{% csrf_token %}
{{ formset.management_form }}
<div id="simpleList" class="list-group">
{% for fo in formset %}
<div class="list-group-item hold">
{% crispy fo %}
<!-- TESTING TO SEE IF THIS WORKS, AND IT DOES! -->
{{ fo.instance }} + {{ fo.instance.pk }} + {{ fo.instance.section }}
<!-- THE PROBLEM OCCURS WHEN THIS IS ADDED -->
<a href="{% url 'section' fo.instance.pk fo.instance.section %}">
{{ fo.instance }}
</a>
<!-------------------------------------------->
<input type="hidden" name="order" value="{{ section.pk }}">
{% for hid in fo.hidden_fields %}
{{ hid }}
{% endfor %}
</div>
{% endfor %}
<button type="submit" class="btn btn-outline-primary">Save changes</button>
</form>
When I add the <a href="{% url 'section' fo.instance.pk fo.instance.section %}>link</a> line I get
Reverse for 'section' with arguments '(None, '')' not found. 1 pattern(s) tried: ['section/(?P<pk>[0-9]+)/(?P<section>[^/]+)\\Z']
The error is clear. fo.instance.pk is None and fo.instance.section is an empty string. Yet when I remove the anchor tag, the line above appears and shows the correct values for both of these. I think I know the difference in how the {{ }} and the {% %}, and I thought I knew how model form instances were tied to the model, but I am missing something.
Thanks for any help.
Formsets create blank forms
The answer was staring me in the face, when I printed the results. The last form, a blank, of course was giving me None and an empty string, since it had no data to fill it with. Thus the simple solution is to check for this before trying to form the url with the information. Therefore, this has nothing to do with the differences between {{ }} and {% %} nor form instances.
{% for fo in formset %}
<div class="list-group-item hold">
{% crispy fo %}
<!-- TESTING TO SEE IF THIS WORKS, AND IT DOES! -->
{{ fo.instance }} + {{ fo.instance.pk }} + {{ fo.instance.section }}
<!-- THE PROBLEM OCCURED WHEN THIS WAS ADDED -->
<!-- THE SIMPLE SOLUTION: --------------------->
{% if fo.instance.pk %}
<a href="{% url 'section' fo.instance.pk fo.instance.section %}">
{{ fo.instance }}
</a>
{% endif %}
<!-------------------------------------------->
<input type="hidden" name="order" value="{{ section.pk }}">
{% for hid in fo.hidden_fields %}
{{ hid }}
{% endfor %}
</div>
{% endfor %}
<button type="submit" class="btn btn-outline-primary">Save changes</button>
</form>
I have not been able to tell why this model query returns an empty queryset...
Here are my models:
class Marks(models.Model):
klass = models.ForeignKey(Klass,on_delete=models.SET_NULL,null=True,blank=True)
stream = models.ForeignKey(Stream,on_delete=models.SET_NULL,null=True,blank=True)
mark = models.IntegerField()
class Klass(models.Model):
name = models.CharField(max_length=20)
The view.
def ResultsView(request):
query = request.GET.get('klass')
if query:
queryset = (Q(klass__name__icontains=query))
the_student = Marks.objects.filter(queryset).distinct()
all_results = {'the_student':the_student,'query':query}
else:
all_results = {}
return render(request,'exams.html',all_results )
The form template
<form action="{% url 'search_marks' %}" method="GET">
<div class="input-group">
<input class="" style="flex:50%" type="text" name="klass">
<button class="btn btn-primary" type="submit"></button>
</div>
</form>
The url
path('search_m',ResultsView,name='search_marks'),
I try getting the results here
{% for mark in the_student %}
{{ mark }}
{% endfor %}
When I print the_student from the view it gives <QuerySet []>
When I try queryset = (Q(mark__icontains=query)) brings an answer for the mark.
I only want a result for klass
I think you are using the whole queryset in your template.
Try
{% for mark in the_student %}
{{ mark.klass }}
{% endfor %}
the_Student is your response key but you use the_student.
the_student != the_Student
you just change the
{% for mark in the_student %}
{{ mark.klass }}
{% endfor %}
to
{% for mark in the_Student %}
{{ mark.klass }}
{% endfor %}
I have rendered a html form with widget_tweaks and i want the default value of the field to be the current username.
#template
{% if user.is_authenticated %}
<form method="post">
{% render_field form.title value="{{ request.user }}" readonly="True" %}
</form>
{% else %}
<h 1>Login First</h 1>
{% endif %}
but this render the exact text "{{ request.user }}" rather than printing the username. If I use the tag and use the {{ request.user }}, prints the current username.
This is how my views.py looks:
views.py
class CreatePostView(CreateView):
template_name = 'posts/new_post.html'
redirect_field_name = 'posts/post_detail.html'
form_class = PostForm
model = Post
def get_absolute_url(self):
return reverse('posts:post_detail', args = [self.id])
In django templatetags, you do not need double accolades {{ }}. Try the following:
<!-- Your template -->
[...]
{% render_field form.title value=request.user readonly="True" %}
[...]
I just removed the double accolades.
I have a form class that looks like..
#forms.py
class ExampleForm(forms.Form):
color = forms.CharField(max_length=25)
description = forms.CharField(widget=forms.Textarea, max_lenght=2500)
and my view looks like this..
#views.py
class EditExample(UpdateView):
model = Example
fields = ['color', 'description']
template_name = 'example.html'
def get_success_url(self):
pass
Template:
#example.html
{% for field in form %}
{% if field.errors %}
<div class="control-group error">
<label class="control-label">{{ field.label }}</label>
<div class="controls">{{ field }}
<span class="help-inline">
{% for error in field.errors %}{{ error }}{% endfor %}
</span>
</div>
</div>
{% else %}
<div class="control-group">
<label class="control-label">{{ field.label }}</label>
<div class="controls">{{ field }}
{% if field.help_text %}
<p class="help-inline"><small>{{ field.help_text }}</small></p>
{% endif %}
</div>
{% endif %}
{% endfor %}
When the template is rendered, all the fields show up and populate correctly but the 'description' doesn't show up in a Textarea but rather in a normal field. Im assuming this is because UpdateView works off of 'model = something' rather than 'form = something'.
I have tried..
#views.py
class EditExample(UpdateView):
model = Example
form_class = Exampleform
template_name = 'example.html'
def get_success_url(self):
pass
but I get a Django error saying "init() got an unexpected keyword argument 'instance'.
Is there any way to successfully get the Description to render in a Textarea using Updateview? If not, how would I accomplish this?
Thanks!
Your form needs to inherit from forms.ModelForm, not the base Form class.
I have a very simple ModelForm in my app that looks like this:
# ModelForm
class ProductForm(ModelForm):
class Meta:
model = MyModel
exclude = ['created', 'last_modified', 'serial_number']
# Model
class BaseModel(models.Model):
created = models.DateTimeField(auto_now_add=True, blank=True, null=True)
last_modified = models.DateTimeField(auto_now=True, blank=True, null=True)
class MyModel(BaseModel):
product = models.TextField(verbose_name='Product Name')
serial_number = models.TextField(verbose_name='Serial Number')
And a form that looks like this:
# Form
<form method="POST" action="{% url some_url %}">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
{% for field in form %}
{% if field.errors %}
<div>{{ field.errors }}</div>
{% endif %}
<div>
{{ field.label_tag }}:
{{ field }}
</div>
{% endfor %}
{% endfor %}
<div class="actions">
<input class="button submit focus" type="submit" value="{% trans "Save" %}" />
</div>
</form>
When I check out the view using this, I just see a colon (:) followed by the textfield: The label is gone.
According to the documentation for ModelForm:
In addition, each generated form field has attributes set as follows:
...
The form field’s label is set to the verbose_name of the model field, with the first character capitalized.
What mistake have I made?
I am using Django 1.4.1 if it matters.
You have to put the field label inside a <label> tag. So:
<div>
<label for="id_{{field.html_name}}">{{field.label}}:</label>
{{ field }}
</div>
The only solution I managed to find that still allowed me to separate each row of the form was doing the following:
<form method="POST" action="{% url some_url %}">
{% csrf_token %}
{{ formset.as_ul }}
<div class="actions">
<input class="button submit focus" type="submit" value="{% trans "Save" %}" />
</div>
</form>
... the key piece being the {{ formset.as_ul }} instead of iterating through each field.
As for why the other listed solution (or the solution in the documentation) didn't work, I will remain baffled.