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.
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>
let's say, I have following django code......
views.py
from extra_views import CreateWithInlinesView, UpdateWithInlinesView, InlineFormSetFactory
class ItemInline(InlineFormSetFactory):
model = Item
fields = ['sku', 'price', 'name']
class ContactInline(InlineFormSetFactory):
model = Contact
fields = ['name', 'email']
class CreateOrderView(CreateWithInlinesView):
model = Order
inlines = [ItemInline, ContactInline]
fields = ['customer', 'name']
template_name = 'order_and_items.html'
def get_success_url(self):
return self.object.get_absolute_url()
and in the html template:
<form method="post">
...
{{ form }}
{% for formset in inlines %}
{{ formset }}
{% endfor %}
...
<input type="submit" value="Submit" />
</form>
Now the problem is: I need both inlines i.e. ItemInline and ContactInline in different section of html code within a single template. What should the solution for this?
Solution: Use Counter within a foorloop in template.
<form method="post">
...
{{ form }}
{% for formset in inlines %}
{% if forloop.counter == 1 %}
Item:
{{ formset }}
{% elif forloop.counter == 2 %}
Contact:
{{ formset }}
{% endfor %}
...
<input type="submit" value="Submit" />
</form>
I'm modifying the default article.html template that came with Aldryn Newsblog to allow for a comment form and listing of the comments for that specific article. I have included the form without a problem. But I can't figure out how to query the comments.
EDITED
Here is my list_comments.html template:
{% load cms_tags staticfiles sekizai_tags %}
{% if comments %}
{% for item in comments %}
<div class="comment paragraph">
<h4>{{ item.author }}</h4>
<p>{{ item.comment }}</p>
<p>{{ item.date }}</p>
</div>
{% endfor %}
{% else %}
<p>No comments exist on this blog. Be the first to comment!</p>
{% endif %}
and comment_form.html
{% load cms_tags staticfiles sekizai_tags %}
<div id="comment_form">
<div class="container constrained paragraph">
<h5>Submit a comment</h5>
<form method="post">
{% csrf_token %}
{{ comment_form }}
<input type="hidden" name="page" value="{{ article.id }}">
<input type="submit" value="Submit Comment">
</form>
</div>
And models.py:
class BlogComment(models.Model):
ip_address = models.CharField(max_length=255, verbose_name="IP Address")
date = models.DateTimeField(default=datetime.now)
article = models.CharField(max_length=255)
author = models.CharField(max_length=255)
comment = models.CharField(max_length=1000)
And in views.py I have these:
def display_form(request):
comment_form = CommentForm()
return render(request, 'comment_form.html', {'comment_form': comment_form})
def get_blog_comments(request):
qs = BlogComment.objects.all()
context = {'comments': qs, 'another': 'test'}
return render(request, 'list_comments.html', context)
And in both templates, the context variables are outputting nothing. I am at a loss for what I'm doing wrong. django.template.context_processors.request is included in my settings.py context_processors.
As already stated, the querying is done in your views.py file.
# views.py
def get_blog_comments(request):
if request.method == "GET":
qs = BlogComment.objects.all()
template = # location of template, ex. blog_list.html
context = {'obj_list': qs}
return render(request, template, context)
How to implement working SearchView in existing views.py?
I already have CBV, and added in urls.py as /moderate and want to apply search form in it. but always got "Results No results found."
This is my /moderate page with 3 forms, using SearchView and piece of code from tutorial in template.
And this from /search page, with urls(r'^search/$', include('haystack.urls'))
urls.py
urlpatterns= [
url(r'^search/', include('haystack.urls')),
url(r'^moderate/', Moderate.as_view(), name='moderate'),
]
views.py
class Moderate(SearchView):
#method_decorator(staff_member_required)
def dispatch(self, *args, **kwargs):
return super(Moderate, self).dispatch(*args, **kwargs)
#model = Ad
template_name = 'adapp/ad_moderate.html'
#template_name = 'search/search.html'
paginator_class = DiggPaginator
paginate_by = 10
ad_type = None
ad_sub_type = None
def get_queryset(self):
qs = super(Moderate, self).get_queryset().filter(ad_type__isnull=False,
ad_sub_type__isnull=False)
return qs
def get_context_data(self, **kwargs):
context = super(Moderate, self).get_context_data(**kwargs)
context['filter'] = ModerateFilter(self.request.GET)
return context
# define method to recieve fields from form, and change data accordings
def post(self, request, *args, **kwargs):
selected = request.POST['selected']
record = Ad.objects.get(pk=int(selected))
form = ModerateForm(request.POST, instance=record)
if form.is_valid():
form.save(commit=True)
return HttpResponseRedirect('')
template/ad_moderate.html
{% extends 'base.html' %}
{% load i18n url_tags %}
{% block content %}
<div id="casing">
<div id="content">
{# filter form, to show only models with moderated=True #}
<form action="" method="get">
{{ filter.form.as_p }}
<input type="submit">
</form>
<h2>Search</h2>
{# search form right from tutorial #}
<form method="get" action="">
<table>
{{ form.as_table }}
<tr>
<td> </td>
<td>
<input type="submit" value="Search">
</td>
</tr>
</table>
{% if query %}
<h3>Results</h3>
{% for result in page.object_list %}
<p>
{{ result.object.title }}
</p>
{% empty %}
<p>No results found.</p>
{% endfor %}
{% else %}
{# Show some example queries to run, maybe query syntax, something else? #}
{% endif %}
</form>
{% for object in filter %}
{# a lot of template tags and third form to change value of model #}
<form action="" method="POST">
{% csrf_token %}
<input type="radio" name="moderated" value="True">Accept
<br>
<input type="radio" name="moderated" value="False">Decline
<input type="hidden" value="{{ object.id }}"
name="selected">
<input class="btn" type="submit" value="moderate">
</form>
search_indexes.py
from .models import Ad
class AdIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
def get_model(self):
# my model, with one search should be
return Ad
templates/search/indexes/app/ad_text.txt
{{ object.title }}
{{ object.short_desc }}
{{ object.description }}
{{ object.experience }}
{{ object.skills }}
{{ object.name }}
{{ object.city }}
get_context_data():
context['search'] = SearchForm(self.request.GET).search()
Would solve a problem.
That means, I should create form and send return from .save() method, rather that django-like form instance.
When I enter an invalid email adress I cant see an error message like "This is not an invalid email".
My comment_form.html:
{% load i18n %}
<form action="/comment/create/" method="post">
{% csrf_token %}
{{ form.errors }}
{% for field in form %}
<div class="fieldWrapper">
{{ field.label_tag }}
{{ field }}<p>
</div>
{% endfor %}
<input type="hidden" name = "object_id" value="{{object_id}}" />
<input type="hidden" name= "next" value="{{ next }}" />
<input type="submit" value="{% trans "Submit" %}">
</form>
my post_detail.html:
extends "base.html" %}
{% block content %}
<div id="exap">
{{ post.content }}
</div>
<div class="comment">
{% for comment in comments %}
<user>{{ comment.owner }}</user>
{{ comment.content}}
{% endfor %}
</div>
{% include "comment_form.html" %}
{% endblock %}
this is my comment.views
def create(request):
if request.method == 'POST':
form = CommentForm(request.POST)
email = request.POST.get('email')
next = request.POST.get('next')
if form.is_valid():
content_type = ContentType.objects.get(app_label="post", model="post")
object_id = request.POST["object_id"]
comment = Comment.objects.create(
content_type = content_type,
object_id = object_id,
content = request.POST.get('content'),
owner= request.POST.get('owner'),
email = request.POST.get('email')
)
else:
print form.errors
else:
form = CommentForm()
return HttpResponseRedirect(next)
Error message doesnt display in template ?
Where am I wrong ?
karthikr is trying to tell you what is wrong in the comments. You are not using the form to validate, so it won't show any errors. Instead of doing if validateEmail(email) you should have the email validation code inside the form class, and in the view you call if form.is_valid().
Plus, when you do write the form's clean_email method, you should not be catching ValidationError: that's the way that errors are passed on to the form's errors list.