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>
Related
Good afternoon Community,
I hope you are all well.
I am building my first website and I have the following problem; when I try to create a new user, if the user enters the wrong data the template does not show the error. Any hints?
Template:
<form action= "" method='post'>
{% csrf_token %}
{% for field in form %}
<p>{{field.label}}{{field}}</p>
{% endfor %}
<button type="submit" class="btn btn-success">Create User</button>
Views.py:
def register_page(request):
form = UserForm
if request.method == 'POST':
form = UserForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('http://127.0.0.1:8000/login_user/')
context = {'form' : form}
return render(request, 'simple_investing/register.htm', context)
Forms.py:
class UserForm(UserCreationForm):
class Meta:
model = User
fields = ('username', 'email', 'password1', 'password2')
As is discussed in the rendering fields manually section of the documentation, for the fields you should also render {{ field.errors }}, and the {{ form.non_field_errors }} which deals with errors not specific to one form.
The template thus should look like:
<form action= "" method="post">
{% csrf_token %}
{{ form.non_field_errors }}
{% for field in form %}
<p>
{{ field.errors }}
{{ field.label }}
{{ field }}
</p>
{% endfor %}
<button type="submit" class="btn btn-success">Create User</button>
</form>
The section also discusses how to enumerate over the errors, and apply certain styling to these errors.
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>
The form doesn't display in the browser. The navbar and submit button show up but no form in between. The problem must be straightforward but I haven't been able to find the issue. Thank you for your help.
views.py
def ProductCreateView(request):
if request.method == 'POST':
form = ProductForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('set_app/product_list.html'))
else:
product_form = ProductForm()
return render(request, 'set_app/product_form.html', {'product_form':product_form})
forms.py
class ProductForm(forms.Form):
class Meta():
model = models.Product
fields = ('code', 'barcode', 'name', 'description', 'brand', 'status')
product_form.html
{% extends "set_app/basic_app_base.html" %}
{% block body_block %}
<h1>
{% if not form.instance.pk %}
Create Product
{% else %}
Update Product
{% endif %}
</h1>
<form method="post">
{% csrf_token %}
{{ product_form.as_p }}
<input type="submit" class="btn btn-primary" value="Submit">
</form>
{% endblock %}
Found the issue:
in forms.py
instead of
class ProductForm(forms.Form):
it should be
class ProductForm(forms.ModelForm):
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'm trying to create a simple todo list using built-in generic views.
Here's my views.py
class TaskList(ListView):
paginate_by = 5
template_name = 'todo/index.html'
context_object_name = 'formset'
def get_queryset(self):
return TaskFormSet(queryset=Task.objects.all())
def post(self, request):
formset = TaskFormSet(request.POST)
if formset.has_changed() and formset.is_valid():
formset.save()
return redirect('/todo')
And here's my template
<form method="post">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
<div>
{% for field in form %}
{{ field }}
{% endfor %}
</div>
{% endfor %}
<input type="submit" value="+">
</form>
So when I submit form I get ['ManagementForm data is missing or has been tampered with']
What's the deal?