Django not finding database object when trying to render view - python

I'm getting the following error when I go to the /val/4/13/bs url:
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/val/4/13/bs
Raised by: valapp.views.BSDetail
No balance sheet found matching the query
Here is the views.py code:
class BSDetail(generic.View):
def get(self, request, *args, **kwargs):
view = BSDisplay.as_view()
return view(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
view = PostEvent.as_view()
return view(request, *args, **kwargs)
class BSDisplay(generic.DetailView):
template_name = 'valapp/balsheet.jinja'
model = BalanceSheet
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
entityobject = get_object_or_404(Entity, pk=self.kwargs['pkent'])
context['bsinfo'] = BalanceSheet.objects.filter(company = entityobject)
return context
class EntityDetail(generic.View):
def get(self, request, *args, **kwargs):
view = EntityDetailDisplay.as_view()
return view(request, *args, **kwargs)
class EntityDetailDisplay(generic.DetailView):
model = Entity
template_name = 'valapp/entitydetail.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
engobject = get_object_or_404(Engagement, pk=self.kwargs['pk'])
entobject = get_object_or_404(Entity, pk=self.kwargs['pkent'])
context['engagement'] = engobject
context['entity'] = entobject
return context
The urls.py code is:
app_name = 'valapp'
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('<int:pk>/', views.ValDetailView.as_view(), name='engagement'),
path('<int:pk>/<int:pkent>/', views.EntityDetail.as_view(), name='entitydetail'),
path('<int:pk>/<int:pkent>/bs', views.BSDetail.as_view(), name='bs'),
path('newval/', views.newval, name="newval"),
path('<int:pk>/newentity/', views.NewEntity.as_view(), name="newentity"),
]
Here is the models.py:
class BalanceSheet(models.Model):
company = models.ForeignKey(Entity, on_delete=models.CASCADE)
account_type = models.CharField(max_length=50, choices = BS_ACT_CHOICES)
value = models.DecimalField(max_digits=20, decimal_places=2)
name = models.CharField(max_length=100)
year = models.IntegerField(choices=YEAR_CHOICES, default=2022)
tab_abv = models.DecimalField(max_digits=20, decimal_places=2, default=0)
tab_rdt = models.DecimalField(max_digits=20, decimal_places=2, default=0)
tab_debt = models.DecimalField(max_digits=20, decimal_places=2, default=0)
def __str__(self):
return self.name
There are balance sheet objects associated with Entity 13.
It's a bit messing with the the 'pk' and the 'pkent', which I plan to clean up in the future. Basically, each balance sheet is associated with an entity, which is associated with an engagement.
When I go to val/4/13, the page does load properly so there is an entity 13 and there are plenty of objects associated with entity 13 in the BalanceSheet model that should be loading.

If I'm not mistaken, your URL structure of <int:pk> and <int:pkent> is that the first pk is your Engagement and pkent is Entity. Your BSDisplay view is a DetailView which has a BalanceSheet model, however the pk passed to it is an Engagement pk, which Django is unable to find. Either change the model of the view or the PK that is passed to the URL.

Related

Using inlineformset_factory with different querysets in CreateView

I am trying to use inlineformset_factory to create instances of the same model.
models.py
class Skill(models.Model):
employee = models.ForeignKey(
Employee, on_delete=models.CASCADE, related_name="employee_skills")
technology = models.ForeignKey(Technology, on_delete=models.CASCADE)
year = models.CharField('common year using amount ', max_length=4)
last_year = models.CharField('Last year of technology using ', max_length=4)
level = models.CharField("experience level", max_length=64, choices=LEVELS)
class Techgroup(models.Model):
""" Group of technology """
name = models.CharField('group_name', max_length=32, unique=True)
class Technology(models.Model):
"""Technologies."""
name = models.CharField('technology name', max_length=32, unique=True)
group = models.ForeignKey(Techgroup, on_delete=models.CASCADE, related_name="group")
In the Administrator pane I created 2 instances of the Techgroup model:
- Framework
- Programming language
All Skill models belong to one of two groups. On the front I display 2 forms, one containing queryset with instances belonging to the Framework, the other with instances belonging to the Programming language.
I divide Querysets using ModelsForm:
forms.py
class SkillBaseCreateForm(forms.ModelForm):
YEAR_CHOICES = [(r, r) for r in range(1, 11)]
LAST_YEAR_CHOICES = [(r, r) for r in range(2015, datetime.datetime.now().year + 1)]
year = forms.CharField(
widget=forms.Select(choices=YEAR_CHOICES),
)
last_year = forms.CharField(widget=forms.Select(choices=LAST_YEAR_CHOICES))
class Meta:
model = Skill
fields = ['technology', 'level', 'last_year', 'year']
class SkillCreatePLanguageForm(SkillBaseCreateForm):
def __init__(self, *args, **kwargs):
super(SkillCreatePLanguageForm, self).__init__(*args, **kwargs)
self.fields['technology'].queryset = Technology.objects.filter(group__name="Programming language")
class SkillCreateFrameworkForm(SkillBaseCreateForm):
def __init__(self, *args, **kwargs):
super(SkillCreateFrameworkForm, self).__init__(*args, **kwargs)
self.fields['technology'].queryset = Technology.objects.filter(group__name="Framework")
SkillFrameworkFormSet = inlineformset_factory(Employee, Skill, form=SkillCreateFrameworkForm, extra=1, can_delete=False)
SkillPLanguageFormSet = inlineformset_factory(Employee, Skill, form=SkillCreatePLanguageForm, extra=1, can_delete=False)
views.py
class SkillTestCreateView(AuthorizedMixin, CreateView):
"""
Create new skill instances
"""
template_name = 'edit.html'
model = Employee
form_class = EmployeeEditForm
def get(self, *args, **kwargs):
"""
Handles GET requests and instantiates blank versions of the form
and its inline formsets.
"""
self.object = Employee.objects.get(pk=self.kwargs['pk'])
form_class = self.get_form_class()
form = self.get_form(form_class)
form_framework = SkillFrameworkFormSet()
form_language = SkillPLanguageFormSet()
return self.render_to_response(
self.get_context_data(form=form,
form_framework=form_framework,
form_language=form_language))
def post(self, request, *args, **kwargs):
"""
Handles POST requests, instantiating a form instance and its inline
formsets with the passed POST variables and then checking them for
validity.
"""
self.object = Employee.objects.get(pk=self.kwargs['pk'])
form_class = self.get_form_class()
form = self.get_form(form_class)
form_framework = SkillFrameworkFormSet(self.request.POST)
form_language = SkillPLanguageFormSet(self.request.POST)
if (form.is_valid() and form_framework.is_valid() and
form_language.is_valid()):
return self.form_valid(form, form_framework, form_language)
else:
return self.form_invalid(form, form_framework, form_language)
def form_valid(self, form, form_framework, form_language):
"""
Called if all forms are valid. Creates a Employee instance along with
associated models and then redirects to a
success page.
"""
self.object = form.save()
form_framework.instance = self.object
form_framework.save()
form_language.instance = self.object
form_language.save()
return HttpResponseRedirect(reverse_lazy('profile', args=[self.kwargs['pk']]))
def form_invalid(self, form, form_framework, form_language):
"""
Called if a form is invalid. Re-renders the context data with the
data-filled forms and errors.
"""
return self.render_to_response(
self.get_context_data(form=form,
form_framework=form_framework,
form_language=form_language,
))
The problem is that I always get an error message when I submit a form:
Select a valid choice. That choice is not one of the available choices.
The problem is that when I submit a form, I always get an error message in the technology field of the queryset which is displayed first in the template.
That is, if the template
{form_framework}}
{form_language}
a mistake on
queryset = Technology.objects.filter(group__name="Framework"
if
{form_language}
{form_framework}}
a mistake on
queryset = Technology.objects.filter(group__name="Programming language"
If I leave only one form in views.py, everything starts to work.
I've been trying to figure it out for 2 days and I think I'm at a dead end. Need help!

django admin: exclude not working in change_form

I have the following admin class:
from django.contrib import admin
class CommandAdmin (admin.ModelAdmin):
list_display = ('name','status','get_requester', 'justification')
readonly_fields = ('name','status','get_requester', 'request', 'justification')
exclude = ('request',)
def get_requester(self,obj):
return obj.request.requester
get_requester.command_order_field = 'requester' #Allows column order sorting
get_requester.short_description = 'Who Requested' #Renames column head
def get_form(self, request, obj=None, **kwargs):
self.exclude = ['request']
form = super(CommandAdmin, self).get_form(request, obj, **kwargs)
return form
def get_queryset(self, request):
print request
qs = super(CommandAdmin, self).get_queryset(request).select_related('request')
return qs.filter(status='pending', request__isnull=False)
The Command model looks like this ...
class Command(models.Model):
... bunch of fields ...
justification = models.CharField(max_length=2000, blank=True, null=True)
request = models.ForeignKey('sudorequests.Request', blank=True, null=True)
When I get to the change form the 'Request' object still appears on the form. Here's a screen shot:

django - admin model assign value to limit_choices_to from another field inside the model

I have extended the admin model, so for each staff member i can assign other customers only if they are in the same group.
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
is_manager = models.BooleanField(default=False)
group_account = models.CharField(max_length=3,blank=True,null=True)
clients_assigned = models.ManyToManyField(User, limit_choices_to = Q(groups__groupaccount__group_account=group_account),blank=True,null=True,related_name='+')
class UserProfileInline(admin.StackedInline):
model = UserProfile
verbose_name = "User extra"
verbose_name_plural = "extra"
filter_horizontal = ('clients_assigned', )
def save_model(self, request, obj, form, change):
return super().save_model(request, obj, form, change)
class UserAdmin(BaseUserAdmin):
inlines = [UserProfileInline, ]
def get_form(self, request, obj=None, **kwargs):
#permissions reduce for regular staff
if (not request.user.is_superuser):
self.exclude = ("app")
self.exclude = ("user_permissions")
## Dynamically overriding
#self.fieldsets[2][1]["fields"] = ('is_active', 'is_staff','is_superuser','groups')
self.fieldsets[2][1]["fields"] = ('is_active', 'is_staff')
form = super(UserAdmin,self).get_form(request, obj, **kwargs)
return form
and extended the group admin model
class GroupAccount(models.Model):
group_account = models.CharField(,max_length=3,blank=True,null=True)
group = models.OneToOneField(Group,blank=True,null=True)
def save(self, *args, **kwargs):
super(GroupAccount, self).save(*args, **kwargs)
what im trying to do is simply to limit the client list for each manager-user by his and their group indicator(group_account field), means the available client list are those whom have the same specific group as himself, such as '555'
when the group_account = '555' in the DB the result of groups__groupaccount__group_account=group_account are empty
but if i change it Hardcoded to: groups__groupaccount__group_account='555'
its return the relevant result.
is that possible and/or what the alternative?
django 1.9
thanks for the help
You should custom the formfield_for_foreignkey method of StackInline
class UserProfileInline(admin.StackedInline):
def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
field = super(UserProfileInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
if db_field.name == 'clients_assigned':
u = request.user
if not u.is_superuser:
field.queryset = field.queryset.filter(groups__in=u.groups.all())
return field

Django ModelForm - Performance issue

I am using ModelForm to allow multiple rows edit at the same time. It is a very simple form that has series of yes_no columns. The model looks like:
models.py
class Yn(models.Model):
yn_id = models.IntegerField(primary_key=True)
description = models.CharField(max_length=30)
def __str__(self):
return ' '.join([
self.description,
])
class Meta:
managed = False
db_table = 'yn'
class Invoice(models.Model):
description = models.CharField(max_length=50)
invoice_date = models.DateTimeField()
...
invoice_sent_yn = models.ForeignKey('Yn', models.DO_NOTHING, db_column='invoice_sent_yn', related_name="invoice_sent_yn")
confirm_receipt_yn = models.ForeignKey('Yn', models.DO_NOTHING, db_column='confirm_receipt_yn', related_name="confirm_receipt_yn")
paid_yn = models.ForeignKey('Yn', models.DO_NOTHING, db_column='paid_yn', related_name="paid_yn")
forms.py
class InvoiceGridEdit(ModelForm):
model = Invoice
fields = ['description','invoice_date','invoice_sent_yn', 'confirm_receipt_yn', 'paid_yn']
def __init__(self, *args, **kwargs):
super(JurisGridEditForm, self).__init__(*args, **kwargs)
...
...
InvoiceFormSet = modelformset_factory(models.Invoice, form=InvoiceGridEdit)
views.py
class InvoiceUpdateGrid(CreateView):
template_name = "/invoice_update_grid.html"
model = Invoice
form_class = InvoviceViewEditForm
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return redirect("account_login")
def get(self, request, *args, *kwargs):
self.object = None
customer_number = self.request.GET.get('customer_number')
invoice_form = InvoiceFormSet(queryset=Invoice.objects.filter(customer_number = customer_number)
return self.render_to_response(self.get_context_data(invoice_form=invoice_form))
def post(self, request, *args, **kwargs):
self.object = None
invoice_form = InvoiceFormSet(self.request.POST)
if (invoice_form.is_valid()):
return self.form_valid(invoice_form)
else:
return self.form_invalid(invoice_form)
def form_valid(self, invoice_form):
...
...
invoice_form.save()
return redirect("customer_list")
def form_invalid(self, invoice_form):
return self.render_to_response(self.get_context_data(invoice_form=invoice_form))
The forms works fine, get and post works, except, it takes a while (~30 sec) to retrieve and update. Using django-debug-toolbar, it looks like the yn columns retrieve separately for each column for each row (~2k rows). The Yn table only has 3 rows -1 - Unknown, 0 - No, 1 - Yes.
I tried to search for work around to stop the craziness of Django hitting the DB 900 times per retrieval. I found something about caching but I have no idea how to do it.
Thanks in advance.

KeyError at / object_post//occuring because of python?or JSON?

Hello I'm getting KeyError at object_post for some reason.
I believe keyError means it's not importing data correctly, but I have no idea what's wrong with the code. If anyone has an idea I would appreciated it. My guess is my python code is wrong, but I googled around and some one says it's JSON problem. I'm not an expert in JSON(so it will be bigger prob if it's the case)...I'll post my code assuming there's something wrong with my code.
Error MEssage: KeyError at /'object_list'
Code:
views.py
for front page
class IndexView(TemplateView):
template_name = 'main/index.html'
def get_context_data(self, **kwargs):
context = super(IndexView, self).get_context_data(**kwargs)
if self.request.user.is_authenticated():
voted = Vote.objects.filter(voter=self.request.user)
posts_in_page = [post.id for post in context["object_list"]]
voted = voted.filter(post_id__in=posts_in_page)
voted = voted.values_list('post_id', flat=True)
context.update({
'voted' : voted,
'latest_posts': Post.objects.all().order_by('-created_at'),
'popular_posts': Post.objects.all().order_by('-views'),
'hot_posts': Post.objects.all().order_by('-score')[:25],
'categories': Category.objects.all(),
})
return context
Models.py
class Post(models.Model):
category = models.ForeignKey(Category)
created_at = models.DateTimeField(auto_now_add = True)
title = models.CharField(max_length = 100)
content = FroalaField()
url = models.URLField(max_length=250, blank=True)
moderator = models.ForeignKey(User, default="")
rank_score = models.FloatField(default=0.0)
with_votes = PostVoteCountManager()
views = models.IntegerField(default=0)
image = models.ImageField(upload_to="images",blank=True, null=True)
slug = models.CharField(max_length=100, unique=True)
objects = models.Manager() # default manager
def save(self, *args, **kwargs):
self.slug = uuslug(self.title, instance=self, max_length=100)
super(Post, self).save(*args, **kwargs)
def __unicode__(self):
return self.title
# for redirecting URL so slug is always shown
def get_absolute_url(self):
return '/%s/%s' % (self.id, self.slug)
def set_rank(self):
# Based on HN ranking algo at http://amix.dk/blog/post/19574
SECS_IN_HOUR = float(60*60)
GRAVITY = 1.2
delta = now() - self.submitted_on
item_hour_age = delta.total_seconds() // SECS_IN_HOUR
votes = self.votes - 1
self.rank_score = votes / pow((item_hour_age+2), GRAVITY)
self.save()
class Vote(models.Model):
voter = models.ForeignKey(User)
post = models.ForeignKey(Post)
def __unicode__(self):
return "%s voted %s" % (self.voter.username, self.post.title)
Complete Error:
KeyError at /
'object_list'
Request Method: GET
Request URL: http://127.0.0.1:8000/
Django Version: 1.8.4
Exception Type: KeyError
Exception Value:
'object_list'
Exception Location: /home/younggue/Desktop/ebagu0.2/rclone/main/views.py in get_context_data, line 25
Python Executable: /home/younggue/Desktop/ebagu0.2/env/bin/python
Edit3:
my modified view
class IndexListView(ListView):
model = Post
queryset = Post.with_votes.all()
template_name = 'main/index.html'
def get_context_data(self, **kwargs):
context = super(IndexListView, self).get_context_data(**kwargs)
if self.request.user.is_authenticated():
voted = Vote.objects.filter(voter=self.request.user)
posts_in_page = [post.id for post in context["object_list"]]
voted = voted.filter(post_id__in=posts_in_page)
voted = voted.values_list('post_id', flat=True)
context.update({
'voted' : voted,
'latest_posts': Post.objects.all().order_by('-created_at'),
'popular_posts': Post.objects.all().order_by('-views'),
'hot_posts': Post.objects.all().order_by('-score')[:25],
'categories': Category.objects.all(),
})
errors occur from here
#login_required
def add_category(request):
if request.method == 'POST':
form = CategoryForm(request.POST)
if form.is_valid():
form.save(commit=True)
return IndexListView(request)
else:
print form.errors
else:
form = CategoryForm()
return render(request, 'main/add_category.html', {'form':form})
I provided one argument request and the error says I provided two: TypeError at /add_category/
""__init__() takes exactly 1 argument (2 given).
So I googled it and people say it's from urls.py
urls.py """
urlpatterns = [
url(r'^$', IndexListView.as_view(), name='index'),
#url(r'^add_post/', views.add_post, name='add_post'),
url(r'^add_post/$', PostCreateView.as_view(), name='post-add'),
url(r'^(?P<slug>[\w|\-]+)/edit/$', PostUpdateView.as_view(), name='post-edit'),
url(r'^(?P<slug>[\w|\-]+)/delete/$', PostDeleteView.as_view(), name='post-delete'),
url(r'^add_category/', views.add_category, name='add_category'),
url(r'^(?P<slug>[\w|\-]+)/$', views.post, name='post'),
url(r'^category/(?P<category_name_slug>[\w\-]+)/$', CategoryDetailView.as_view(), name='category'),
]
I have IndexListView.as_view().
why is this error happening?
Your view inherits from TemplateView so nobody fills up the object_list entry in the context.
Instead, you might want to inherit from ListView or other generic CBVs which populate such context key
As described there:
This template will be rendered against a context containing a variable
called object_list that contains all the publisher objects.
you can see it in the code for ListView
def get(self, request, *args, **kwargs):
self.object_list = self.get_queryset()
...
def get_context_data(self, **kwargs):
"""
Get the context for this view.
"""
queryset = kwargs.pop('object_list', self.object_list)
page_size = self.get_paginate_by(queryset)
context_object_name = self.get_context_object_name(queryset)
if page_size:
paginator, page, queryset, is_paginated = self.paginate_queryset(queryset, page_size)
context = {
'paginator': paginator,
'page_obj': page,
'is_paginated': is_paginated,
'object_list': queryset
}
else:
context = {
'paginator': None,
'page_obj': None,
'is_paginated': False,
'object_list': queryset
}
if context_object_name is not None:
context[context_object_name] = queryset
context.update(kwargs)
return super(MultipleObjectMixin, self).get_context_data(**context)
As you can see, the get method sets self.object_list to the queryset retrieved and then the get_context_data method uses it to update the context for the template.
On the contrary, TemplateView does not perform such steps:
def get(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
return self.render_to_response(context)
def get_context_data(self, **kwargs):
if 'view' not in kwargs:
kwargs['view'] = self
return kwargs
so the object_list key does not exist in the context dicitonary.
Of course, in case for some reason you prefer not to use Listview you can still perform such steps in your code, overriding the get and get_context_data methods or inheriting from the proper mixins, e.g.
class IndexView(TemplateResponseMixin, MultipleObjectMixin , View):
Given your latest edit:
in add_category you do
return IndexListView(request)
which makes little sense (i.e. returning an instance of a view).
I presume you are trying to redirect to the index page, so that can be achieved with
return redirect(reverse_lazy('index'))

Categories