Problem with CheckboxSelectMultiple from a CharField ModelForm in Django - django

I'm having trouble getting my form to save in Dajngo due to the following error on validation:
<ul class="errorlist"><li>pt_medical_condition<ul class="errorlist"><li>Select a valid choice.
['anx', 'Bip'] is not one of the available choices.
>pt_surgical_history<ul class="errorlist"><li>Select a valid choice.
['bre', 'pca'] is not one of the available choices.
I've got this model:
class pt_data(models.Model):
condition_choices = [('ane', 'Anemia'), ('anx', 'Anxiety'), ('art', 'Arthritis'),
('ast', 'Asthma'), ('Bip', 'Bipolar'), ('ca', 'Cancer'), ('clo', 'Clotting disorder'),
('chf', 'CHF'), ('mdd', 'Depression'), ('cop', 'COPD'), ('ger', 'GERD'),
('gla', 'Glaucome'), ('hiv', 'HIV/AIDS'), ('ibs', 'IBS/Crohn\'s'),
('hld', 'High cholesterol'), ('ckd', 'Kidney disease'), ('ner', 'Nerve/Muscle disease'),
('ocd', 'OCD'), ('ost', 'Osteoporosis'), ('pai', 'Pain disorder'), ('pts', 'PTSD'),
('sch', 'Schizophrenia'), ('sei', 'Seizures'), ('sca', 'Sickle cell anemia'),
('su', 'Substance use disorder'), ('thy', 'Thyroid disease')]
surgery_choices = [('app', 'Appendix removal'), ('bra', 'Brain surgery'),
('bre', 'Breast surgery'), ('cabg', 'CABG'), ('pca', 'Cardiac stent'),
('cho', 'Gallbladder removal'), ('col', 'Bowel surgery'), ('csec', 'C-section'),
('fra', 'Bone fracture repair'), ('her', 'Hernia repair'), ('hys', 'Uterus removal'),
('joi', 'Joint replacement'), ('lun', 'Lung surgery'), ('spi', 'Spine/back surgery'),
('thy', 'Thyroid surgery'), ('ton', 'Tonsil removal'), ('strf', 'Tubal ligation'),
('strm', 'Vasectomy'), ('wei', 'Weight reduction surgery')]
pt_medical_condition = models.CharField(max_length=100, blank=True, null=True,
choices=condition_choices)
pt_surgical_history = models.CharField(max_length=100, blank=True, null=True, choices=surgery_choices)
And this form:
class ptForm(forms.ModelForm):
class Meta:
model = pt_data
fields = ('__all__')
widgets = {
'pt_medical_condition': CheckboxSelectMultiple(attrs={'class': 'cond_checkbox'}),
'pt_surgical_history': CheckboxSelectMultiple(attrs={'class': 'surg_checkbox'}),
}
And this is my HTML:
{% for check in form.pt_medical_condition %}
{% if forloop.counter|divisibleby:3 %}
<div> </div>
{% endif %}
<label class='mx-2' id="{{ check.choice_label }}">
{{ check.tag }} {{ check.choice_label }}
</label>
{% endfor %}
{% for check in form.pt_surgical_history %}
{% if forloop.counter|divisibleby:2 %}
<div> </div>
{% endif %}
<label class='mx-2' id="{{ check.choice_label }}">
{{ check.tag }} {{ check.choice_label }}
</label>
{% endfor %}
The HTML is rendered just fine, the problem seems to arise on submit. It looks like the correct characters are there, however they are surrounded by incorrect characters. The following "anx" is appropriate but won't be validatated by Django because everything else that has been tacked on 'anx&#x27. Could it be a problem with posting the information with AJAX? Or maybe using a CSRF cookie to POST? Has anyone else encountered this problem? Any suggestions would be helpful.

Related

How to format Django form with UIKit styling

I am struggling to see a way to style a django form in the style of a uikit horizontal form. UIKit has the styling I want and Django has the validation and templating I want.A way to implement a datepicker too would be useful.
I have tried the plain django form template with .as_p and .as_table. I have also tried to use Meta and widgets but couldn't get that to work. I can't see how I can add the needed uikit tags to each element and add the uk-form-controls div.
template.html
<form class="uk-form-horizontal uk-margin-large uk-align-center">
<div class="uk-margin">
<label class="uk-form-label" for="form-horizontal-text">Job Title</label>
<div class="uk-form-controls">
<input class="uk-input uk-form-width-large" id="form-horizontal-text" type="text" placeholder="Some text...">
</div>
</div>
forms.py
class job_form(forms.Form):
job_title = forms.CharField(label='Job Title', max_length=50)
hiring_manager = forms.CharField(label='Hiring Manager', max_length=50)
job_description = forms.CharField(label='Job Description', max_length=50)
salary = forms.IntegerField()
closing_date = forms.DateField()
I am expecting to be able to have the uikit form styling with the templating and validation of django forms but am yet to get it to work.
Django has a variety of ways to override the form behavior and layout. I see you are using forms.Form instance. Simply add your classes to the form class like:
class NiceForm(forms.Form):
solid_field=forms.CharField(widget=forms.TextInput(attrs={'class': 'uk-form-input'}))
Although it is simple, but sluggish, when you want introduce breaking changes to the layout, I would override the template (or render method if you like) to bundle a reusable widget. Simple example to extract the form to external reusable template as you can render them manually as HTML like documentation.
Leave the form clean and use templatetag to override classes:
# _form_icludes.html
{% for field in form.visible_fields %}
<fieldset class="uk-fieldset">
<div class="uk-margin">
<label class="uk-form-label" for="{{ field.id_for_label }}">{{ field.label }}</label>
<div class="uk-form-controls">
{% if field.field.widget.input_type == 'select' %}
{{ field | add_css_cls:'uk-select'}}
{% elif field.field.widget.input_type == 'option'%}
{{ field | add_css_cls:'uk-option'}}
{% elif field.field.widget.input_type == 'checkbox'%}
{{ field | add_css_cls:'uk-checkbox'}}
{% elif field.field.widget.input_type == 'select'%}
{{ field | add_css_cls:'uk-select'}}
{% elif field.field.widget.input_type == 'file'%}
{{ field }}
{% else %}
{{ field | add_css_cls:'uk-input'}}
{% endif %}
{% if field.help_text %}
<span class="uk-text-small uk-text-left uk-text-italic">
{{ field.help_text }}
</span>
{% endif %}
{% if field.errors %}
{% for error in field.errors %}
<p class="uk-flex uk-flex-middle uk-text-danger ">
<span data-uk-icon="icon:warning" class="uk-text-danger uk-margin-small-right"></span>
{{ error | escape }}
<p/>
</div>
{% endfor %}
{% endif %}
</div>
</fieldset>
{% endfor %}
# add_css_cls
from django import template
register = template.Library()
#register.filter
def add_css_cls(value, arg):
css_classes = value.field.widget.attrs.get('class', '').split(' ')
if css_classes and arg not in css_classes:
css_classes = '%s %s' % (css_classes, arg)
return value.as_widget(attrs={'class': css_classes})
There are many different ways.

Django how to iterate querysets of two subclasses in template?

I am using django-model-utils for inheritance Managers. I want to get result of both sub-classes with one dictionary without getting duplicates.
models.py
class Images(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='images_created', on_delete=models.CASCADE)
created = models.DateTimeField(auto_now_add=True, null=True, blank=True)
objects = InheritanceManager()
class Postimg(Images):
user_img= models.ImageField(upload_to='images/%Y/%m/%d', null=True, blank=True)
class Postsms(Images):
user_message = models.CharField(max_length=500,blank=True)
views.py
def home(request):
all_post = Images.objects.all().order_by('-created').select_subclasses()
return render(request, 'copybook/home.html',{ 'all_post':all_post})
copybook/home.html
{% for foo in all_post %}
<hr>
<br> SMS by: <p>{{ foo.user}} __ {{ foo.created }}</p>
<h2>{{ foo.user_message }}</h2>
<hr>
<br> IMAGE by: <p>{{ foo.user}} __ {{ foo.created }}</p>
<img src="{{ foo.user_img.url }}"width="250">
{% endfor %}
I expect the result when I upload an image or message that should get top at home page, but now when I upload an image, a blank message also gets iterated.
I think the problem is in my home.html, because I do not know how to iterate
over two sub-classes with a single for loop without getting duplicates.
In your template, you are processing every item as if it were both a message and an image. That's why you get empty image sections for messages and empty message sections for images.
The simplest workaround would be to check if user_img or user_message evaluates to True:
{% for foo in all_post %}
<hr>
{% if foo.user_message %}
<br> SMS by: <p>{{ foo.user}} __ {{ foo.created }}</p>
<h2>{{ foo.user_message }}</h2>
{% else %}
<br> IMAGE by: <p>{{ foo.user}} __ {{ foo.created }}</p>
<img src="{{ foo.user_img.url }}"width="250">
{% endif %}
{% endfor %}
Instead of else you can do a separate if foo.user_img to avoid message objects with empty messages to be interpreted as images.

Displaying an Image in ModelForm

I have the following model:
class Portfolio(models.Model):
id = models.AutoField(primary_key=True)
member = models.ForeignKey(Member, on_delete=models.CASCADE)
image = models.ImageField(upload_to='portraits/', default='/images/some_image.png')
For that I made the ModelForm:
class PortfolioForm(forms.ModelForm):
class Meta:
model = Portfolio
exclude = ['id']
I need many of those in one template so I am creating them in the Following way in my view
def portfolio_form(request, pk):
...
formset = PortfolioFormSet(queryset=Portfolio.objects.filter(pk__in=list_of_ids))
for x in p]
finally in the html I have this:
<form enctype="multipart/form-data" action="{% url 'elec:portfolio_form' pk=id %}" method="POST">{% csrf_token %}
...
{{ formset.management_form }}
{% for form in formset.forms %}
<tr>{% for field in form %}
{% if field.name == 'image' %}
<td><img src="{{field.image.url}}"></td>
{% else %}
<td align="center" valign="middle">{{field}}</td>
{% endif %}
{% endfor %}</tr>
{% endfor %}
<input type="submit" class="btn btn-default" value="Save and Refresh" />
</form>
Now what I expect to see is the image that I am saving into that Model. The if statement is coming back as false but why?. What am I doing wrong? Everywhere I looked it should work like this.
Also I have added the request.FILES in PortfolioForm with that the instance is not called how can I fix that?
OK I found the solution in Stackoverflow since I used some other words to find a solution.
what you need to do in the template instead of :
{<td><img src="{{field.image.url}}"></td>}
is this :
{<td><img src="{{form.instance.image.url}}"></td>}

Display of data in HTML

Suppose I have an object called "comment_list", which is just a list of comments & related info. I'd like to display that to the page, so I do this:
page.html
{% for comment in comment_list %}
<b>ID:{{ comment.id }} - {{ comment.name }} (on {{ comment.submit_date }})</b><br>
<h4>{{ comment.comment }}</h4><br><br>
{% endfor %}
I used the django-comments add-on for this, and it works very well, no problem at all. Now, here's the thing - I wanted to add a special feature to the comments so that if activated, this special feature will display in place of that particular comment. I built a new table that connected to Comments, and linked it via comment_id.
What I then want to do is implement an "if-else" thing in the HTML to replace the comment as it loops. Just to be clear, "comment_list" has multiple objects within. So...:
page.html
{% if special_feature.comment_id = comment.id %}
<b>ID:{{ comment.id }} (on {{ comment.submit_date }})</b><br>
<h4>YES SPECIAL FEATURE!</h4><br><br>
{% else %}
<b>ID:{{ comment.id }} - {{ comment.name }} (on {{ comment.submit_date }})</b><br>
<h4>{{ comment.comment }}</h4><br><br>
{% endif %}
"special_feature" also has multiple objects within. But I can't seem to make it work. "special_feature.comment_id" will not appear, because I expect it to have more than one objects inside. I have to specifically state it as "special_feature.X.comment_id", where "X" is a number.
So the solution is to somehow use the "forloop.counter" for that. In which case, the final code could look like so:
page.html
{% for comment in comment_list %}
{% if special_feature.(forloop.counter|add:"-1").comment_id = comment.id %}
<b>ID:{{ comment.id }} (on {{ comment.submit_date }})</b><br>
<h4>YES SPECIAL FEATURE!</h4><br><br>
{% else %}
<b>ID:{{ comment.id }} - {{ comment.name }} (on {{ comment.submit_date }})</b><br>
<h4>{{ comment.comment }}</h4><br><br>
{% endif %}
{% endfor %}
"add:-1" is so that the counter starts from "0" rather than "1". "special_feature.(forloop.counter|add:"-1").comment_id" doesn't work obviously, is there a better way to handle this?
EDIT:
Here's the view.py
#login_required(login_url='sign_in')
def display_comments(request, magazine_slug, art_id):
context = {}
populateContext(request, context)
magazine_data = get_object_or_404(Magazine, slug=magazine_slug)
article_data = get_object_or_404(Article, project_id=magazine_data.id, id=art_id)
special_feature = CommentSpecial.objects.all().filter(user_id=request.user.id)
context = {'article':article_data, 'magazine':magazine_data, 'special_feature':special_feature}
return render(request, 'projsapp/page.html', context)
#login_required(login_url='sign_in')
def add_special_feature_comments(request, art_id):
context = {}
populateContext(request, context)
# Acquire data from post
data = request.POST
special_type = data.get('id_special')
date_time=datetime.datetime.now()
# Confirm whether article exists
article_data = get_object_or_404(Article, id=art_id)
content_type = ContentType.objects.get_for_model(article_data)
# Save a new comment manually
save_comment=Comment.objects.create(object_pk=art_id, user_name="SYSTEM", user_email="lala#lala.com", comment="SPECIAL", ip_address="127.0.0.1", is_public=1, is_removed=0, content_type_id=content_type.id, site_id=settings.SITE_ID, user_id=request.user.id, submit_date=date_time)
# Save to CommentSpecial as well!
CommentSpecial.objects.create(special_type=0, user_id=request.user.id, text="SUPER", comment_id=save_comment.id)
return HttpResponseR blah blah....
And here's model.py for CommentSpecial:
class CommentSpecial(models.Model):
comment = models.ForeignKey(Comment)
user_id = models.ForeignKey(User)
creation_date = models.DateTimeField(auto_now_add=True)
text = models.CharField(max_length=100, blank=True, null=True, default='')
special_type = models.BooleanField(default=False)
# False = Super Special, True = Typical Special

How I get data from "third" related model in django?

Hi guys,
I have this models:
class Pais(models.Model):
nome = models.CharField('Nome', max_length=50)
class Brinq(models.Model):
descricao = models.CharField('Nome', max_length=50)
class Filhos(models.Model):
nome = models.CharField('Nome', max_length=50)
idade = models.IntegerField('Idade')
pai = models.ForeignKey('Pais')
brinq = models.ForeignKey('Brinq', related_name='Brinq')
This view:
def editPai(request, idpai=None):
if idpai:
pai = Pais.objects.get(id=idpai)
else:
pai = None
ItensInlineFormSet = inlineformset_factory(Pais, Filhos, form=FilhosForm, extra=1)
formPais = PaisForm()
formsetItens = ItensInlineFormSet(instance=pai)
return render_to_response("base.html", {
"formPais": formPais, "formsetItens": formsetItens
}, context_instance=RequestContext(request), )
and this forms:
class PaisForm(ModelForm):
class Meta:
model = Pais
class FilhosForm(ModelForm):
class Meta:
model = Filhos
Ok, How can I get "descricao" value from "Brinq" model in my template? I think it's a simple question but, I tried looking, looking and looking again from internet and I don't find anything about this.
I start to thing it's not possible to do it using django, I want to believe that I'm wrong, but as I said, I didn't find anything about this in internet.
I try:
{% for form in formsetItens %}
<tr>
<td> {{ form.nome }}</td>
<td> {{ form.idade }}</td>
<td> {{ form.brinq__descricao }}</td>
</tr>
{% endfor %}
and {{ form.brinq.descricao}} to, and nothing... :(
Can anyone help me with this problem?
Regards,
You are trying to iterate over a FormSet. As the docs say "The formset gives you the ability to iterate over the forms in the formset and display them as you would with a regular form".
So you can for example do the following to display all the fields included in the form:
{% for form in formsetItens %}
{{ form.as_table }}
{% endfor %}
..or if it fits your use case you could wrap each form into a form tag, and loop over the form fields:
{% for form in formsetItens %}
<form action="/contact/" method="post">
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}
<p><input type="submit" value="Send message" /></p>
</form>
{% endfor %}