I want to pass a jlist (which I generate everytime the 'javaindex' method is called) to another view i.e the javaresult view. I am generating the jlist from the Question model.
def javaindex(request):
javapool = list(Question.objects.all())
random.shuffle(javapool)
jlist = javapool[:10]
request.session['jlist'] = jlist
return render(request,'index.html',{'latest_question_list': jlist})
My other view is
def javaresult(request):
ch = [0]
correct = 0
jlist = request.session['jlist']
for i in range(1,11):
s = request.POST.get(str(i))
if s:
question, choice = s.split('-')
ch.append(choice)
if jlist[i].ans == ch[i]:
correct+=1
return HttpResponse(correct)
I searched on SO and hence added the request.session['jlist'] but that is giving me an error <Question: Question object> is not JSON serializable.
How do i get rid of this? Thanks :)
Save ids of the Question objects in the session and get objects from DB in second view again.
def javaindex(request):
...
request.session['jlist'] = [j.id for j in jlist]
...
def javaresult(request):
...
jlist = Question.objects.filter(id__in=request.session['jlist'])
...
Related
Apologies for this newbie question. I'm not sure if I even phrased it correctly.
I have a class inside a function that lists a bunch of variables, and I want to be able to choose which variables are printed and returned at the final function call. However, I clearly don't understand enough about objects to accomplish this, because it raises errors when I try to attempt something.
def gpscall(call):
#Write GPSinput
out = ''
ser.write(com.GPSstatus.encode())
time.sleep(1)
#Read output
while ser.inWaiting() > 0:
decoded = (ser.read(1).decode)
out += decoded()
strlen = len(str(out))
substr = out[0:strlen-9]
#GPS? information list
variables = substr.splitlines()
#Storing each output in a variable
class GPS:
PULSE_SAWTOOTH = [int(s) for s in variables[1] if s.isdigit()]
TRACKED_SATELLITES = [int(s) for s in variables[2] if s.isdigit()]
VISIBLE_SATELLITES = [int(s) for s in variables[3] if s.isdigit()]
LONGITUDE = variables[5]
longlen = len(LONGITUDE)
LONGDEG = LONGITUDE[0:longlen-7]
LONGMIN = LONGITUDE[longlen-7:]
LATITUDE = variables[6]
latlen = len(LATITUDE)
LATDEG = LATITUDE[0:latlen-7]
LATMIN = LATITUDE[latlen-7:]
HEIGHT = variables[7]
KNOTS = variables[8]
DEGREES = [9]
GPS_STATUS = variables[10]
TIMING_MODE = variables[17]
FIRMWARE_VERSION = variables[20]
print (call)
return (call)
if __name__ == "__main__":
#Call the functions
gpscall(gpscall.GPS.LATITUDE)
This raises the error,
Function 'gpscall' has no 'GPS' member.
I don't understand why it cannot see the class, I think I'm using the function parameters incorrectly.
Any help with my poorly written code would be greatly appreciated.
Perhaps something like so is your intention? __init__ will initialize the object, and the self. will "save variables to the object."
class GPS:
def __init__(self):
#Write GPSinput
ser.write(com.GPSstatus.encode())
#Read output
out = ''
while ser.inWaiting() > 0:
decoded = (ser.read(1).decode)
out += decoded()
#GPS information list
substr = out[0:len(str(out))-9]
variables = substr.splitlines()
self.PULSE_SAWTOOTH = [int(s) for s in variables[1] if s.isdigit()]
self.TRACKED_SATELLITES = [int(s) for s in variables[2] if s.isdigit()]
self.VISIBLE_SATELLITES = [int(s) for s in variables[3] if s.isdigit()]
self.LONGITUDE = variables[5]
self.LONGDEG = LONGITUDE[0:len(LONGITUDE)-7]
self.LONGMIN = LONGITUDE[len(LONGITUDE)-7:]
self.LATITUDE = variables[6]
self.LATDEG = LATITUDE[0:len(LATITUDE)-7]
self.LATMIN = LATITUDE[len(LATITUDE)-7:]
self.HEIGHT = variables[7]
self.KNOTS = variables[8]
self.DEGREES = variables[9]
self.GPS_STATUS = variables[10]
self.TIMING_MODE = variables[17]
self.FIRMWARE_VERSION = variables[20]
gps = GPS()
print(gps.GPS_STATUS)
Yor cls inside the function is perfect and there is nothing wrong there. You are just trying to call the function and the cls objects in a wrong way.
if __name__ == "__main__":
#Call the functions
gpscall(gpscall.GPS.LATITUDE) <---- ERROR HERE
gpscall is a function, so when you are trying to access GPS.LATITUDE, it won't find any objects. You would have to do either this
gpscall(gpscall("").GPS.LATITUDE)
But I think the best way to do this is to write the func inside the cls. You will still be able to access all the variables of the cls, and it won't create much hassle.
PS: That's a good question, not a noob one. Good luck (y)
I come from native POO programming languages and I'm new in Python, also Django.
I see that in Django they put all code from an app in same views.py or models.py.
Now I'm in a view called:
def create_ticket(self):
....
And inside I have this code
is_staff=User.objects.get(pk=request.user.id).is_staff
if is_staff==1:
R_Client_Accountant = LinkUserContable.objects.filter(contable=mongoId)
print(R_Client_Accountant)
accountantList = []
for relation in R_Client_Accountant:
try:
rmongosql = RMongoSql.objects.get(mongoId=relation.user.id)
user = User.objects.get(pk=rmongosql.helpdeskId)
accountantList.append((user.id,user.username))
except:
pass
else:
R_Client_Accountant = LinkUserContable.objects.filter(user=mongoId)
accountantList = []
for relation in R_Client_Accountant:
try:
rmongosql = RMongoSql.objects.get(mongoId=relation.contable.id)
user = User.objects.get(pk=rmongosql.helpdeskId)
accountantList.append((user.id,user.username))
except:
pass
As you can see I repeat code inside the 'try' just exchanging {user XOR contable}
If I want to write a function passing by parameter this {user XOR contable} where should I place it ?
To me, in corresponding model from models.py is not correct because there are so much code lines referring to different models and views.py is just for view functions right ?
Regards,
VĂctor.
you can use the getattr function to use a string to get the required attribute getattr(relation, relation_attr)
your function would look like this
def create_ticket(self):
is_staff=User.objects.get(pk=request.user.id).is_staff
if is_staff==1:
relation_attr = 'user'
else:
relation_attr = 'contable'
R_Client_Accountant = LinkUserContable.objects.filter(contable=mongoId)
print(R_Client_Accountant)
accountantList = []
for relation in R_Client_Accountant:
try:
rmongosql = RMongoSql.objects.get(mongoId=getattr(relation, relation_attr).id)
user = User.objects.get(pk=rmongosql.helpdeskId)
accountantList.append((user.id, user.username))
except:
pass
I know if we have a model class, we can make a generate table and use:
class Meta:
model = MyModel
To display every field.
Now say if I have a list of dictionaries, instead of model, is there a similar way to do so?
(Since there are so many different dictionaries, which might be dynamically created, I don't wanna create a customized one each time :-))
You can create your own class that inherits from Table and define the fields you want there.
class JsonTable(Table):
json_key_1 = Column()
json_key_2 = Column()
Also django tables2 have a fields attribute but you can't use it if your data is an array of dicts.
I've been doing this too, here's a rough sketch.
Piggy-backing on top of django_tables2 is miles ahead of rolling your own!
Plus, I hook up the results to jquery FooTable plugin.
import django_tables2 as tables
counter = 0
def generate(li_dict):
#unique classname.
global counter
counter += 1
table_classname = "MyTableClass%s" % (counter)
class Meta:
#ahhh... Bootstrap
attrs = {"class": "table table-striped"}
#generate a class dynamically
cls = type(table_classname,(tables.Table,),dict(Meta=Meta))
#grab the first dict's keys
li = li_dict[0].keys()
for colname in li:
column = tables.Column()
cls.base_columns[colname] = column
return cls
#now, to make use of it...
li_dict = [dict(a=11,b=12,c=13),dict(a=21,b=22,c=23)]
cls = generate(li_dict)
table = cls(li_dict)
# below didn't work, wanted a whole bunch of django setup done first.
# but I fairly confident it would...
print table.as_html()
>>>django.core.exceptions.ImproperlyConfigured: {% querystring %} requires django.core.context_processors.request to be in your settings.TEMPLATE_CONTEXT_PROCESSORS in order for the included template tags to function correctly.
#this did...
print "%s" % table
>>><django_tables2.tables.MyTableClass1 object at 0x1070e1090>
i am sorry for poor english :), but a think which can help, actually with this we can transforme a numpy (matrix) in a generic django table2. By the way, thanks Pyeret for your help.
def convert_array_list_dict(arr):
_list = []
for i in xrange(0, arr.shape[0]):
_list.append(dict(enumerate(arr[i,:])))
for i in xrange(0,len(_list)):
for key in _list[i].keys():
_list[i]["col_" + str(key)] = _list[i].pop(key)
return _list`
This function above convert numpy array to list of dict
counter = 0
def list_dict(dict_):
global counter
counter += 1
table_classname = "MyTableClass%s" % (counter)
class Meta:
attrs = {"class": "paleblue", 'width': '150%'}
cls = type(table_classname, (tables.Table,), dict(Meta=Meta))
list_ = dict_[0].keys()
for colname in list_:
column = tables.Column()
cls.base_columns[colname] = column
return cls
This code make a generic table...and
t = np.loadtxt(doc.document)
tab = convert_array_list_dict(t)
table = list_dict(tab)
table_content = table(tab)
RequestConfig(request, paginate={'per_page': 30}).configure(table_content)
return render(request,'app/snippets/upload_file.html',{'document':document,'table_content':table_content})
Above we can see how use all code...
I have a small model method I'm using to get the previous and next object relative to the current object. It looks something like this:
class Article
...
def get_prev_next(self):
articles = list(Article.objects.all())
i = articles.index(self)
try:
p = articles[i - 1]
except IndexError:
p = None
try:
n = articles[i + 1]
except IndexError:
n = None
return {'prev': p, 'next': n}
It works, and may well be inefficient, but now I want to use it in a different model.
I'd like to make this into a mixin, but I can't figure out how to get the original model class name so I can run Model.objects.all() and get my list.
I have so far:
class PrevNextMixin(object):
objects = list(???.objects.all())
i = objects.index(self)
...
A mixin is still a class. The code still needs to go into a method. That method will get a self argument just as it does now.
class PrevNextMixin(object):
def get_prev_next(self):
objects = list(self.__class__.objects.all())
I'm trying to create notifications like facebook has. Everything works all right but I have duplicates. For instance, action = like, url = post/1 I want to get all notifications with status = 1 - unread and eliminate duplicates where action and url are the same. You can find code below I have such error:
error: 'list index out of range' in
if n_dup[i]['url'] == n_dup[j]['url'] and n_dup[i]['action'] == n_dup[j]
def recieve_notification(request):
t = loader.get_template('notifications.html')
nots = Notification.objects.filter(recipent=request.user, status=1, pub_date__gte=datetime.datetime.now()-datetime.timedelta(days=3))
n_dup = [] #list of notifications with duplicates
for n in nots:
n_dup.append({'id':n.id, 'url':n.url, 'action':n.action})
i = len(n_dup)-1
j = len(n_dup)-1
while j>=0:
while i>=0:
if n_dup[i]['url'] == n_dup[j]['url'] and n_dup[i]['action'] == n_dup[j]['action'] and i is not j:
del n_dup[i]
i-=1
j-=1
out_n = []
for n in n_dup:
n_id = n['id']
out_n.append(Notification.objects.get(id=n_id))
c = RequestContext(request, {'notifications':out_n, 'notifications_count':len(out_n)})
return HttpResponse(t.render(c))`
Maybe you are in knowledge of better way to code all this stuff?
On the first iteration of both loops, j == i == len(n_dup)-1, so n_dup[i] == n_dup[j]. It is considered a duplicate and is remove. On the second iteration, you'll try to access n_dub[len(n_dup)-1] which doesn't exist any more, because you removed it.
If I may suggest an alternative approach, lets be lazy and have python do the duplicate detection for us :
class Notification:
def __init__(self, id, url, action):
self.id = id
self.url = url
self.action = action
def __eq__(self, other):
return self.url == other.url and self.action == other.action
def __hash__(self):
return hash(self.url) ^ hash(self.action)
unique_notifications = {Notification(n.id, n.url, n.action) for n in nots}
We define a notification object with a way to compare it and compute a hash (this is needed to put it in a set), and create a set of the notifications. A set never contains duplicate, so you can now iterate over the set !
You can also add this methods to your notification object and use it directly. You would then write :
out_n = set(Notification.objects.filter(...))
Bonus : the algorithm used by the set to remove duplicate is much more efficient than the one you where using.