Change the name of output of form-variables Django - html

I'm following this Django guide for creating a "recipe" home-page, and I'm completly new to Django and html.
I am using the CreateView class for creating a new class of the instance opskrift
class opskrift(models.Model):
title = models.CharField(max_length=100)
algorithm = models.TextField()
time_taken = models.CharField(max_length=10)
prep_time = models.CharField(max_length=10)
n_persons = models.CharField(max_length=5)
def __str__(self):
return self.title
with the view
class OpskriftCreateView(CreateView):
model = opskrift
fields = ["title","algorithm","time_taken","prep_time","n_persons"]
The problem is, that it displays the variable names i.e n_persons, prep_time on the homepage etc. but I would like to make it Number of persons, Preperation time.
Is there a way to do so using the template below
{% extends "indkoeb/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="OPSKRIFT">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">New</legend>
{{form|cripsy}}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Save</button>
</div>
</form>
</div>
{% endblock content %}

class opskrift(models.Model):
title = models.CharField(max_length=100)
algorithm = models.TextField()
time_taken = models.CharField(max_length=10)
prep_time = models.CharField(max_length=10,verbose_name="Preperation time")
n_persons = models.CharField(max_length=5,verbose_name='Number of persons')

Related

Django MPTT, can't get parent_id for threaded comments reply

My Problems are as follows:
Im relatively new to Django. so sorry for this mess.
I've tried to implement threaded comments to my blog via MPTT. But when i pressing the 'Reply' Button django throws me a Type Error
Normal parent comments working correctly
When i just create a comment with via the admin site, i can create parent comments and child comments and they will be indented just as expected in the main Application too...
my Database is mySQL.
The Error:
in _calculate_inter_tree_move_values
space_target = target_right - 1
~~~~~~~~~~~~~^~~
TypeError: unsupported operand type(s) for -: 'NoneType' and 'int'
my models.py:
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
from mptt.models import MPTTModel, TreeForeignKey
STATUS = (
(0,"Draft"),
(1,"Publish")
)
class Post(models.Model):
title = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=200, unique=True)
author = models.ForeignKey(User, on_delete= models.CASCADE, related_name='blog_posts')
updated_on = models.DateTimeField(auto_now=True)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
status = models.IntegerField(choices=STATUS, default=0)
class Meta:
ordering = ['-created_on']
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post_detail',args=[self.slug])
class Comment(MPTTModel):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
name = models.CharField(max_length=80)
email = models.EmailField()
body = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
active = models.BooleanField(default=False)
parent=TreeForeignKey('self', null=True, blank=True, on_delete=models.CASCADE, related_name='children')
class MPTTMeta:
order_insertion_by = ['created_on',]
def __str__(self):
return 'Comment {} by {}'.format(self.body, self.name)
#just for the threaded comments
def get_comments(self):
return Comment.objects.filter(parent=self).filter(active=True)
views.py:
from django.shortcuts import render, get_object_or_404, redirect, HttpResponseRedirect
from django.views import generic
#from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
#from django.template import loader
from .models import Post, Comment
from .forms import CommentForm
class PostList(generic.ListView):
queryset = Post.objects.filter(status=1).order_by('-created_on')
template_name = 'index.html'
paginate_by = 3
#class PostDetail(generic.DetailView):
# model = Post
# template_name = 'post_detail.html'
class AboutMe(generic.TemplateView):
template_name = 'about_me.html'
class Contact(generic.TemplateView):
template_name = 'contact.html'
class Impressum(generic.TemplateView):
template_name = 'impressum.html'
class StaticContent(generic.TemplateView):
template_name = 'static_html_content.html'
class SideBar(generic.TemplateView):
template_name = 'sidebar.html'
#class PostDetail(generic.DetailView):
# model = Post
# context_object_name = "post"
# template_name = "post_detail.hhml"
def post_detail(request, post):
template_name = 'post_detail.html'
post = get_object_or_404(Post, slug=post, status=1)
comments = post.comments.filter(active=True)
new_comment = None
#comment posted
if request.method == 'POST':
comment_form = CommentForm(request.POST)
if comment_form.is_valid():
# Create comment object but dont save to database yet
new_comment = comment_form.save(commit=False)
# Assign thecurrent post to the comment
new_comment.post = post
#save the comment to the database
new_comment.save()
#redirect to the same page and focus on that comment
return HttpResponseRedirect('/' + post.slug)
#return redirect(post.get_absolute_url()+'#'+str(new_comment.id))
else:
comment_form = CommentForm()
return render(request, template_name, {'post': post, 'comments': comments, 'new_comment': new_comment, 'comment_form': comment_form})
def reply_page(request):
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
post_id = request.POST.get('post_id')
parent_id = request.POST.get('parent')
post_url = request.POST.get('post_url')
print(post_id)
print(parent_id)
print(post_url)
print('was here reply!')
reply = form.save(commit=False)
reply.post = Post(id=post_id)
reply.parent = Comment(id=parent_id)
reply.save()
return redirect(post_url+'#'+str(reply.id))
return redirect('/')
forms.py:
from .models import Comment
from django import forms
from mptt.forms import TreeNodeChoiceField
class CommentForm(forms.ModelForm):
parent = TreeNodeChoiceField(queryset=Comment.objects.all())
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['parent'].widget.attrs.update(
{'class': 'd-none'})
self.fields['parent'].label = ''
self.fields['parent'].required = False
class Meta():
model = Comment
fields = ('name', 'parent', 'email', 'body')
widgets = {
'name': forms.TextInput(attrs={'class': 'col-sm-12'}),
'email': forms.TextInput(attrs={'class': 'col-sm-12'}),
'body': forms.Textarea(attrs={'class': 'form-control'}),
}
def save(self, *args, **kwargs):
Comment.objects.rebuild()
return super(CommentForm, self).save(*args, **kwargs)
post_details.html:
{% extends 'base.html' %}
{% load static %}
{% load crispy_forms_tags %}
{% load mptt_tags%}
{% block content %}
<header class="masthead" style="height: 13.9em;">
<!-- javascript add -->
<script src="{% static 'js/main.js'%}"></script>
</header>
<div class="container">
<div class="row">
<div class="col-md-8 card mb-4 mt-3 left top">
<div class="card-body">
<h1>{% block title %} {{ post.title }} {% endblock title %}</h1>
<p class=" text-muted">{{ post.author }} | {{ post.created_on }}</p>
<p class="card-text ">{{ post.content | safe }}</p><br>
<a href="{% url 'home' %}" style="float: right;"
class="btn btn-danger">Go Back</a><br><br>
</div>
</div>
{% block sidebar %} {% include 'sidebar.html' %} {% endblock sidebar %}
</div>
<div class="row">
<div class="col-md-8 card mb-4 mt-3 left top">
<div class="card-body">
<h3>Add Comment</h3>
<form method="POST" action="">
{% csrf_token %}
{{ comment_form | crispy }}
<button type="submit" class="btn btn-danger">Comment</button>
</form>
<!-- count comments section-->
{% with comments.count as total_comments %}
<h3 class="mt-5">
{{ total_comments }} comment{{ total_comments|pluralize }}
</h3>
{% endwith %}
<!-- show comment section -->
<div>
<ul style="list-style-type: none;">
{% recursetree comments %}
<li>
<!-- parent body -->
<div>
<div class="border p-4 rounded">
<h4>{{ node.name }}</h4>
<small class="text-muted">On {{ node.created_on }}</small>
<h5>{{ node.body }}</h5> <br>
<button class="btn btn-danger btn-sm" onclick="handleReply({{node.id}})">Reply</button>
<div id="reply-form-container-{{node.id}}" style="display:none">
<form method="POST" action="{% url 'reply' %}" class="mt-3">
{% csrf_token %}
<input type="hidden" name="post_id" value="{{post.id}}">
<input type="hidden" name="parent" value="{{comment.id}}">
<input type="hidden" name="post_url" value="{{post.get_absolute_url}}">
{{comment_form|crispy}}
<div>
<button type="button" onclick="handleCancel({{node.id}})" class="btn btn-danger border btn-sm">Cancel</button>
<button type="submit" class="btn btn-danger btn-sm">Submit</button>
</div>
</form>
</div>
</div>
</div>
<br>
<!-- if children -->
{% if not node.is_leaf_node %}
<ul ul style="list-style-type: none;">
<div class="children pl-2 pl-md-5">
{{ children }}
</div>
</ul>
{% endif %}
</li>
{% endrecursetree%}
</ul>
</div>
</div>
</div>
</div>
</div>
{% endblock content %}
I've tried to change the values in the formfields of the post_details.html to node.parent.id
but nothing seems to happen.
Also i tried to change the parent_id's datatype to see if there something happens.
but because it runs in this Opperant-Error i think it could be an issue with saving to the mySQL Database...
Ok... Now i have have found the answer.
In views.py i've edited these lines:
parent_id = request.POST.get('parent')
and replace 'parent' with 'commend_id'
parent_id = request.POST.get('comment_id')
In post_detail.html i have changed the form:
<input type="hidden" name="parent" value="{{comment.id}}">
to...
<input type="hidden" name="comment_id" value="{{node.id}}">
Now it runs as expected! YAY!

ValueError at /plants/plants/ too many values to unpack (expected 2) when using django_filters

Hej!
I'm having trouble with my django filter.
When I put {{myFilter}} in the template I only get an ObjectNumber and when I put {{myFilter.form}} I get the error:
ValueError at /plants/plants/
too many values to unpack (expected 2)
Does anyone have an idea what's going on?
# views.py
def plants_view(request):
plants = Plant.objects.all()
myFilter = PlantFilter(plants)
context = {"plants": plants, "myFilter": myFilter}
return render(request, 'plants/search_table.html', context)
# filters.py
class PlantFilter(django_filters.FilterSet):
class Meta:
model = Plant
fields = ['name',]
it doesn't matter if I use fields = [ ] or fields = '__all__' .
template.html
{% extends "landing/base.html" %}
{% load static %}
{% load i18n %}
{% load admin_urls %}
{% block page-title %} {%translate "View Plants" %} {% endblock %}
{% block head %}
<link href="{% static 'landing/vendor/tabulator/dist/css/tabulator.min.css' %}" rel="stylesheet">
<link href="{% static 'landing/vendor/tabulator/dist/css/bootstrap/tabulator_bootstrap4.min.css' %}" rel="stylesheet">
{% endblock %}
{% block content %}
<br>
<div class="row">
<div class="col">
<div class="card card-body">
<form method="get">
{{myFilter.form}}
<button class="btn-primary" type="submit">Search</button>
</form>
</div>
</div>
</div>
</br>
# models.py
class Plant(models.Model):
name = models.CharField(
max_length=200
)
def __str__(self):
return f"{self.name}"
def serialize(self):
return {
"Name": self.name
}
Did you follow the documentation on this page ?
views.py
def plants_view(request):
plants = Plant.objects.all()
myFilter = PlantFilter(request.GET, queryset=plants)
context = {"plants": plants, "myFilter": myFilter}
return render(request, 'plants/search_table.html', context)
template.html
<form method="get">
{{ myFilter.form.as_p }}
<button class="btn-primary" type="submit">Search</button>
</form>

Django from is not being past into html template

As in the question title "{{form}}" from is not being loaded into html template I checked by previous projects I have almost the same code, differences are required fields, naming etc. mechanic is the same.
In those projects registration function works perfectly here it's not even throwing an error just don't display anything.
No wonder what might be wrong in here.
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from .models import Profile
class RegistrationForm(UserCreationForm):
email = forms.EmailField(max_length=60, help_text="Required field")
class Meta:
model = Profile
fields = ["email", "username", "password", "password2", "calories_plan", "diet_type"]
views.py
def registration_view(request):
context = {}
if request.POST:
form = RegistrationForm(request.POST)
if form.is_valid():
email = form.cleaned_data.get("email")
password = form.cleaned_data.get("password")
new_account = authenticate(email=email, password=password)
login(request, new_account)
else:
context["registration_form"] = form
else:
form = RegistrationForm()
context["registration_form"] = form
return render(request, "Account/registration.html", context)
html template
{% extends 'main.html' %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="post">
{% csrf_token %}
<fieldset class="form-group">
<legend class=border-bottom mb-4>Join today
{{ form }}
</legend>
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Sign Up</button>
</div>
</form>
<div class="border-top pt-3">
<small class="text-muted">
Already have an account?
<a href="#" class="ml-2">
Log In
</a>
</small>
</div>
</div>
{% endblock %}
And how it looks in browser.
You're passing 'registration_form' to the context, but in template you are calling {{ form }}.
Replace:
{{ form }}
with:
{{ registration_form }}

How to remove <br/> tag from Textarea?

I'm using Django to construct a simple personal website. I just built a basic email form. Here's the models.py file for it:
from django.db import models
class Message(models.Model):
name = models.CharField(max_length=200, unique=True)
email = models.EmailField(unique=True)
subject = models.CharField(max_length=100, unique=True)
message = models.CharField(max_length=1000, unique=True)
def __unicode__(self):
return self.name
And here is the corresponding forms.py file:
from django import forms
from rksite.models import Message
class EmailForm(forms.ModelForm):
name = forms.CharField(max_length=200,help_text="Name:")
email = forms.EmailField(help_text="Email:")
subject = forms.CharField(max_length=100, help_text="Subject:")
message = forms.CharField(max_length=1000, widget=forms.Textarea, help_text="Message:")
class Meta:
model = Message #link the model to the form
And finally, I'll also include the form's html page below:
{% extends 'rksite/base.html' %}
{% block title %}RaghavKumarContact{% endblock %}
{% block content %}
<h1>Contact Me</h1>
<br />
<form class="span6" id="email_form" method="POST" action="/home/contact/">
{% csrf_token %}
{% for field in form.visible_fields %}
{{ field.errors }}
{{ field.help_text }}
{{ field|linebreaks }}
{% endfor %}
<br />
<button class="btn btn-primary" type="submit" name="send">Send</button>
</form>
{% endblock %}
Now, no matter what I do, the "br/" tag shows up inside the "Message" Textarea field. Here's what I see on my webpage:
How can I get rid of this tag from this Textarea?
EDIT:
This is what it'll look like if I don't have the linebreaksfilter applied:
What is an alternative to the linebreaks filter??
Don't use linebreaks here:
{{ field|linebreaks }}
That renders the widget for the form, then passes the entire rendered HTML block through the linebreaks filter. That filter converts newlines into <br /> tags, and the rendering for a Textarea widget includes a newline before the text:
def render(self, name, value, attrs=None):
if value is None:
value = ''
final_attrs = self.build_attrs(attrs, name=name)
return format_html('<textarea{}>\r\n{}</textarea>',
flatatt(final_attrs),
force_text(value))
(Source from https://github.com/django/django/blob/master/django/forms/widgets.py#L435)
I'm not sure why you'd want to pass the field values though linebreaks - an HTML textarea should handle regular linebreaks in the message text just fine, if that's what you're worrying about.

How to access and make use of html data in django?

I am having a hard time figuring out the right logic for my problem, i have 3 models,
class Item(SmartModel):
name= models.CharField(max_length=64,help_text="Name for this item e.g Hamburger")
price=models.DecimalField(max_digits=9,decimal_places=2)
optionalitems = models.ManyToManyField('optionalitems.OptionalItemCategory',null=True,blank=True)
class OptionalItems(SmartModel):
"""Optional items that belong to an item e.g topping that belongs to a pizza"""
name = models.CharField(max_length=20, help_text="Item name.")
price = models.DecimalField(max_digits=9, decimal_places=2, null=True,blank=True)
class OptionalItemCategory(SmartModel):
"""Category to which optional items belong"""
title = models.CharField(max_length=20,help_text="Category name")
optional_items = models.ManyToManyField(OptionalItems)
in my template,
{%for optionalcategory in optionalcategories %}
<h5 id="blah"> {{ optionalcategory.title}} </h5>
{% for optionalitem in optionalcategory.optional_items.all %}
<ul>
<input type="radio" value="radio" name="optional" value="op"><li id="item_appearence">{{optionalitem.name}}<span> {{optionalitem.price}}</span></li><a/>
</ul>
{% endfor %}
{% endfor %}
So for example an Item like a burrito will have an OptionalItem steak or chicken.I am able to access the Item like so item = get_object_or_404(Item, pk=obj.id) but my problem is i cannot figure out how to capture the OptionalItem. I want to be able to access the OptionalItem, i want to obtain the value of the radio button and its attributes. its kind of tricky.
Your code is inconsistent and that makes it hard to read, understand and work with. Some advice, clean it up. Something like this:
class Category(models.Model):
name = models.CharField(max_length=200)
class Option(models.Model):
name = models.CharField(max_length=200)
price = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True)
class Item(models.Model):
category = models.ForeignKey(Category)
name = models.CharField(max_length=200)
price = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True)
options = models.ManyToManyField(Option)
Than you need a from and a view. As I interpret your question: you want a form to select a option for an Item. So the code below will render all options and the widget RadioSelect() lets the user select one item. But why use radiobuttons? If an Item has a relation to one Option, than the Item model should have a foreignKey not M2M!
Form:
class ItemForm(ModelForm):
options = forms.ChoiceField(widget=forms.RadioSelect())
class Meta:
model = Item
fields = ( 'options', )
View:
from django.shortcuts import render
from django.http import HttpResponseRedirect
def your_view(request, id):
item = Item.objects.get(pk=id) # Your item object.
if request.method == 'POST': # If the form has been submitted...
form = ContactForm(request.POST) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
# Process the data in form.cleaned_data
options = form.cleaned_data['options']
# ...
return HttpResponseRedirect('/thanks/') # Redirect after POST
else:
form = ArticleForm(instance=article)
return render(request, 'contact.html', {
'form': form,
})
Template:
{% for obj in item.options_set.all %}
{{ obj.name }} {{ obj.price }}
{% endfor %}
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
I dind't test the code. But this should get you started. The documentation is your friend:
https://docs.djangoproject.com/en/1.5/topics/forms/
https://docs.djangoproject.com/en/1.5/#forms
In your template, you can simply render the price. I'd write a method in the Item model, that formats the OptionalItems the way you like.
i.e.
class Item(SmartModel)
...
def get_optional(self):
return ','.join([a.optionalitems for a in self.optionalitems.all()])
Of course, you should change that method to have it format the way you'd like.
If you pass a queryset of Items to your template, you can do something like the following:
{% for item in items %}
Name: {{ item.name}}
Price: {{ item.price }}
Optional Items: {{ item.get_optional }}
{% endfor %}