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

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.

Related

AttributeError at /mobile/7/delete/ 'tuple' object has no attribute '_meta'

I am trying to delete an item from my project but it gives error. interestingly it is deleting the item but gives error mention above.
views.py:
def delete_mobile(request, mobile_id):
mobile1 = get_object_or_404(Mobile, pk=mobile_id).delete()
form = MobileForm(instance=mobile1)
if form.is_valid():
form.delete()
return redirect('mobile')
return render(request, 'device/delete_mobile.html', {'mobile': mobile1})
delete_mobile.html:
{% extends 'device/base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<div class="container">
<form action="{% url 'delete_mobile' mobile.instance.id %}" method="POST">
{% csrf_token %}
<h3>Delete {{ header }}:</h3>
{{ mobile|crispy }}
<button class="btn btn-success" type="submit">Delete</button>
</form>
{% endblock %}
urls.py:
path('mobile/<str:mobile_id>/delete/', views.delete_mobile, name='delete_mobile'),
actually, the problem was occurring due to repetition of .delete() method in my delete view.
now I have fixed it and working properly.
def delete_mobile(request, mobile_id):
mobile1 = get_object_or_404(Mobile, pk=mobile_id)
form = MobileForm(instance=mobile1)
if form.is_valid():
form.delete()
return redirect('mobile')
return render(request, 'device/delete_mobile.html', {'mobile': mobile1})

create view of oneToMany object in related object view

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.

How to Create a UpdateForm with TemplateView?

I need to create a UpdateForm with a TemplateView. Why with TemplateView? Because, I has a attribute what is geo_location, and I'm using LeafLet maps, and LeafLet maps doesn't work with generic.UpdateView or others the same type.
Here my views from Update:
class UpdateStore(LoginRequiredMixin, TemplateView):
template_name = 'store_form'
success_url = reverse_lazy('register:store_list')
def post(self, request, *args, **kwargs):
store_id = kwargs['store']
store = get_object_or_404(Store, pk=store_id)
form = StoreForm(request.POST, on_edit=True)
if form.is_valid():
form.save()
return redirect(reverse('register:store_list'))
else:
context = self.get_context_data()
context['data_form'] = form
return render(request, self.template_name, context)
return self.get(request)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
store_id = self.kwargs['store']
store = get_object_or_404(Store, pk=store_id)
data = {
'name': store.name,
'description': store.description,
'address': store.address,
'geo_loc': store.geo_loc,
'opened': store.opened
}
context['editing'] = True
context['data_form'] = StoreForm(initial=data, on_edit=True)
context['store'] = store
return context
Here is my template code:
{% extends 'base.html' %}
{% load bootstrap3 %}
{% load leaflet_tags %}
{% block extra_css %}
{% leaflet_css plugins="forms" %}
{% endblock %}
{% block body %}
<h1> Update Store </h1>
<form method="POST">
{% csrf_token %}
{{ form }}
{% buttons %}
<button type="submit">
{% bootstrap_icon "star" %} Save
</button>
{% endbuttons %}
</form>
{% endblock %}
{% block extra_js %}
{% leaflet_js plugins="forms" %}
{% endblock %}
I trying this, but in my template, the Forms doesn't load, and my template are blanked :(. Someone knows why? I need another method for get anything else?
Thanks.
The problem with your code is that you place the form in the data_form key of the context:
context['data_form'] = StoreForm(initial=data, on_edit=True)
and then on the template you try to use it with {{form}} instead of {{data_form}}. After that the form should be rendered.

Using redirect sends me to /tag/?search=input instead of /tag/input (Django URL argument from form)

I have a page where there is a path /tag/name_of_tag and you can see all posts tagged with that tag.
Inside the page, you can also select another tag in a form and go to that tag.
The problem is that instead of going to /tag/searched_tag, it goes to /tag/?search=searched_tag
How can I change it doesn't leave the ?search= part?
urls.py:
url(r'tag/(?P<input_tag>\w+)$', views.tag_view, name='tag'),
views.py:
def tag_view(request, input_tag):
form = TagSearchForm()
if request.method == 'GET':
form = TagSearchForm(request.GET)
if form.is_valid():
input = form.cleaned_data['search']
print(input)
return redirect('fortykwords:tag_view', input)
else:
form = SearchForm()
latest_post_list = Post.objects.filter(tags=input_tag, status__exact="published")
paginator = Paginator(latest_post_list, 3)
page = request.GET.get('page')
posts = paginator.get_page(page)
context = {'latest_post_list': latest_post_list, 'page_tag': input_tag, 'form': form}
return render(request, 'fortykwords/tag.html', context)
forms.py:
class TagSearchForm(forms.Form):
search = tagulous.forms.SingleTagField(
tag_options=tagulous.models.TagOptions(
autocomplete_view='fortykwords:post_tags_autocomplete'
),
label='Tags',
required=True,
help_text=_('Filter by lead tags. You can organize leads by any tag you want.'),
)
tag.html:
{% extends "base_generic.html" %}
{% block content %}
<form action="." method="get">
{{ form }}
<input type="submit" value="Submit" />
</form>
<h3>Posts with the tag {{ page_tag }}</h3>
{% if latest_post_list %}
<ul>
{% for post in latest_post_list %}
<li> {{ post.author }} {{ post.pub_date }}
<br>
{{ post.title }}</li>
{% for tag in post.tags.all %}
{{ tag.name }}
{% endfor %}
{% endfor %}
</ul>
{% else %}
<p>No posts are available.</p>
{% endif %}
{% endblock %}
You need to provide the argument input to redirect method as input_tag=input.
Example:
return redirect('fortykwords:tag_view', input_tag=input)
It's showing as /tag/?search=searched_tag because your form is submitting by GET but never getting to the redirect. It seems is_valid() is returning False.
I've tested a very similar version of your code and don't think it's a bug in tagulous, but would still be interested to know what had gone wrong (I wrote tagulous). Spotted a couple of places you can streamline your code a bit, so try::
def tag_view(request, input_tag):
# Can't see any POSTs in your example, so you can pass the form GET here
# Might also be nice to pass the original tag in so it shows in the form
form = TagSearchForm(request.GET, initial={'search': input_tag})
# The form already has the GET, so you can go straight into the is_valid
if form.is_valid():
input = form.cleaned_data['search']
print('Valid: ', input)
return redirect('fortykwords:tag_view', input)
else:
print('Invalid: ', form.errors, form.non_field_errors)
# You can remove the else for if not GET, which would never be reached
# on to pagination as before
(although fwiw I'd recommend ipdb instead of print)

how validate form and show the value of the filled fields?

now im learning to validate form, "all" is working, im showing the erros of empty fields, but i have 2 questions:
how ill show the value in the filled fields when there are errors in another fields?, like <input ... value= {{ value }} > the problem is that my fields are not html forms fields.
how ill show the error exactly over the empty fields?
how i have this:
form.py
class NuevaDiligenciaForm(forms.Form):
titulo = forms.CharField(max_length=70)
tipo = forms.ChoiceField(choices=TIPO)
vias= forms.TypedChoiceField(widget=forms.RadioSelect(), choices=CHOICES)
view.py
def add(request):
form = NuevaDiligenciaForm()
errors =[]
if request.method =='POST':
if not request.POST.get('titulo',''):
errors.append('Titulo es requerido')
if not request.POST.get('vias',''):
errors.append('Vias es requerido')
#if not errors:
return render_to_response('account/add.html', { 'formulario':form ,'errors':errors},context_instance = RequestContext(request))
template.html
{% if errors %}
<ul>
{% for error in errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
{% if message %}
<p style="color: red;">{{ message }}</p>
{% endif %}
<form action='.' method='POST' class="nueva-diligencia">
{{ formulario.as_p }}
<input type="submit" value="Continuar">
</form>
Thanks again :)
You form code looks fine here but your view needs to change to this:
def add(request):
if request.method =='POST':
form = NuevaDiligenciaForm(request.POST)
if form.is_valid():
clean_data = form.cleaned_data
# Now do something with the cleaned data...
else:
form = NuevaDiligenciaForm()
return render_to_response('account/add.html', { 'formulario': form }
and your template should look like this:
{% if message %}
<p style="color: red;">{{ message }}</p>
{% endif %}
<form action='.' method='POST' class="nueva-diligencia">
{{ formulario.as_p }}
<input type="submit" value="Continuar">
</form>
Now what happens is that if there is bad data from the POST, form.is_valid() will fail and the view will return the validated form, which will include errors next to fields that have them. Django takes care of all the error handling for you here! Try it out and let me know if it works as you expect it to.
This is a pretty good resource if you'd like to see how/why this simplified version actually works better: http://www.djangobook.com/en/2.0/chapter07/