create view of oneToMany object in related object view - django

I have a questionnaire, containing many questions with their answers. My main objective is to create a webpage where I can show the details of a questionnaire with the list of rules (question/answer) and in the bottom of the page I want to call the create rule page:
def create_rule_view(request, id, sc_id):
if request.method == "POST":
input = InputForm(request.POST)
answer = AnswerForm(request.POST)
rule = RuleForm(request.POST)
if rule.is_valid() and input.is_valid() and answer.is_valid():
r = rule.save()
i = input.save(commit=False)
a = answer.save(commit=False)
i.rule_id = r
i.save()
a.rule_id = r
a.save()
question = input.cleaned_data["patterns"]
else:
input = InputForm()
answer = AnswerForm()
rule = RuleForm()
return render(request, "rule/create_rule.html", {
'rule': rule,
'input': input,
'answer': answer
})
def detail_scenario(request, id, sc_id):
object = get_object_or_404(Scenario, id=sc_id)
# TODO : add rule in the same view
create_rule_div = create_rule_view(request, id, sc_id)
print("content", create_rule_div)
context = {
'scenario': object,
'create_rule_div': create_rule_div
}
return render(request, "scenario/detail_scenario.html", context)
This is rule_create.html:
{% block content %}
<form method="POST"> {% csrf_token %}
<h2>Create Rule</h2>
{{ rule.name}}
{{ input.patterns }}
{{ answer.text }}
<input type="submit" value="Save Rule"/>
</form>
{% endblock %}
This is detail_senario.html:
{% block content %}
<h2>Scenario {{ scenario.id }}</h2>
<p>Scenario for : {{ scenario.chatbot_id }}</p>
<p>Name: {{ scenario.name }}</p>
<p>Description: {{ scenario.description }}</p>
<p>State: {{ scenario.state }}</p>
{% for rule in scenario.rule_ids.all %}
<li>{{ rule }}</li>
{% endfor %}
<div>{% block rule %}
{{ create_rule_div.content }}{% endblock %}
</div>
{% endblock %}
when I call url of detail_scenario I got an html code in navigator like this:
How can I fix this?
Thanks.

Related

How can I judge the object if is exists in the templates?

In the template:
<h4>
{% if data.wine_one %}
{{ data.wine_one.title }}
{% elif data.news_one %}
{{ data.news_one.title }}
{% endif %}
</h4>
I promise the data.wine_one is exists, because in the views.py I have print out it.
But in the templates it do not shows up the data.wine_one.title, and I use the data.wine_one != None can not judge it too.
EDIT
In the views.py:
def getData():
banner = models.Banner.objects.filter(fk_info=1)
info = models.Info.objects.all().first()
aboutus = models.AboutUs.objects.all().first()
winery = models.Winery.objects.all()[:3]
winery_consult = models.WineryConsult.objects.all()[:4]
data = {
'banner': banner,
'info': info,
'aboutus': aboutus,
'winery': winery,
'winery_consult': winery_consult,
}
return data
def productdetails(request, nid):
data = getData()
wine_one = models.Winery.objects.filter(id=nid).first()
data['wine_one'] = wine_one
print (data['wine_one'].title) # there ouput the "gaoliangjiu"
return render(request, 'article_list_content.html', data)
You've misunderstood how the template context works.
There's no element called data in the template; that's just the local variable you're using in the view to build up the context. In the template, you just reference the keys of that object directly. So it should be:
{% if wine_one %}
{{ wine_one.title }}
{% elif news_one %}
{{ news_one.title }}
{% endif %}

Button does not listen/work

I'm trying to detect if the button is clicked and store the value of a retrieved info in session from def detail.
views.py:
def job_display(request):
job_list = Job.objects.filter(Publication_Status="A").order_by('- Job_Position')
context = {'job_list': job_list}
return render(request, 'frontend/jobs.html', context)
def detail(request, job_id):
jreq = get_object_or_404(Job, pk=job_id)
if request.POST.get(jreq.Job_Position):
request.session['jpos'] = jreq.Job_Position
return HttpResponseRedirect('apply')
return render(request, 'frontend/details.html', {'jreq': jreq})
template:
<h1>{{ jreq.Job_Position }}</h1>
<h2>{{ jreq.Job_Description }}</h2>
{{ jreq.Available_Slots }}
<ul>
{% for req in jreq.job_requirement_set.all %}
<li>{{ req.Job_Requirements }}</li>
{% endfor %}
<p> BLA BLA BLA <p/>
{% for req in jreq.skill_requirement_set.all %}
<li>{{ req.Skill_Requirements }}</li>
{% endfor %}
<input name="form-type " name = {{ jreq.Job_Position }} value={{ jreq.Job_Position }} type="submit"/>
In short, you need to put your <input> into a <form>. Without a form you cannot POST any data.
Sounds like you need to learn how a form works in web development. While it's hard to give you a concrete example, django original document is always your friend: https://docs.djangoproject.com/en/1.8/topics/forms/

Could not parse the remainder django template

I have a condition within a loop in my template like this:
{% for message in message_trash %}
<td><a href="#">
{% if request.session.user_email == message.message_user_reciever.user_email %}
{{ message.message_user_reciever.user_firstName }} {{ message.message_user_reciever.user_lastName }}
{% elif request.session.user_email == message.message_user_sender.user_email %}
{{ message.message_user_sender.user_firstName }} {{ message.message_user_sender.user_lastName }}
{% endif %}
</a><small>Friends</small></td>
{% endfor %}
but i don't know why i get this error when applying the url?
TemplateSyntaxError: Could not parse the remainder: '==message.message_user_reciever.user_email' from 'request.session.user_email==message.message_user_reciever.user_email'
Update:
this is the view and variables that i render to the template:
def trashMessages(request, userId):
if isMessageOwner(request, userId):
user = Users.objects.get(user_id=userId)
message_trash = Messages.objects.filter(Q(message_user_reciever= user, message_sender_type='TRASH') | Q(message_user_sender=user, message_reciever_type='TRASH'))
return render(request, 'navigation_messages.html', {'user': user, 'message_trash': message_trash, 'type': 'trash'})
On testing your code out, I can only replicate your issue is by swapping:
{% if request.session.user_email == message.message_user_reciever.user_email %}
for
{% if request.session.user_email ==message.message_user_reciever.user_email %}
Note the missing space. Is the snippet in your question exactly as it is in your template?

Get current URL kwargs in the template?

I'm accomplishing this at the moment by doing:
context['card_type'] = self.kwargs['card_type']
context['role_line'] = self.kwargs['role_line']
context['sort_by'] = self.kwargs['sort_by']
Which seems crazy counter intuitive to me.
Say if i was already at the urls of players/one/two/three
Is there an already prebuilt way to get current kwargs of one, two & three for use in templates?
Edit
urls.py
urlpatterns = patterns('',
url(
r'^$',
NationListView.as_view(),
name='index'
),
url(
r'^(?P<slug>[a-z-]*)/$',
NationDetailView.as_view(),
name='nation'
),
url(
r'^(?P<slug>[a-z-]*)/(?P<card_type>[a-z]*)/(?P<role_line>[a-z]*)/(?P<sort_by>[a-z0-9]*)/$',
NationDetailFilteredView.as_view(),
name='nation_filter'
),
)
The mixin that builds the context
class CoreDetailFilteredMixin(object):
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super(CoreDetailFilteredMixin, self).get_context_data(**kwargs)
base_objects(context)
# Pull all the players that belong to the object_type
context['players'] = Player.objects.filter(
**{filters: context['object'].asset_id}
)
# Define the available card types
card_types = {
'if': {'card_type__gte': 2},
'gold': {'overall_rating__gte': 75},
'silver': {'overall_rating__range': (65, 74)},
'bronze': {'overall_rating__lte': 64}
}
# Check if the given card type is in the dictionary because 'all' throws an KeyError
if self.kwargs['card_type'] in card_types:
context['players'] = context['players'].filter(**card_types[self.kwargs['card_type']])
# Don't show inform cards for specific colour card types
if self.kwargs['card_type'] not in ['if', 'all']:
context['players'] = context['players'].exclude(card_type__gte=2)
# Define available role lines
role_lines = {
'att': 3,
'mid': 2,
'def': 1,
'gk': 0
}
# Check if the given role line is in the dictionary because 'all' throws an KeyError
if self.kwargs['role_line'] in role_lines:
context['players'] = context['players'].filter(role_line=role_lines[self.kwargs['role_line']])
# Define the available sort by keys
sorts = {
'ovr': 'overall_rating',
'att1': 'card_att1',
'att2': 'card_att2',
'att3': 'card_att3',
'att4': 'card_att4',
'att5': 'card_att5',
'att6': 'card_att6r'
}
# Add a descending order to the existing queryset
context['players'] = context['players'].order_by('-' + sorts[self.kwargs['sort_by']])
# Create pagination
cbv_pagination(self, context, context['players'], 28, 'players')
context['card_type'] = self.kwargs['card_type']
context['role_line'] = self.kwargs['role_line']
context['sort_by'] = self.kwargs['sort_by']
return context
How i use it currently in the template
{% with object.get_class_name|add:'s'|add:':'|add:object.get_class_name|add:'_filter'|lower as url_string %}
<dl class="sub-nav">
<dt>Card Type:</dt>
{% with 'all if gold silver bronze' as card_types %}
{% for ct in card_types.split %}
{% cycle 'All' 'Inform' 'Gold' 'Silver' 'Bronze' as card_type_name silent %}
{% if card_type == ct %}
<dd class="active">
{% else %}
<dd>
{% endif %}
<a href="{% url url_string object.slug ct role_line|default:'all' sort_by|default:'ovr' %}">
{{ card_type_name }}
</a>
</dd>
{% endfor %}
{% endwith %}
</dl>
<dl class="sub-nav">
<dt>Role Line:</dt>
{% with 'all att mid def gk' as role_lines %}
{% for rl in role_lines.split %}
{% cycle 'All' 'Attackers' 'Midfielders' 'Defenders' 'Goalkeepers' as role_lines_name silent %}
{% if role_line == rl %}
<dd class="active">
{% else %}
<dd>
{% endif %}
<a href="{% url url_string object.slug card_type|default:'all' rl sort_by|default:'ovr' %}">
{{ role_lines_name }}
</a>
</dd>
{% endfor %}
{% endwith %}
</dl>
<dl class="sub-nav">
<dt>Sort By:</dt>
{% with 'ovr att1 att2 att3 att4 att5 att6' as sorts %}
{% for sort in sorts.split %}
{% ifequal role_line 'gk' %}
{% cycle 'Overall' 'Diving' 'Handling' 'Kicking' 'Reflexes' 'Speed' 'Positioning' as sorts_name silent %}
{% else %}
{% cycle 'Overall' 'Pace' 'Shooting' 'Passing' 'Dribbling' 'Defending' 'Heading' as sorts_name silent %}
{% endifequal %}
{% if sort_by == sort %}
<dd class="active">
{% else %}
<dd>
{% endif %}
<a href="{% url url_string object.slug card_type|default:'all' role_line|default:'all' sort %}">
{{ sorts_name }}
</a>
</dd>
{% endfor %}
{% endwith %}
</dl>
{% endwith %}
As I learnt here, the view is already passed to the context (for class-based views). So you can do the following in the template without needing to explicitly pass the kwargs from the view:
{{ view.kwargs.card_type }}
{{ view.kwargs.role_line }}
{{ view.kwargs.sort_by }}
You can use dict.update():
update([other])
Update the dictionary with the key/value pairs from other, overwriting existing keys.
context.update(self.kwargs)

Caught AttributeError while rendering: 'str' object has no attribute '_meta'

def broadcast_display_and_form(request):
if request.method == 'POST' :
form = PostForm(request.POST)
if form.is_valid():
post = form.cleaned_data['post']
obj = form.save(commit=False)
obj.person = request.user
obj.post = post
obj.save()
readers = User.objects.all()
for x in readers:
read_obj = BroadcastReader(person = x)
read_obj.post = obj
read_obj.save()
return HttpResponseRedirect('/broadcast')
else :
form = PostForm()
posts = BroadcastReader.objects.filter(person = request.user)
return render_to_response('broadcast/index.html', { 'form' : form , 'posts' : posts ,} )
My template
{% extends "base.html" %}
{% load comments %}
{% block content %}
<form action='.' method='POST'>
{{ form.as_p }}
<p>
<input type="submit" value ="send it" /></input>
</p>
</form>
{% get_comment_count for posts.post as comment_count %}
{% render_comment_list for posts.post %}
{% for x in posts %}
<p>
{{ x.post.person }} - {{ x.post.post }}
</p>
{% endfor %}
{% endblock %}
What is posts.post supposed to be? posts is a BroadcastReader QuerySet, and probably doesn't have such an attribute? I'm guessing the comment rendering tags are causing your error? Try removing them, or using posts.0 or similar to debug.
Which "post" do you actually want to display comments for? Your view logic is unclear.