Query set too many objects to unpack expected(2) in django templateView - django

I have written a view to show open, completed, accepted and closed tickets on dashboard on clicking which goes into particular url to display the tickets accordingly and am switching the templates according to their status, I am querying the ticket status and I get the following error
Too many objects to unpack (expected 2)
models.py
class Modes(models.Model):

Error is due to this query...
Ticket.objects.filter('status')
You should specify something like:
if Ticket.objects.filter(status='Opened'):
template_name = 'app/open_tickets.html')
Also please check the logic. Above query makes no sense in get_template_name... You should be getting one template according to request. So if request is for 'opened' then you should get template only for 'opened'.
Suppose if you want to get for 'opened' you need to pass it in query and do this:
if self.request.GET.get('status', '') == 'Opened':
template_name = 'app/open_tickets.html')

def show(request,status):
if status.title() in ['O','A,'C','Cl']:
if status.title() == 'O':
models = Model.objects.filter(status='O')
else:
models = Model.objects.filter(status=status.title(),accepted_by=request.user)
templates = {'O':'p/op.html','A':'p/d.html','C':'p/pp.html','Cl:'a.html'}
return render(request,templates[status.title()],{'tickets':tickets})
inside your urls.py
path('models/<str:status>/',views.show,name='show')

Related

Query data linked via Foreign key

I have 2 models linked 'Project' and 'Event'. Event has an FK to Project
I want to return all events that are related only to the project.
I have a basic view that returns the specific project and im trying to include the event list within that view.
def show_project_details(request,project_id):
today = now().date()
project = Project.objects.get(pk=project_id)
events = Event.objects.event_list = Event.objects.filter(event_date__gte=today).order_by('event_date')
events_list = Event.objects.get(project_name_id=project_id)
form = ProjectForm(request.POST or None, instance=project)
return render(request, 'pages/project_details.html', {"project": project, "form": form, "events": events, 'events_list':events_list})
but it returns
Event matching query does not exist.
Any ideas?
to get all the event related to a particular project
use
project = Project.objects.get(pk=project_id)
events = project.event_set.filter(event_date__gte=today).order_by('event_date')
so the full view would reduce to
def show_project_details(request,project_id):
today = now().date()
project = Project.objects.get(pk=project_id)
events = project.event_set.filter(event_date__gte=today).order_by('event_date')
form = ProjectForm(request.POST or None, instance=project)
return render(request, 'pages/project_details.html', {"project": project, "form": form, "events": events})
Brian Obot's answer is a very good solution to your actual problem.
To answer your question why you get this specific error with your code:
Event matching query does not exist.
As you have not (yet) provided your models, I can only guess that the error occurs for this line of code:
events_list = Event.objects.get(project_name_id=project_id)
objects.get will always raise an error if it does not exactly find 1 single object. For fetching data that can return 0 to many results (as is the case for regular reverse foreign key relations), you should use filter.
Your current code should work if you change the above line to:
events_list = Event.objects.filter(project_name_id=project_id)
This really will return a list (actually a queryset) - that could also be empty.
In terms of performance / amounts of statements executed on the database:
Both ways (project.event_set and Event.objects.filter) will result in extra statements to the database.
If you want to avoid that and fetch everything when you fetch the project data, you would have to work with annotations.
As long as you are not experiencing any issues, it's fine to leave it as is. If you are interested to venture into that area, read more: https://docs.djangoproject.com/en/3.2/ref/models/querysets/#annotate

Is APITest with Query params different then just normal url?

I'm writing some unit tests against an API that either returns all the books, or only returns the books of the given genre in the query params. This seems to be working when I hit it in my local dev server. However, it doesn't even go into the else statement if the genre is specified in my unit test.
My unit test looks like this:
class TitlesAndBlurbsListTestCase(APITestCase):
def setUp(self):
# Creates a lot of books with genre horror
# and books not in the horror genre
def test_horror_genre(self):
# Ensure that screener can see all the available books
self.client.login(username='b', password='b')
response = self.client.get('/api/titles-and-blurbs/?genre=horror')
self.assertEqual(response.status_code, status.HTTP_200_OK)
# Ensure that the screener gets all horror books at first
horror_books = TitlesAndBlurbs.objects.filter(genre='horror')
# I keep getting an assertion error here - it returns all the books
self.assertEqual(len(response.data), horror_books.count())
My api viewset looks like this
class TitlesAndBlurbsListViewSet(viewsets.mixins.ListModelMixin,
viewsets.mixins.RetrieveModelMixin,
viewsets.GenericViewSet):
model = TitlesAndBlurbs
permission_classes = [ScreenerPermissions]
serializer_class = TitlesAndBlurbsSerializer
def get_queryset(self):
if self.action == 'list':
genre = self.request.QUERY_PARAMS.get('genre', None)
if not genre:
print 'i dont have query params of genre'
TitlesAndBlurbs.objects.all()
else:
print genre
TitlesAndBlurbs.objects.filter(genre=genre)
return TitlesAndBlurbs.objects.all()
my url/router looks like
router.register(r'api/titles-and-blurbs', TitlesAndBlurbsListViewSet)
When I hit the url 'api/titles-and-blurbs/?genre=horror' in my browser I get the print statement and titles and blurbs that have the genre horror. However, when I hit in the
test suite, I don't get the print statement genre I get the print statement of 'i dont have query params', and it returns all books. Any help is really
appreciated.
Try passing the query parameter as a data payload instead. Change the line in your test to:
response = self.client.get('/api/titles-and-blurbs/', {'genre': 'horror'})
Django docs here on the different ways to pass query parameters in urls.
Another person reported a similar issue with an empty QUERY_PARAMS while testing DRF (see here). It looks like they fixed it but maybe they missed something or you didn't get the update.
If someone comes across this, for me it helped to:to change the url from
/api/titles-and-blurbs?genre=horror
to
/api/titles-and-blurbs/?genre=horror
Both urls were working find in Postman, but only the second one is working properly in the tests.

Using FullCalendar with Django Views

I'm trying to implement the FullCalendar on my website, but am a little new to this and not quite sure how to format what I want to do. I have a view which will grab all of an individual user's events. I want to take those events and populate the calendar with them. My issue is that I don't know what to return in the view or how to handle that return value in the JavaScript function. Here's what I have right now:
View:
def calEvents(request):
user = request.user.get_profile()
eventList = user.eventList
ownedList = user.ownedEvent
events = #Part I'm having trouble with
return HttpResponse(events)
The eventList and ownedEvent keep track of all of a user's events. They have names/dates associated with them. What I don't understand is the format I need to put all that information in to return in my HttpResponse.
My JavaScript function is:
$(document).ready(function() {
$('#calendar').fullCalendar({
eventSources: [
{
url: '/calEvents/',
editable: false,
}
]
});
});
I'm telling it to go to the Django view, but am lost after that. Thanks so much in advance!
I have done this by building a list of dictionaries in my Django view, setting at minimum the required fields of 'title' and the start time, then using simplejson.dumps with cls=DjangoJSONEncoder to return json.
from django.core.serializers.json import DjangoJSONEncoder
def calEvents(request):
# as above, then:
events = []
for event in eventList:
events.append({'title': event.name, 'start': event.start})
# something similar for owned events, maybe with a different className if you like
return HttpResponse(simplejson.dumps(events, cls=DjangoJSONEncoder), mimetype='application/json')
You may also with to limit the events you return based on the starting and ending times provided by the get request:
def calEvents(request):
user = request.user.get_profile()
start_timestamp = request.GET.get('start')
end_timestamp = request.GET.get('end')
start_datetime = datetime.datetime.fromtimestamp(float(start_timestamp))
end_datetime = datetime.datetime.fromtimestamp(float(end_timestamp))
eventList = user.eventList.filter(start_time__lte=end_datetime, end_time__gte=start_datetime)
I am neglecting error handling for the timestamp conversion - fullcalendar will give you appropriate values, but it would be best to allow for the possibility of bad input. And I am making assumptions about the structure of your event models.

Django Haystack custom SearchView for pretty urls

I'm trying to setup Django Haystack to search based on some pretty urls. Here is my urlpatterns.
urlpatterns += patterns('',
url(r'^search/$', SearchView(),
name='search_all',
),
url(r'^search/(?P<category>\w+)/$', CategorySearchView(
form_class=SearchForm,
),
name='search_category',
),
)
My custom SearchView class looks like this:
class CategorySearchView(SearchView):
def __name__(self):
return "CategorySearchView"
def __call__(self, request, category):
self.category = category
return super(CategorySearchView, self).__call__(request)
def build_form(self, form_kwargs=None):
data = None
kwargs = {
'load_all': self.load_all,
}
if form_kwargs:
kwargs.update(form_kwargs)
if len(self.request.GET):
data = self.request.GET
kwargs['searchqueryset'] = SearchQuerySet().models(self.category)
return self.form_class(data, **kwargs)
I keep getting this error running the Django dev web server if I try and visit /search/Vendor/q=Microsoft
UserWarning: The model u'Vendor' is not registered for search.
warnings.warn('The model %r is not registered for search.' % model)
And this on my page
The model being added to the query must derive from Model.
If I visit /search/q=Microsoft, it works fine. Is there another way to accomplish this?
Thanks for any pointers
-Jay
There are a couple of things going on here. In your __call__ method you're assigning a category based on a string in the URL. In this error:
UserWarning: The model u'Vendor' is not registered for search
Note the unicode string. If you got an error like The model <class 'mymodel.Model'> is not registered for search then you'd know that you haven't properly created an index for that model. However this is a string, not a model! The models method on the SearchQuerySet class requires a class instance, not a string.
The first thing you could do is use that string to look up a model by content type. This is probably not a good idea! Even if you don't have models indexed which you'd like to keep away from prying eyes, you could at least generate some unnecessary errors.
Better to use a lookup in your view to route the query to the correct model index, using conditionals or perhaps a dictionary. In your __call__ method:
self.category = category.lower()
And if you have several models:
my_querysets = {
'model1': SearchQuerySet().models(Model1),
'model2': SearchQuerySet().models(Model2),
'model3': SearchQuerySet().models(Model3),
}
# Default queryset then searches everything
kwargs['searchqueryset'] = my_querysets.get(self.category, SearchQuerySet())

Django- Many to Many field querying

I have following structure of models in django :
class BodySubPart(models.Model):
body_subpart=models.CharField(max_length=20)
def __str__(self):
return self.body_subpart
class BodyPart(models.Model):
body_part=models.CharField(max_length=20)
body_subpart=models.ManyToManyField(BodySubPart)
def __str__(self):
return self.body_part
Ex:
example,
if BodyPart=head then BodySubPart= face,mouth,eyes,nose.
if BodyPart=arm then BodySubPart= shoulder,fingers,elbow.
like this many body parts are stored.
...
now I want to create a runtime form have two choicefields (BodySubPart and BodyPart) such that when i select the BodyPart it should change the list in BodySubPart.
Ex.
The first choicefield has body parts={head,arm,chest...}
The second choice field should change when i select a particular part
If i select "head" then second choice field should show,
body sub parts={face,mouth,eyes,nose...}
Please help me here.....
What have you tried?? I think you will find people are more willing to help you if you have actually tried something yourself and not just want others to do it for you. It should go something like this:
1) BodyPart.objects.all() # all body parts
2) head = BodyPart.objects.get(body_part='head')
head_subparts = head.body_subpart.all() # all head subparts
django does a great job of explaining how to query these relationships.
https://docs.djangoproject.com/en/dev/topics/db/models/#many-to-many-relationships
In addition there are a number of really great tutorials online regarding djangos' manytomany relationships.
This requires a bit of AJAX, so first step is to create a view to handle that:
from django.core import serializers
from django.http import HttpResponse, HttpResponseBadRequest
from django.shortcuts import get_list_or_404
def ajax_get_bodysubparts(request):
bodypart_id = request.GET.get('bodypart_id')
if bodypart_id:
bodysubparts = get_list_or_404(BodySubPart, bodypart__id=bodypart_id)
data = serializers.serialize('json', bodysubparts)
return HttpResponse(data, mimetype='application/json')
else:
return HttpResponseBadRequest()
Tie that to some URL in urls.py. Then, some JavaScript for your form (assumes jQuery):
$(document).ready(function(){
$('#id_bodypart').change(function(){
var selected = $(this).val();
if (selected) {
$.getJSON('/url/to/ajax/view/', {
'bodypart_id': selected
}, function (data, jqXHR) {
options = [];
for (var i=0; i<data.length; i++) {
options.append('<option value="'+data[i].id+'">'+data[i].body_subpart+'</option>');
}
$('#id_bodysubpart).html(options.join(''));
});
}
});
});
You will probably need a combination of custom form fields and widgets to get what you want.
Check out the django-ajax-filtered-fields project to see if that is close what you are looking for. It will at least provide some guidance if you decide to create your own.
You will need some javascript to make a new request to populate your fields dynamically, so that will also not be available with standard django forms.