How to access data from models in view in Django? - django

So I have a models file:
import datetime
from django.db import models
class Organization(models.Model):
name = models.CharField(max_length=128, unique=True);
description = models.TextField(blank=True);
location = models.CharField(max_length=256, blank=True);
contact_email = models.EmailField(max_length=128, unique=True);
org_type = models.ForeignKey('OrganizationType');
created_at = models.DateTimeField(editable=False);
updated_at = models.DateTimeField();
def save(self, *args, **kwargs):
''' On save, update timestamps '''
datetime_now = datetime.datetime.now();
# If there's no ID, it's new
if not self.id:
self.created_at = datetime_now;
# Always update the modified at value
self.modified_at = datetime_now;
return super(User, self).save(*args, **kwargs);
class Meta:
app_label = 'bc';
And a view file Organization.py:
from django.shortcuts import render, redirect
from django.contrib import auth
from django.core.context_processors import csrf
from BearClubs.bc.forms.user import UserSignUpForm
from BearClubs.bc.models.organization import Organization
def directory(request):
first_50_clubs = [];
# get 50 clubs here
return render(request, 'directory.html' {'clubs': first_50_clubs});
I am really new to Django so pardon me. How do I go about getting the first 50 clubs in the first_50_clubs in the Organization.py view file?

According to the documentation, you can just use list slicing:
Use a subset of Python’s array-slicing syntax to limit your QuerySet
to a certain number of results. This is the equivalent of SQL’s LIMIT
and OFFSET clauses.
def directory(request):
first_50_clubs = Organization.objects.all()[:50]
return render(request, 'directory.html' {'clubs': first_50_clubs})
Also, you don't need to put semi-colons at the end of code lines in python.
Hope that helps.

You can get first 50 clubs in the first_50_clubs by following query :
first_50_clubs = Organization.objects.all().order_by('id')[:50]
It will fetch records when its got inserted .
If you want last inserted 50 records then just use - in order_by . like :
first_50_clubs = Organization.objects.all().order_by('-id')[:50]

Related

AttributeError at / 'str' object has no attribute 'objects'

I am new to Django. I am working on a project that uses weather API to get the weather.Everything was working fine until models.py was made and imported city on views.py
I use ver. 1.11.13
models.py
from __future__ import unicode_literals
from django.db import models
class city(models.Model):
name = models.CharField(max_length=25)
def __str__(self):
return self.name
class Meta:
verbose_name_plural ='cities'
views.py ( Error comes at cities = city.objects.all())
import requests
from django.shortcuts import render
from .models import city
def index(request):
url= 'http://api.openweathermap.org/data/2.5/weather?q={}& units=imperial&appid=e1a2ef38103d2e572d316e38452e2acd'
city = 'Lucknow'
cities = city.objects.all()
weather_data =[]
for city in cities:
r= requests.get(url.format(city)).json()
city_weather = {
'city':city.name ,
'temperature' :r['main']['temp'],
'description' :r['weather'][0]['description'],
'icon' :r['weather'][0]['icon'] ,
}
weather_data.append(city_weather)
print(weather_data)
context = {'weather_data' : city_weather}
return render(request,'weather/weather.html', context)
Solve this issue.
For dynamic table name you can use like
table_name = 'MyTable'
model = getattr(YOURAPP.models, table_name)
model.objects.all()
In your index function, you write:
def index(request):
url= 'http://api.openweathermap.org/data/2.5/weather?q={}& units=imperial&appid=e1a2ef38103d2e572d316e38452e2acd'
city = 'Lucknow'
cities = city.objects.all()
# ...
As a result, you defined city here as a locally scoped variable, and with a string value. A quick fix is to rename the string, like:
def index(request):
url= 'http://api.openweathermap.org/data/2.5/weather?q={}& units=imperial&appid=e1a2ef38103d2e572d316e38452e2acd'
city_ = 'Lucknow'
cities = city.objects.all()
# ...
# use city_ for the string element
But nevertheless, a class typically starts with an uppercase, so I would advice to rename your class City instead of city.
Furthermore I find it weird that you defined this string, since nowehere in the view, you are supposed to use it. The url.format(..) should probably use the city.name of the City object in the queryset.

Django Form use of user id

The following code is working nicely:
class SelectTwoTeams(forms.Form):
campaignnoquery = UserSelection.objects.filter(user=349).order_by('-campaignno')[:1]
currentCampaignNo = campaignnoquery[0].campaignno
cantSelectTeams = UserSelection.objects.filter(campaignno=currentCampaignNo)
currentTeams = StraightredTeam.objects.filter(currentteam = 1).exclude(teamid__in=cantSelectTeams.values_list('teamselectionid', flat=True))
team_one = forms.ModelChoiceField(queryset = currentTeams)
team_two = forms.ModelChoiceField(queryset = currentTeams)
However, you can see that the user id is currently hardcoded into the filter as 349. I would like this to be the id of the user logged in. I know in the view I can use:
currentUser = request.user
currentUserID = currentUser.id
But this code does not work within the forms section. If anyone could point me in the correct direction that would be ideal.
When I follow the suggestion below using the following form I get an error saying: NameError: name 'currentUserID' is not defined
# coding=utf-8
from dwad.threadlocals import get_current_user
from django.db.models import Max
from django import forms
from straightred.models import StraightredTeam
from straightred.models import UserSelection
class SelectTwoTeams(forms.Form):
def save(self):
currentUser = get_current_user()
currentUserID = currentUser.id
campaignnoquery = UserSelection.objects.filter(user=currentUserID).order_by('-campaignno')[:1]
currentCampaignNo = campaignnoquery[0].campaignno
cantSelectTeams = UserSelection.objects.filter(campaignno=currentCampaignNo)
currentTeams = StraightredTeam.objects.filter(currentteam = 1).exclude(teamid__in=cantSelectTeams.values_list('teamselectionid', flat=True))
team_one = forms.ModelChoiceField(queryset = currentTeams)
team_two = forms.ModelChoiceField(queryset = currentTeams)
Many thanks, Alan.
One method is to use local.threading. I have used this solution on a number of Django installations to good use.
I know there are a number of different opinions whether this is a good or bad solution. I tend to fall into the category that it can be extremely good in the right circumstances.
To set it up, create a file called threadlocals.py:
try:
from threading import local
except ImportError:
from django.utils._threading_local import local
_thread_locals = local()
def get_current_user():
return getattr(_thread_locals, 'user', None)
class ThreadLocalsMiddleware(object):
def process_request(self, request):
_thread_locals.user = getattr(request, 'user', None)
Then, add this ThreadLocalsMiddleware class to your project's middleware in settings.py:
MIDDLEWARE_CLASSES = [
...
'myproject.threadlocals.ThreadLocalsMiddleware',
...
]
Now, all you need to do is call the method get_current_user() from anywhere in your project.
from myproject.threadlocals import get_current_user
class SelectTwoTeams(forms.Form):
def save(self):
# for example:
currentUser = get_current_user()
currentUserID = currentUser.id
Found this answer at Reddit.
It is very simple and it is working good in my case.
In your view you have to include some code like this:
if form.is_valid():
obj = form.save(commit=False)
obj.user = request.user # logged in user is available on a view func's `request` instance
obj.save() # safe to save w/ user in tow

django dynamic form generation

say I have a model such:
class ComponentLength(models.Model):
component_name = models.CharField(max_length=155)
length1 = models.IntegerField()
length2 = models.IntegerField()
length3 = models.IntegerField()
length4 = models.IntegerField()
Now I have a form for the user to select a component, and on the next page I want to display 4 checkboxes for the various length options, which are different for different components.
What is the best way in Django to generate the form with these checkboxes based on the component name (accessible in session data) already selected by the user.
Any help much appreciated.
You could use a normal django form and change its fields upon instantiation, in the init method. Something like this:
class SecondForm(forms.Form):
def __init__(self, *args, **kwargs):
super(SecondForm, self).__init__(*args, **kwargs)
try:
#get the object, something like this:
obj_ = ComponentLength.objects.get(component_name = session.get('component_name_or_whatever_you_stored'))
except:
#handle the error case, e.g:
return
self.fields['length1'] = forms.CheckboxInput(attrs={'value' : obj_.length1 })
self.fields['length2'] = forms.CheckboxInput(attrs={'value' : obj_.length2 })
self.fields['length3'] = forms.CheckboxInput(attrs={'value' : obj_.length3 })
self.fields['length4'] = forms.CheckboxInput(attrs={'value' : obj_.length4 })
#Consider using a hidden input instead of polluting the session variables
#with form data
self.fields['component_length'] = forms.HiddenInput(attrs={'value' : obj_.pk})
The above code is not tested, but I expect it should work. Please let me know how it goes.
Form wizards is exactly what you need.
https://docs.djangoproject.com/en/1.7/ref/contrib/formtools/form-wizard/
See the example shown here https://docs.djangoproject.com/en/1.7/ref/contrib/formtools/form-wizard/#usage-of-namedurlwizardview
And how forms are defined here https://docs.djangoproject.com/en/1.7/ref/contrib/formtools/form-wizard/#conditionally-view-skip-specific-steps
I haven't tested the code below, but it should be something similar to the following:
myapp/forms.py
from django.forms import ModelForm
from myapp.models import ComponentLength
class ComponentLengthNameForm(ModelForm):
class Meta:
model = ComponentLength
fields = ['component_name',]
class ComponentLengthChoicesForm(ModelForm):
class Meta:
model = ComponentLength
fields = ['length1', 'length2', 'length3', 'length4',]
myapp/views.py
from django.contrib.formtools.wizard.views import SessionWizardView
from django.shortcuts import render_to_response
class ComponentWizard(SessionWizardView):
def done(self, form_list, **kwargs):
return render_to_response('done.html', {
'form_data': [form.cleaned_data for form in form_list],
})
myapp/urls.py
from django.conf.urls import url, patterns
from myapp.forms import ComponentLengthNameForm, ComponentLengthChoicesForm
from myapp.views import ContactWizard
named_contact_forms = (
('name', ComponentLengthNameForm),
('length-choices', ComponentLengthChoicesForm),
)
component_wizard = ComponentWizard.as_view(named_contact_forms,
url_name='component-wizard-form-step', done_step_name='finished')
urlpatterns = patterns('',
url(r'^my-form/(?P<step>.+)/$', component_wizard, name='component-wizard-form-step'),
url(r'^my-form/$', component_wizard, name='component-wizard-form'),
)

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})

Django pagination (get page no. corresponding to the object)

I have a paginate I am trying to get the index page from an object page (sort of pagination in reverse)
The get_paginated_posts returns a paginator for the model Post:
class PostManager(models.Manager):
def get_paginated_posts(self, request=None):
if request and request.user.has_perm('blog.change_post'):
posts = super(PostManager, self).filter(is_update=False)
else:
posts = super(PostManager, self).filter(publish=True, is_update=False)
return Paginator(posts, POSTS_PER_PAGE)
.
.
This is my model
class Post(models.Model):
.
.
.
def get_page(self, request=None):
paginator = Post.objects.get_paginated_posts(request)
for i in range(1, paginator.num_pages+1):
if self in paginator.page(i).object_list:
return i
pass
return False
My concern is the Post.objects.get_paginated_posts call in the get_page function.
Is it right to call Post class from an instance? Is there any other better way to do this possible?
Why cannot I call super(Post, self).objects.get_paginated_posts to do the same?
I understand that self.objects.get_paginated_posts wont work because of absent access for the object to its manager.
Solved
Final code as suggested by Tomasz Elendt:
class PostManager(models.Manager):
def get_paginated_posts(self, user=None):
if user and user.has_perm('blog.change_post'):
posts = super(PostManager, self).filter(is_update=False)
else:
posts = super(PostManager, self).filter(publish=True, is_update=False)
return Paginator(posts, POSTS_PER_PAGE)
class Post(models.Model):
.
def get_page(self, request=None):
return self._default_manager.filter(is_update = False, time__gt=self.time).count()/POSTS_PER_PAGE +1
#Just a one line now :P
It's not the best idea what you're doing. Try to imagine how many queries it'll be translated to -- in the worst case you'd need to retrieve all user's posts from database!
I assume that you have some predefined ordering in your Post model (the one that Paginator uses). Use that to obtain the number of user's posts that precede that specific post record. If you divide that number by the POSTS_PER_PAGE value you'll get your page number.
IMHO using PostManager in Post methods is ok. What's not ok is that you're passing request object to it while I think you should use user_id for that (and permission checking should be really part of a view logic).
EDIT: example
from django.db import models
from django.contrib.auth.models import User
POSTS_PER_PAGE = 10
class Post(models.Model):
"""
>>> from datetime import datetime, timedelta
>>> from django.db import connection
>>> from django.conf import settings
>>>
>>> user = User.objects.create_user("test", "test#domain.com")
>>> for i in xrange(100):
... p = Post.objects.create(author=user,
... pub_date=datetime.now() - timedelta(hours=i))
>>> post = Post.objects.all()[68]
>>> settings.DEBUG = True # monkey-patching settings - ugly
>>> connection.queries = [] # cleaning previous queries
>>> post.get_page()
7
>>> len(connection.queries) # print number of queries of `get_page` call
1
"""
pub_date = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(User)
class Meta:
ordering = ["-pub_date"]
def get_page(self):
return self._default_manager.filter(author__id=self.author_id).filter(
pub_date__gt=self.pub_date).count() / POSTS_PER_PAGE + 1