Rendering database objects in Django - django

This is a basic question but I can't figure out what I'm doing wrong...
I'm trying to render a detail view in my django site, but my calls to get the object are just failing or else not rendering.
Here is what I have:
views.py
from django.template import loader
from django.views.generic.base import TemplateView
from django.http import HttpResponse
from .models import user_profile
def detail(request, content_id):
template = loader.get_template('profiles/detail.html')
profile = user_profile.objects.get(pk=content_id)
context = {'profile': profile}
return HttpResponse(template.render(context, request))
Within the template, I have simply been testing the calls using:
<h1>{{ profile }}</h1>
<h1>{{ profile.name }}</h1>
This is my first time rendering this from scratch, I know I'm missing something dumb I just can't sort it. Thank you!
edit This current setup receives a 500 error. Without the get(pk) statement it loads, but doesn't show the variables, just the rest of my HTML.
upon request, here is the urls.py:
urlpatterns=[
path('<int:content_id>/', views.detail, name='detail'),
]
edit: solution Solved! Ends up there was an issue with the model where a migration was not properly performed and a column was read as missing.

Model was contained a column that was missing in the database. Even though it was not being called, it still resulted in an error when the model was referenced.

Related

How to use multiple django-markdownx editors on the same page?

I have followed http://neutronx.github.io/django-markdownx/js/docs/markdownx.html#MarkdownX docs but can't get it done properly.
What is the correct way to setup two or more editors in the same page?
You don't have to set it up that way. MarkdownX is already initiated as your load {{form}} and {{form.media}}, so it has no meaning. Now, coming to your question. Using two editors on the same page in really straight forward.
in your forms.py:
from django import forms
from markdownx.fields import MarkdownxFormField
class FirstForm(forms.Form):
yourfirstfield = MarkdownxFormField()
class SecondForm(forms.Form):
yoursecondfield = MarkdownxFormField()
in your views.py:
from django.shortcuts import render
from .forms import FirstForm, SecondForm
def form_view(request):
context = {
'first_form': FirstForm,
'second_form': SecondForm
}
return render(request, 'form_template.html', context)
in your form_template.html:
<form>
<p>{{first_form}}</p>
<p>{{second_form}}</p>
</form>
I hope that helps!

Page not rendering because of url

I want to make contact page is made of simple template html.
in view.py i made this
from .models import tutorials
from django.views import generic
class Contactviews(generic.View):
template_name = 'home/contact.html'
and this is my url:
url(r'^contact$',views.Contactviews.as_view(), name='contact')
the contact.html is just a simple text that extends from base.html .and it doesnt involve any functionality from models.py
so the page is not rendering.
i think maybe problem is on my url address.
The base View class doesn't know anything about templates. You should use TemplateView.

Pass context variables from two view functions to the same template

I trying to render values from two function to one html and I not sure how to perform this task.
I suppose to use "return render" in both function? and how should be in urls.py to read this both functions?
For now I have as is bellow and of course TopAlerts not returning anything. Any suggestions?
views.py
def OneWeekRequest(request):
#code here....
......
return render_to_response('weeklyreport.html',
{'n1week': n1week,
'g1week': g1week,
'fweeks': fweeks,
'g4weeks': g4weeks,
'form': form,
'start': start,
'end': end,
'wnumber': wnumber,
'speriod': selectedrange},
context_instance=RequestContext(request))
def TopAlerts(request):
#code here....
......
return render(request, 'weeklyreport.html', {'tops': tops})
urls.py
from django.conf import settings
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
url(r'^$', 'platforms.views.queryset'),
url(r'^weeklyreport/$', 'weeklyreport.views.OneWeekRequest'),
#url(r'^weeklyreport/', include('weeklyreport.urls')),
I created templatetag.py in templatetags
from django import template
from platforms.models import Platform, Event
register = template.Library()
#register.simple_tag
def top_alerts(top):
tops = Event.objects.filter(sourcetype_id__in=[1, 3],
status_id__in=[1,2,7,8],
event_datetime__range=('2014-04-07', '2014-04-13')
).exclude(service_id__in=[759, 7]
).values("event_datetime",
"platform__name",
"host__name","service__name",
"eventtype__name",
"status__name", "data")
return {'tops': tops}
and in my template.
{% load templatetag %}
and
{% top_alerts top %}
And is working fine, but i not entirely sure if this goes correct way with my project.
You can't return two views from one URL. A URL always points to one single view (although of course multiple URLs can point to the same view).
It sounds like your TopAlerts view should really be an inclusion tag.

How to get user value in base.html?

I'd like to work with user data in main base.html which is my main template.
I actually use the login generic view. When I'm logged in on the homepage it gives me user information but in all other pages user is blank.
I've read many things about this: request, RequestContext, I've added django.contrib.auth.context_processors.auth to the processors list.
Any idea how to get this variable to show everywhere?
Two ways:
If you're using django 1.4+, you can use, render() when returning from your views:
def my_view(request):
...
return render(request, 'template.html', ctx)
If you're using older django or you don't like the render approach, you would return RequestContext using render_to_response, like this:
def my_view(request):
...
return render_to_response('template.html', ctx, context_instance=RequestContext(request))
Edit: sorry, forgot to actually answer question. If you're rendering your templates using one of the above ways and have:
django.contrib.auth in your INSTALLED_APPS
auth in midleware
auth in context_processors
(take a look at default settings.py file: https://github.com/django/django/blob/master/django/conf/global_settings.py )
Then you can use: {{ user }} and {{ user.is_anonymous }} to figure out what's going on.

Using class based generic view DetailView with a ModelForm reveals a bug - how to proceed?

I've been impressed how rapidly a functional website can go together with generic views in the tutorials. Also, the workflow for form processing is nice. I used the ModelForm helper class to create a form from a model I made and was delighted to see that so much functionality came together. When I used the generic list_detail.object_detail I was disappointed that all that I could display were fields individually. I knew the ModelForm class contained information for rendering, so I wanted to use the ModelForm with a generic view.
I was asking around on stackoverflow to get some direction, and appreciate the answers and comments from several posters. I've figured out how to get this to work, but there is a bug in DetailView. The solution includes a workaround.
To use a ModelView with the generic view and get all the fields to render automatically the following works:
Create a project, and in it create application inpatients.
If you have
# inpatients/models.py
class Inpatient(models.Model):
last_name = models.CharField(max_length=30)
first_name = models.CharField(max_length=30,blank=True)
address = models.CharField(max_length=50,blank=True)
city = models.CharField(max_length=60,blank=True)
state = models.CharField(max_length=30,blank=True)
DOB = models.DateField(blank=True,null=True)
notes = models.TextField(blank=True)
def __unicode__(self):
return u'%s, %s %s' % (self.last_name, self.first_name, self.DOB)
class InpatientForm(ModelForm):
class Meta:
model = Inpatient
and
# inpatients/views.py
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render_to_response
from django.views.generic import DetailView
from portal.inpatients.models import *
def formtest(request):
if request.method == 'POST':
form = InpatientForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/inpatients')
else:
form = InpatientForm()
return render_to_response("formtest.html", {'form': form})
class FormDetailView(DetailView):
model=Inpatient
context_object_name='inpatient' # defines the name in the template
template_name_field='inpatient_list_page.html'
def get_object(self):
inpatient=super(FormDetailView,self).get_object()
form=InpatientForm(instance=inpatient)
return form
def get_template_names(self):
return ['inpatient_list_page.html',]
and
#urls.py
from django.conf.urls.defaults import patterns, include, url
from django.views.generic import ListView
from portal.inpatients.models import Inpatient, InpatientForm
from portal.inpatients.views import FormDetailView
urlpatterns = patterns('',
(r'^formtest/$','portal.inpatients.views.formtest'),
(r'^inpatients/$', ListView.as_view(
model=Inpatient, template_name='inpatient_list_page.html')),
(r'^inpatient-detail/(?P<pk>\d+)/$', FormDetailView.as_view()),
)
# with a template containing
{% block content %}
<h2>Inpatients</h2>
<ul>
{% for aninpatient in object_list %}
<li><a href='/inpatient-detail/{{ aninpatient.id }}/'>
{{ aninpatient }}, id={{ aninpatient.id }}</a></li>
{% endfor %}
</ul>
{{ inpatient.as_p }}
{% endblock %}
# Yeah, kind of hokey. The template is for both the list view and detail view.
# Note how the form is rendered with one line - {{ inpatient.as_p }}
it works. The instructions for using class based generic views lives at https://docs.djangoproject.com/en/1.3/topics/class-based-views/ Instructions there are pretty clear. The key to making things work is to redefine get_object. In the documentation under the section "Performing extra work" it nicely describes how to do this, the steps being to call the original version of get_object, and then to the extra work. The bit that I realized is that the return object can be a ModelForm object. The object that get_object returns goes straight into the template in a render. By taking the retrieved inpatient object and running it through InpatientForm it can be passed to a view as a form which then renders itself.
As to the bug: The bug in DetailView is that the get_template_names function tries to make a template name from a structure that does not exist. In
https://code.djangoproject.com/browser/django/trunk/django/views/generic/detail.py
on lines 127 to 140 we have within SingleObjectTemplateResponseMixin.get_template_names:
127 # The least-specific option is the default <app>/<model>_detail.html;
128 # only use this if the object in question is a model.
129 if hasattr(self.object, '_meta'):
130 names.append("%s/%s%s.html" % (
131 self.object._meta.app_label,
132 self.object._meta.object_name.lower(),
133 self.template_name_suffix
134 ))
135 elif hasattr(self, 'model') and hasattr(self.model, '_meta'):
136 names.append("%s/%s%s.html" % (
137 self.model._meta.app_label,
138 self.model._meta.object_name.lower(),
139 self.template_name_suffix
140 ))
The error is that the code on line 131 is executed and dies with error message <'ModelFormOptions' object has no attribute 'app_label'>. I conclude that the _meta object is defined. I suppose that the problem is that in a ModelForm the class Meta is defined. That Meta probably doesn't have the fields set that are expected. The workaround is just to rewrite get_template_names and return the correct template.
I'm new to Django and Python. I appreciate the answers and comments by the contributors at the following previous questions I asked. (
Putting links in list_detail.object_list to list_detail.object_detail,
Using form in object_detail,
Rolling your own generic views in Django)
What should I do to report the bug?
You are right I believe. This is a bug which stems from the fact that both ModelForm and Models have a _meta attribute. This same bug would exhibit itself anytime an object is returned from get_object() that contains a _meta attribute.
get_object does not have to return a Model instance. You can confirm this by looking at the source for DetailView and reading it's docstring:
class DetailView(SingleObjectTemplateResponseMixin, BaseDetailView):
"""
Render a "detail" view of an object.
By default this is a model instance looked up from `self.queryset`, but the
view will support display of *any* object by overriding `self.get_object()`.
"""
Notice that the doc string explicitly says that any object is supported by overriding self.get_object().
Another piece of corroborating evidence is from the location where this bug itself occurs which is the get_template_names method of SingleObjectTemplateResponseMixin.
# The least-specific option is the default <app>/<model>_detail.html;
# only use this if the object in question is a model.
if hasattr(self.object, '_meta'):
names.append("%s/%s%s.html" % (
self.object._meta.app_label,
self.object._meta.object_name.lower(),
self.template_name_suffix
))
elif hasattr(self, 'model') and hasattr(self.model, '_meta'):
names.append("%s/%s%s.html" % (
self.model._meta.app_label,
self.model._meta.object_name.lower(),
self.template_name_suffix
))
Again looking at this code, the comment itself say "If the object in question is a model". From this comment we can infer that the object doesn't always have to be a model.
However if you are trying to create a view that allows someone to edit/create/delete a model you really should have a look at the Editing Views which include FormView, CreateView, EditView and DeleteView. You can see more information for these at https://docs.djangoproject.com/en/1.3/ref/class-based-views/#editing-views.
To answer the question as to how to report the bug, you should follow the guidelines detailed at https://docs.djangoproject.com/en/1.3/internals/contributing/#reporting-bugs.