This is my models.py:
class QuestionCategory(models.Model):
name = models.CharField(max_length=200)
class Question(models.Model):
question = models.CharField(max_length=200)
answer = models.TextField()
category = models.ForeignKey(QuestionCategory)
What I want to do is to get the questions and group_by the QuestionCategory
So I can display my questions like this:
Question_Category (1)
Question (1)
Answer (1)
Question (2)
Answer (2)
....
Question_Category (2)
Question (3)
Answer (3)
Question (...)
Answer (...)
...
This is the doc to my question: https://docs.djangoproject.com/en/1.8/topics/db/aggregation/
You do not need GROUP_BY, just use reverse foreignkey lookup:
categories = QuestionCategory.objects.prefetch_related('question_set').all()
for category in categories:
print category.name
for question in category.question_set.all():
print question.question
print question.answer
In your views.py
def questions(request):
categories = QuestionCategory.objects.prefetch_related('question_set').all()
return render(request, 'question.html', {
'questions': questions
})
In your question.html
{% for category in categories %}
<h2>{{ category.name }}</h2>
{% for question in category.question_set.all %}
<h3>{{ question.question }}</h3>
<p>{{ question.answer }}</p>
{% endfor %}
{% endfor %}
The prefetch_related is use to optimise your query.
Related
I am trying to get a test form that includes subforms to work but the form does not validate on submission. The form itself is submitting a recipe with ingredients as its subforms using FieldList(). I have also made sure to include hidden_tag() in the HTML.
Forms:
class IngredientsForm(FlaskForm):
ingredient_name = StringField("Ingredient", validators=[DataRequired()])
class RecipeForm(FlaskForm):
recipe_name = StringField("Recipe name", validators=[DataRequired()])
ingredients = FieldList(FormField(IngredientsForm), min_entries=2, max_entries=5)
submit = SubmitField("Submit")
Views:
#app.route("/", methods=["GET", "POST"])
def index():
form = RecipeForm()
return render_template("index.html", form=form)
#app.route("/submit", methods=["POST"])
def submit():
form = RecipeForm()
print(f"ERRORS: {form.errors}")
print(f"DATA: {form.data}")
if form.validate_on_submit():
print("Validated!")
print(form.recipe_name)
for ingredient in form.ingredients.data:
print(ingredient)
return redirect("/")
else:
print("Form not validated")
return render_template("index.html", form=form)
HTML:
<h1>Enter recipe:</h1>
<form action="/submit" method="POST">
{{ form.hidden_tag() }}
<p>
{{ form.recipe_name.label }} <br>
{{ form.recipe_name() }}
</p>
<p>
{{ form.ingredients.label }} <br>
{% for ing in form.ingredients %}
{{ ing.ingredient_name.label }}
{{ ing.ingredient_name() }}
<br>
{% endfor %}
</p>
<p>
{{ form.submit() }}
</p>
</form>
Output:
ERRORS: {}
DATA: {'recipe_name': 'butterbread', 'ingredients': [{'ingredient_name': 'butter', 'csrf_token': None}, {'ingredient_name': 'bread', 'csrf_token': None}], 'submit': True, 'csrf_token': 'Ijg1NmVjZjIwODY3MTJkNDNkMTFiNDQ2YzdiNzYyYzYyNmUzNGUzMWMi.YtaF7g.WRn25PWYMFplr_KV7RoZq1uLgrI'}
Form not validated
127.0.0.1 - - [19/Jul/2022 03:22:44] "POST /submit HTTP/1.1" 200 -
So far, no errors show up but it looks like in the data that since each subform has None as its csrf_token, maybe that's messing up the validation? I've tried getting this to validate for a while but to no avail.
You can disable csrf protection for the FlaskForm by setting the flag to false within the class Meta. CSRF protection is not necessary for nested forms as long as the parent form takes over this task.
class IngredientsForm(FlaskForm):
class Meta:
csrf = False
ingredient_name = StringField("Ingredient", validators=[DataRequired()])
class RecipeForm(FlaskForm):
recipe_name = StringField("Recipe name", validators=[DataRequired()])
ingredients = FieldList(FormField(IngredientsForm), min_entries=2, max_entries=5)
submit = SubmitField("Submit")
An alternative is to inherit from Form.
Figured it out. The problem is that the subform IngredientsForm inherits from FlaskForm which is a subclass that's csrf secure, and was the reason preventing validation. You don't need this as you have already the token in the main form.
Instead, have it inherit from wtforms.Form which doesn't have that. Another way is to disable csrf during init, but the previous method is preferred.
I want to write in less code a function that will add the active classname and automatically removes all the other active class names. But there is also a unique class name needed for JavaScript in my case. But want to put that all in class name. How can I make this a valid classname. Is there a way to do that so it will not conflict with each other.
<ul class="three">
<li
v-for="(post, index) in listData.data"
:key="index"
:class="'list-item unordered-list ' + post.name.toLowerCase() + { active : activeName == post.name}"
#click="showInfo(post.name, post.description)">
{{ post.name }}
</li>
</ul>
Have a look at the object syntax or array syntax of class binding, which allows binding to an object or array returned by a value. That way you can simplify complex class or style combinations by calling a function from the template, like the example from the docs:
<div v-bind:class="classObject"></div>
...
data: {
isActive: true,
error: null
},
computed: {
classObject: function () {
return {
active: this.isActive && !this.error,
'text-danger': this.error && this.error.type === 'fatal'
}
}
}
<ul class="three">
<li
v-for="(post, index) in listData.data"
:key="index"
:class="['list-item', 'unordered-list ', post.name.toLowerCase(), { active: activeName == post.name }]"
#click="showInfo(post.name, post.description)">
{{ post.name }}
</li>
</ul>
I have a dynamic table with students based on class block. That is the table has the list of students in each period block. The HTML which dynamically builds this is
html += "<tr>"+
"<td class='align-middle'><input type='checkbox' class='form-check' style='width:50px;height:50px;'></td>"+
"<td class='align-middle'><input type='image' onclick='StudentClicked(\""+item.FirstName+"\",\""+item.LastName+"\",\""+item.Suffix+"\",\""+item.NickName+"\")' src="+path+" onError='StudentImageError("+i+")' id='studentimage"+i+"' height='100'></td>"+
"<td class='align-middle'>"+item.FirstName +" "+item.LastName+"</td>"+
"<td class='align-middle'></td>"+
"<td class='align-middle'>0</td>" +
"<td class='align-middle'>0</td>"+
"</tr>"
Therefore when the user clicks the image, StudentClicked is called.
function StudentClicked(FirstName, LastName, Suffix, NickName){
$.getJSON('/studentSelected',
{firstName: FirstName, lastName: LastName, suffix: Suffix, nickName: NickName},
function(data){})
}
The idea here is that I want to click the image link and the getJSON will look for my app.route("/studentSelected"). I will perform a database call with the variables I have passed to this route and build an object. I want to pass this object to an html page. Here is the python code for the app.route
#app.route('/studentSelected', methods=['GET','POST'])
def studentSelected():
firstName = request.args.get('firstName', 0, type=str)
lastName = request.args.get('lastName', 0, type=str)
suffix = request.args.get('suffix', 0, type=str)
nickName = request.args.get('nickName', 0, type=str)
students = []
con, cur = ConnectToDatabase()
SQL = "select * from students where FirstName = ? and LastName = ? and Suffix = ? and NickName = ?"
entities = (firstName, lastName, suffix, nickName)
student, cur = Execute(SQL, cur, entities)
return render_template('studentcard.html', student=student)
Currently I get "Method Not Allowed. The method is not allowed for the requested URL." which I interpret as I'm not passing the right method to my route. But as you can I do pass both methods to my route. Why else would I be getting this error? studentcard.html exists in the folder templates.
One guess I have is that the return statement returns functionality to the getJSON function.
What is a better strategy for this type of process. The end result is for the clicked image to run app.route, call the database and then redirect the webapp to a new route for studentSelected and load and run this page.
contents of studentcard.html
{% extends 'layout.html' %}
{% block body %}
<div class="container mt-3">
{% from "includes/_formhelpers.html" import render_field %}
</div>
{% endblock %}
I have forms to Post Article in my blog Django2. When I run django server there is no error, but when I Post and submit Article in my frontEnd apps nothing happens and doesn't save any data.
Any help on this would be highly appreciated!
Template HTML
<div class="create-article">
<h2>Create an Awesome New Articles</h2>
<form class="site-form" action="{% url 'articles:create' %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form }}
<input type="submit" value="Create">
</form>
</div>
forms.py
from django import forms
from . import models
class CreateArticle(forms.ModelForm):
class Meta:
model = models.Article
fields = ['title', 'body', 'slug', 'thumb']
views.py
def article_create(request):
if request.method == 'POST':
form = forms.CreateArticle(request.POST, request.FILES)
if form.is_valid():
# save article to db
instance = form.save(commit=False)
instance.author = request.user
instance.save
return redirect('articles:list')
else:
form = forms.CreateArticle()
return render(request, 'articles/article_create.html', {'form': form})
urls.py
from django.urls import path
from . import views
app_name = 'articles'
urlpatterns = [
path('', views.article_list, name="list"),
path('create/', views.article_create, name="create"),
path('<slug>/', views.article_detail, name="detail"),
]
Thanks.
It starts here: instance = form.save(commit=False), where you are not commiting the save.
Further down you have instance.save as if you were setting a model field, but with not value given to it.
Make that line instance.save() instead.
I'd like to add custom class in my drupal template, in header region, but it doesn't works.
<!-- BEGIN OUTPUT from 'themes/marinenat/templates/layout/page.html.twig' -->
<div class="layout-container">
<header role="banner">
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'region' -->
<!-- FILE NAME SUGGESTIONS:
x region--header.html.twig
* region.html.twig
-->
<!-- BEGIN OUTPUT from 'themes/marinenat/templates/layout/region--header.html.twig' -->
<div class="nav">
I'd like to add this class after "nav" class di region--header.
Anyone can help me
You already have all you need in the output.
Many roads lead to Rome
If themes/marineat is you base theme, simply copy themes/marinenat/templates/layout/region--header.html.twig into your subtheme's themes/MYSUBTHEME/templates directory and edit this file. Flush cache. Done.
If themes/marinenat is you custom subtheme simply edit the suggested template file /themes/marinenat/templates/layout/region--header.html.twig/ and add your class there. Flush cache. Done.
Last but not least you can also add classes to a region from a preprocess function from your MYSUBTHEME.theme file or any MYMODULE.module file.
/**
* Implements template_preprocess_region().
*/
function MYTHEME/MYMODULE_preprocess_region(&$variables) {
if (isset($variables['region']) && $variables['region'] == 'header') {
$variables['attributes']['class'][] = 'MYCLASS';
}
}
How to pass a string from PHP to Twig
/**
* Implements template_preprocess_region().
*/
function MYTHEME/MYMODULE_preprocess_region(&$variables) {
$variables['foo'] = FALSE;
if (isset($variables['region']) && $variables['region'] == 'header') {
// Get the current node.
$node = \Drupal::routeMatch()->getParameter('node');
if ($node instanceof \Drupal\node\NodeInterface) {
// Get the node type.
$node_type = $node->bundle();
// Do what ever else you need to do to retrieve your class dynamically.
$variables['foo'] = $node_type;
}
}
}
Then in your region--header.html.twig Twig file it's:
{% if foo %}
<div class="nav {{ foo }}">
{{ content }}
</div>
{% endif %}