Django - Cannot resolve keyword - django

I am trying to filter results in a django view using a function as follows:
views.py
def index(request):
european_team_list = Team.objects.all().filter(type = 'Europe')
context = {'european_team_list': european_team_list}
return render(request, 'myapp/index.html', context)
admin.py
class Team(models.Model):
continent = models.CharField()
def _team_type(self):
if self.country = "Europe":
return "Europe"
else:
return "Not Europe"
team_type = property(_team_type)
...other fields...
However, when I load the page, I get an error "Cannot resolve keyword 'team_type' into field. Choices are:" and then it lists all the fields in the Team class other than team_type. Any guidance would be much appreciated.

The simple answer is that you can't do this with the filter() method. filter() is used to construct SQL queries and can only operate on objects at the database level.
So you should figure out how to phrase your query using the database values. It's not clear what your actual code is, but it might look something like:
european_team_list = Team.objects.filter(continent='Europe')
or:
european_team_list = Team.objects.filter(country__in=('France', 'Poland'))

Related

Django Filters - Edit queryset based on slug from url

So I have a simple model called Pages. Every Page belongs to a certain category, since this is a ForeignKey relation, a Page can only belong to a single category.
Besides categories we also use tags to furthermore filter the different pages.
We use a category view to display all pages belonging to a certain category, easy peasy.
The thing is, we use django-filters to filter the pages by selecting different tags. The list of tags is increasing by the amount of pages. Therefore I would like to only show related tags to the category.
urls.py
path('<slug:category_slug>/', views.PageByCategoryView.as_view(), name='page_by_category'),
views.py
class PageByCategoryView(FilterView):
logger.info("Category view is called")
model = Page
filterset_class = PageByCategoryFilter
strict = False
queryset = Page.published_objects.all()
template_name = 'pages/page_by_category.html'
filters.py
class PageByCategoryFilter(django_filters.FilterSet):
tags = django_filters.ModelMultipleChoiceFilter(
queryset=Tag.objects.filter(page__category_id='2'), <-- actually works!
conjoined=True,
widget=forms.CheckboxSelectMultiple()
)
class Meta:
model = Page
fields = [
'tags__slug'
]
So the tags used in the filter actually get filtered by page__category_id = 2, this is exactly what I want to achieve though I want to do this dynamically. I tried to define the qs like so;
#property
def qs(self):
queryset = super(PageByCategoryFilter, self).qs
current_category = self.request.GET.get('category_slug')
if current_category:
logger.info("Current category is in url")
return queryset.filter(category__slug=current_category)
return queryset
This just doesn't seem to be working, how can i get the current_category from the url?
Alright, what I did below does actually work but it look kinda hackish..
Doe anyone have a better answer on solving this issue?
def category_filter(request):
path = request.path
category_slug = re.sub('\/+', r'', path)
current_category = category_slug
return Tag.objects.filter(page__category__slug=current_category).distinct()
With best regards,
Kevin
Your original view function should be able to take a parameter category_slug where the category slug of the URL is passed in, like in this example from the Django docs (notice how num is declarad as an int in the URL and then passed as an argument to page):
In urls.py
path('blog/page<int:num>/', views.page),
In your view function
def page(request, num=1):
...
If you're using Django REST, you should be able to get the URL parameter your kwargs member attribute, like so:
In urls.py
url('^purchases/(?P<username>.+)/$', PurchaseList.as_view()),
In your view classes:
class PurchaseList(generics.ListAPIView):
serializer_class = PurchaseSerializer
def get_queryset(self):
"""
This view should return a list of all the purchases for
the user as determined by the username portion of the URL.
"""
username = self.kwargs['username'] # this is what you're after
return Purchase.objects.filter(purchaser__username=username)

Filtering OrganizationUser's by Organization in Django-Organizations

There is a relatively similar thread on this topic, but I can't seem to figure out how to translate it to my situation. I have a roster that I need to only display the organizationusers within the same organization of the viewer. I have a webapp that I am developing that is used to manage volunteers in an organization. I'm still new to backend development so I'm having trouble problem solving.
This is the code for the table view using Django_Tables2 package:
#tables.py
class VolunteerTable(tables.Table):
class Meta:
model = OrganizationUser
# views.py
def VolunteerRoster(request):
table = tables.VolunteerTable(OrganizationUser.objects.all())
return render(request, 'staff/roster.html', {'table': table})
I'm trying to figure out how to either convert the view to a class-based view so I can use the OrganizationMixin and the SingleTableView in Django_Tables2's documentation.
I was thinking about something like this based on the other threads explanation
class VolunteerRoster(SingleTableView, OrganizationMixin):
table_class = VolunteerTable
queryset = OrganizationUser.objects.all()
template_name = "staff_roster.html"
def get_queryset(self):
return self.queryset.filter(organization=self.get_organization())
When I try this I get: "TypeError: init() takes 1 positional argument but 2 were given"
As I said, I'm still new to django so I'm not really sure what to fix in this instance.
Try:
def get_queryset(self):
return OrganizationUser.objects.filter(organization=self.request.user.organization)

Django FilterSet set initial value

We are using Django_Filterset in our project. I have been asked to set a default filter value for a foreign key column in the model
class RegFilter(django_filters.FilterSet):
class Meta:
model = models.Reg
fields = {
'id': ['exact'],
'nom_id': ['icontains'],
'nom_name': ['icontains'],
'product__name': ['icontains']
}
The product name should default to a product already in the db when the initial screen is displayed - any idea how this can be achieved? Appreciate your help.
I built on the answer given by #Gayathri and fixed a few small issues. He had a typo in his code, and the code wouldn't work with multiple choice fields, since they require the MultiValueDict functionality for multiple entries.
Given a rather regular view, here is the full code (in Python3 syntax):
class BookListView(FilterView):
model = Book
filterset_class = BookFilter
def get_filterset_kwargs(self, filterset_class):
kwargs = super().get_filterset_kwargs(filterset_class)
if kwargs['data'] is None:
filter_values = MultiValueDict()
else:
filter_values = kwargs['data'].copy()
if not filter_values:
# we need to use `setlist` for multi-valued fields to emulate this coming from a query dict
filter_values.setlist('status', ['new', 'ready'])
filter_values['sorting'] = '-created'
kwargs['data'] = filter_values
return kwargs
I managed to solve this one and thought the solution might help someone else in a situation similar to me.
In the views.py, override the FilterView method
def get_filterset_kwargs(self, filterset_class):
kwargs = super(RegFilter, self).get_filterset_kwargs(filterset_class)
if kwargs['data'] is None:
request_dict = {}
else:
request_dict = kwargs['data'].dict()
# This default will not be populated if any other filter options are chosen to restrict the query set
if not request_dict:
request_dict.update({
'product__name': 'ABC Product'
})
request_dict = kwargs['data']
return kwargs
This should now set the default product as 'ABC product' when no other options are passed to restrict the data fetched.

Django: how to use custom manager in get_previous_by_FOO()?

I have a simple model MyModel with a date field named publication_date. I also have a custom manager that filters my model based on this date field.
This custom manager is accessible by .published and the default one by .objects.
from datetime import date, datetime
from django.db import models
class MyModelManager(models.Manager):
def get_query_set(self):
q = super(MyModelManager, self).get_query_set()
return q.filter(publication_date__lte=datetime.now())
class MyModel(models.Model):
...
publication_date = models.DateField(default=date.today())
objects = models.Manager()
published = MyModelManager()
This way, I got access to all objects in the admin but only to published ones in my views (using MyModel.published.all() queryset).
I also have
def get_previous(self):
return self.get_previous_by_publication_date()
def get_next(self):
return self.get_next_by_publication_date()
which I use in my templates: when viewing an object I can link to the previous and next object using
{{ object.get_previous }}
The problem is: this returns the previous object in the default queryset (objects) and not in my custom one (published).
I wonder how I can do to tell to this basic model functions (get_previous_by_FOO) to use my custom manager.
Or, if it's not possible, how to do the same thing with another solution.
Thanks in advance for any advice.
Edit
The view is called this way in my urlconf, using object_detail from the generic views.
(r'^(?P<slug>[\w-]+)$', object_detail,
{
'queryset': MyModel.published.all(),
'slug_field': 'slug',
},
'mymodel-detail'
),
I'm using Django 1.2.
In fact, get_next_or_previous_by_FIELD() Django function (which is used by get_previous_by_publication_date...) uses the default_manager.
So I have adapted it to reimplement my own utility function
def _own_get_next_or_previous_by_FIELD(self, field, is_next):
if not self.pk:
raise ValueError("get_next/get_previous cannot be used on unsaved objects.")
op = is_next and 'gt' or 'lt'
order = not is_next and '-' or ''
param = smart_str(getattr(self, field.attname))
q = Q(**{'%s__%s' % (field.name, op): param})
q = q|Q(**{field.name: param, 'pk__%s' % op: self.pk})
qs = MyModel.published.filter(q).order_by('%s%s' % (order, field.name), '%spk' % order)
try:
return qs[0]
except IndexError:
def get_previous(self):
return self._own_get_next_or_previous_by_FIELD(MyModel._meta.fields[4], False)
def get_next(self):
return self._own_get_next_or_previous_by_FIELD(MyModel._meta.fields[4], True)
This is not a very clean solution, as I need to hardcode the queryset and the field used, but at least it works.

Django: How to make a query for on object based on an M2M field (multiple selections for field on search form)

I need help coming up with an efficient way to do a search query for a set of objects, based on a M2M field. My search form is going to look something like Blue Cross Blue Shield's | eg: this image
Now, let's suppose my model looks like this:
# models.py
class Provider(models.Model)
title = models.CharField(max_length=150)
phone = PhoneNumberField()
services_offered = models.ManyToManyField(ServiceType)
def __unicode__(self):
return self.title
class ServiceCategory(models.Model):
service_category = models.CharField(max_length=30)
def __unicode__(self):
return self.service_category
class Meta(object):
verbose_name_plural = "Service Categories"
class ServiceType(models.Model):
service_type = models.CharField(max_length=30)
service_category = models.ForeignKey(ServiceCategory)
def __unicode__(self):
return u'%s | %s' % (self.service_category, self.service_type
Also, we have to keep in mind that the options that we select are subject to change, since how they display on the form is dynamic (new ServiceCategories and ServiceTypes can be added at anytime). *How should I go about constructing a query for the Provider objects, given that a person using the search form can select multiple Services_Offered?*
This is currently my HIGHLY INEFFICIENT METHOD:
#managers.py
from health.providers.models import *
from django.db.models import Q
class Query:
def __init__(self):
self.provider_objects=Provider.objects.all()
self.provider_object=Provider.objects
self.service_object=ServiceType.objects
self.category_objects=ServiceCategory.objects.all()
def simple_search_Q(self, **kwargs): #matt's learning note: **kwargs passes any dictionary
return self.provider_objects.filter(
Q(services_offered__service_type__icontains=kwargs['service']),
Q(title__icontains=kwargs['title']),
Q(state=kwargs['state']),
).distinct().order_by('title')
====================
#views.py
from django.shortcuts import render_to_response
from health.providers.models import *
from health.search.forms import *
from health.search.managers import Query #location of the query sets
from django.core.paginator import Paginator, InvalidPage, EmptyPage
from django.template import RequestContext
def simple_search(request):
if request.method == 'POST':
SimpleSearch_form = SimpleSearch(request.POST)
if SimpleSearch_form.is_valid():
request.session["provider_list"] = None
kwargs = {'title': request.POST['title'],
'service': request.POST['service'], 'state': request.POST['state'] }
provider_list = Query().simple_search_Q(**kwargs)
return pagination_results(request, provider_list)
else:
SimpleSearch_form = SimpleSearch()
return render_to_response('../templates/index.html', { 'SimpleSearch_form': SimpleSearch_form},
context_instance=RequestContext(request))
How can I make my query:
Obtain Provider objects based on selecting multiple request.POST['service']
More efficient
Thanks for any help in advanced.
Best Regards,
Matt
1: for multiple request.POST['service'], I assume you mean these are CheckBoxes.
I'd make the CheckBox values ID's, not names, and do a PK lookup.
'services_offered__pk__in': request.POST.getlist('service')
That would return all Provider objects that have ALL of the services selected.
PS: You are also using CapitalCase for instances which is very confusing. If you want your code to be readable, I highly recommend some changes to your style (don't use CapitalCase for instances or variables) and make your variables more descriptive.
SimpleSearch_form = SimpleSearch() # what is SimpleSearch?
simplesearch_form = SimpleSearchForm() # now, it's very clear what the class SimpleSearchForm is
# and the form instance is clearly a for instance.
2: making it more efficient? You could get rid of a lot of code and code separation by remove your whole Query class. Also, I don't know why you are using Q objects since you are not doing anything that would require it (like OR or OR + AND).
def simple_search(request):
if request.method == 'POST':
searchform = SimpleSearchForm(request.POST)
if searchform.is_valid():
request.session['provider_list'] = None
post = request.POST
providers = Provider.objects.filter(services_offered__pk__in=post.getlist('services'),
title=post['title'], state=post['state'])
return pagination_results(request, provider_list)
else:
searchform = SimpleSearchForm()
return direct_to_template(request, '../templates/index.html', { 'searchform': searchform})