How to configure fields in Django forms.Form? - python

I'm learning Django and web dev and having difficulty configuring the fields in Django forms.Form so that they come out correctly. Below is my code:
Even if I adjust my attrs rows and cols in forms.Textarea it doesn't make any difference. Also, it doesn't seem to matter what I put in CSS the output is still the same.
class NewPageForm(forms.Form):
title = forms.CharField(label="Title", max_length=100, widget=forms.TextInput)
content = forms.CharField(label="Content", widget=forms.Textarea(attrs{"rows":3,"cols":10}))
My html:
{% block body %}
<div class="form">
<form action="{% url 'create' %}" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type = submit>
</form>
</div>
{% endblock %}
What it looks like:
Please advise.

You may try:
content = forms.CharField(label=False, widget=forms.Textarea(attrs={'rows': 3}))
or even add a CSS class to customize it:
content = forms.CharField(label=False, widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 3}))

Related

How do you iterate through two items in a model and display on site using Django?

I have a models.py with the following fields:
class ChatStream(models.Model):
bot = models.TextField()
user = models.TextField()
name = models.CharField(max_length=100, null=True)
created_date = models.DateTimeField(auto_now_add=True)
And I'd like on a website to iterate through "bot" and "user" one at a time, so the site would hypothetically display something like:
bot: hello!
user: what's up?
bot: I'm good
user: What's your name
bot: bot is my name
.... etc. this would keep going...
So in my views.py I have
def displayDict(request):
m = ChatStream.objects.all()
return render(request, 'chatStream.html',
{"chat": m})
def send(request):
message = request.POST.get('userMessage', False)
ip = visitor_ip_address(request)
response = routes(message, ip)
print(ip, "user sent:", message, "bot response:", response)
chatItem = ChatStream(bot=response, user=message, name=ip)
chatItem.save()
return HttpResponseRedirect('/chat/')
Then in my template, chat.html I have
{% block chatStream %} {% endblock %}
And chatStream.html (this is where the error is happening I believe... how do you iterate through two items in the model so they appear one after the other on the html file?)
{% extends 'chat.html' %}
{% block chatStream %}
{% for a in bot%}
{% for b in user%}
<p>
<b>bot:</b> {{a}} <br>
<b>user:</b> {{b}} <br>
</p>
{% endfor %}
<form action="/send/" method = "post">{% csrf_token %}
<input type="text" name="userMessage">
<input type="submit" value="Send to smallest_steps bot">
</form>
{% endblock %}
But this does not work -- no text from the model is displayed on the site. I am not understanding how to iterate through two items within the model at once inside of the chatStream.html.
A lot going on here, lets try to break it down:
First, you need to pass context variables to your templates if you want to render them using the (jinja-like) Django template rendering system.
Your view function for rendering the template would look like this:
views.py
def render_chat_page(request):
# do some logic:
...
# pack the context variables:
context = {
'some_key' : 'some_value',
'chat_streams' : ChatStream.objects.all(),
...
}
return render(request, 'chat_page.html', context=context)
Ok, now that we've passed the context variables to the template, we can render html elements using the variables like so:
template.html
<div> The value of "some_key" is: {{some_key}} </div>
{% for chat_stream in chat_streams %}
<div> user says: {{chat_stream.user}}</div>
<div> bot says: {{chat_stream.bot}}</div>
{% endfor %}
This will render the user and bot messages for each ChatStream object. However my hunch is that this is not entirely what you're after, instead you may want something more dynamic.
In your displayDict view you're passing a QuerySet to the context. So, you need to loop over the QuerySet in your template.
{% extends 'chat.html' %}
{% block chatStream %}
{% for item in chat %}
<p>
<b>bot:</b> {{item.bot}} <br>
<b>user:</b> {{item.user}} <br>
</p>
{% endfor %}
<form action="/send/" method = "post">{% csrf_token %}
<input type="text" name="userMessage">
<input type="submit" value="Send to smallest_steps bot">
</form>
{% endblock %}

How to use <int:pk> in class-based general views

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.

Django-autocomplete-light showing empty dropdown instead of autocomplete widget

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.

Django Tinymce Not Displaying The Rich Text Form

I want to use TinyMCE in my Django project, after doing all the necessary settings, when I visit the page, the form only render normal django form but not TinyMCE rich text form. Below are my settings.
I copied tinymce folder to media folder:
C:/Python27/Scripts/nate/media/js/tiny_mce
Settings.py
TINYMCE_JS_URL = '/media/js/tiny_mce/tiny_mce.js/'
TINYMCE_DEFAULT_CONFIG = {
'plugins': "table,spellchecker,paste,searchreplace",
'theme': "advanced",
'cleanup_on_startup': True,
'custom_undo_redo_levels': 10,
}
TINYMCE_SPELLCHECKER = True
TINYMCE_COMPRESSOR = True
urls.py
(r'^tinymce/', include('tinymce.urls')),
Models
class Finmall(models.Model):
user=models.ForeignKey(User)
name=models.CharField(max_length=250, unique=True)
content1 = models.TextField()
content2 = models.TextField()
def __unicode__(self):
return self.user
Template
<head>
<script type="text/javascript" src="{{ MEDIA_URL }}/js/tiny_mce/tiny_mce.js"></script>
</script>
</head>
{% block content %}
<div id="postcribbody" class="wrapper">
<p class="list">You can make it</p>
<form enctype="multipart/form-data" form action="." method="POST">
{% csrf_token %}
{{ FinmallForm.as_p }}
<input type="submit" class="cribput" value="Submit"/>
</form>
</div>
{% endblock %}
How can I make the content1 and content2 display TinyMCE rich text form?
An Example from the Documentation:
from django import forms
from tinymce.widgets import TinyMCE
class FinmallForm(forms.ModelForm):
...
content = forms.CharField(widget=TinyMCE(attrs={'cols': 80, 'rows': 30}))
...
class Meta:
model = Finmall
The problem is that you are displaying the form as a Django form.
The rich edit text field will be a JS thing which Django will not create. The django.form feature will be create a HTML element.
I suggest manually putting the rich edit in to the template. As long as you give the rich edit the same "name" as the Django form element you can use it in the POST which is returned.
EDIT: You are publishing a models.TextField() when the form is rendered. This will generate a element in the form. This form will have only default properties.
I am not 100% sure how TinyMCE works but you would need to bind it to that element though a "id" or "name" value or just put the forms code in yourself into the template.
I myself do not use Django to render the forms I create forms myself in the template and give them the same names what Django would give them.
Look at the source code for the rendered page and see what the form looks like. Then set up a test page with TinyMCE and get it working and look at the difference between the element.
:)
Try to put above form {{ form.media }} i.e. {{ FinmallForm.media }} in your template
<head>
<script type="text/javascript" src="{{ MEDIA_URL }}/js/tiny_mce/tiny_mce.js"></script>
</script>
</head>
{% block content %}
<div id="postcribbody" class="wrapper">
<p class="list">You can make it</p>
{{ FinmallForm.media }}
<form enctype="multipart/form-data" form action="." method="POST">
{% csrf_token %}
{{ FinmallForm.as_p }}
<input type="submit" class="cribput" value="Submit"/>
</form>
</div>
{% endblock %}

Django Filter Error

I want to save and filter users objects in my django app. After inputting the below codes, the imagefield keeps giving me a validation error, saying:
This field is required.
It’s pointing to the imagefield that I should fill it. How can I get rid of that error and make it filter?
Models
class Fin(models.Model):
user=models.ForeignKey(User)
title=models.CharField(max_length=250)
main_view=models.ImageField(upload_to="photos")
side_view=models.ImageField(upload_to="photos")
address=models.CharField(max_length=200)
city=models.CharField(max_length=200)
state=models.CharField(max_length=200)
guideline=models.TextField(max_length=1000)
def __unicode__(self):
return self.title
def get_absolute_url(self):
return self.title
class FinForm(ModelForm):
class Meta:
model=Fin
fields=('title','main_view','side_view', 'address','city','state','guideline')
exclude=('user')
Views
def fincrib(request):
extra_data_context={}
#if there's nothing in the field do nothing.
if request. method=="POST":
form =FinForm(request.POST)
if form.is_valid():
data=form.cleaned_data
newfincribs=Fin(
user= request.user,
title=data['title'],
main_view=Fin.objects.latest['main_view'],
side_view=Fin.objects.latest['side_view'],
address=data['address'],
city=data['city'],
state=data['state'],
guideline=data['guideline'])
newfincribs.save()
extra_data_context.update({'FinForm':form})
else:
form = FinForm()
extra_data_context.update({'FinForm':form})
extra_data_context.update({'Fins':Fin.objects.filter(user=request.user)})
plan=Fin.objects.filter(user=request.user)
paginator=Paginator(plan, 5)
try:
page=request.GET.get('page', '1')
except ValueError:
page=1
try:
Fins=paginator.page(page)
except (EmptyPage, InvalidPage):
Fins=paginator.page(paginator.num_pages)
extra_data_context.update({'Fins': Fins})
return render_to_response('post.html',extra_data_context,context_instance=RequestContext(request))
Template
{% block content %}
<form action="." method="POST">
{% csrf_token %}
<center> {{FinForm.as_p}} </center>
<input type="submit" value="Submit"/>
</form>
{% for Fin in Fins.object_list %}
<tr>
{{Fin.user}} </p> </strong>
<p>{{Fin.title}}</p>
<p><img src="{{MEDIA_URL}}/{{Fin.main_view}}"/></p>
<p> <img src="{{MEDIA_URL}}/{{Fin.side_view}}"/></p>
<p> {{Fin.address}} </p>
<p> {{Fin.city}}</p>
<p> {{Fin.state}}</p>
<p> {{Fin.guideline}}</p>
{% endfor %}
<div class="pagination">
<span class="step-links">
{% if Fins.has_previous %}
previous
{% endif %}
<span class="current">
Page {{ Fins.number }} of {{ Fins.paginator.num_pages }}
</span>
{% if Fins.has_next %}
next
{% endif %}
</span>
</div>
{% endblock %}
It's because by default all model fields are required, it means if you want to create and save new model instance in the database, you should fill all the mandatory fields. Maybe
main_view=Fin.objects.latest['main_view'],
side_view=Fin.objects.latest['side_view'],
is giving you the error, because there is no data.
change
main_view=models.ImageField(upload_to="photos")
side_view=models.ImageField(upload_to="photos")
to
main_view=models.ImageField(upload_to="photos", blank=True, null=True)
side_view=models.ImageField(upload_to="photos", blank=True, null=True)
btw, im not sure which django version you're using but your code is rather messy, any reason you're not using CBVs and static tags?

Categories

Resources