Django data saving and presenting - python

My Django project need to acquire one list after processing in one function of views.py.
def acquire(request):
import sys
n = []
for topic in Topic.objects.filter(owner=request.user).order_by("date_added"):
entries = topic.entries.all()
q = entries.text
n.append(q)
return render(request, "projects/topics.html", n)
The list "n" above need to be transferred to another function of views.py for the information in another "results.html" page.
def results(request):
data = XXXX
return render(request, "projects/results.html", {"datas": data})
How could I edit "XXX" in results function to transfer the "n" list?

You can write a utility function that can be used by both views and stores the data for the current session:
def acquire(request):
data = _get_data(request)
return render(request, "projects/topics.html", {'data': data})
def results(request):
data = _get_data(request)
return render(request, "projects/results.html", {'data': data})
# this is not a view, but a utility function
def _get_data(request)
# this will try to use the data generated in a previous request of
# the same session. So the data might be stale by now
if not 'user_entries' in request.session:
n = []
for topic in Topic.objects\
.filter(owner=request.user)\
.order_by('date_added')\
.prefetch_related('entries'): # prefetch avoids the nested queries
for entry in topic.entries.all():
n.append(entry.text)
request.session['user_entries'] = n
return request.session['user_entries']

You can declare the list n outside of the function so you can use it wherever you want, like:
n = []
def acquire(request):
import sys
for topic in Topic.objects.filter(owner=request.user).order_by("date_added"):
entries = topic.entries.all()
q = entries.text
n.append(q)
return render(request, "projects/topics.html", n)
def results(request):
data = n
return render(request, "projects/results.html", {"datas": data})

You have to remember that whatever variable you set, it only lives within the view/function as Django is stateless. That's why you have a database and cookies.
This is how you do it. Unless that list has thousands and thousands of entries, this will be fast.
def results(request):
data = []
for topic in Topic.objects.filter(owner=request.user).order_by("date_added"):
entries = topic.entries.all()
q = entries.text
data.append(q)
return render(request, "projects/results.html", {"datas": data})
If you want to be really fast, you could change the request and work on the database level and create a join. Something along the lines of this (I'm a bit rusty)
data = Entries.objects.filter(topic__owner=request.user).order_by("topic__date_added").values("text")

Related

django edit and update multiple object of one form

I have one form for add information to table and in craete view I can copy the form as much I want and insert it to the table like this:
My form and can copy them:
But when I want to edit and update them how can I pass the queryset to form and show them in template I write my view like this and choose formset but my formset never show in template:
def machineedit(request, id):
querymachine = machinefixedmodel.objects.get(pk=id)
querywarranty = warranty.objects.get(machine_id=id)
# querygallery = galleryModel.objects.filter(machine_id=id)
querynet = netpriod.objects.filter(machine_id=id)
newadform = modelformset_factory(netpriod, form=netpriodfrom,fields=('activity', 'material'),
extra=0)
# print(newadform)
formmachine = MachinefixedForm(instance=querymachine)
formwaranty = warrantyForm(instance = querywarranty)
# formgallery = galleryform(instance = querygallery)
# formblueprint = galleryform(instance = querygallery)
# formnetpriod = netpriodfrom(instance=querynet)
formnetpriod = newadform(request.POST or None, querynet)
context ={'formmachine': formmachine,
# 'formgallery': formgallery,
'formwarranty': formwaranty,
# 'formblueprint': formblueprint,
'formnetpriod': formnetpriod,}
return render(request, "edit.html", context)
Is the way I choose the right way or not?
can anyone help me please...

Django - Check if a variable set exists in the Database and process it if it does?

So I have a Django App, where a CSV-File can be uploaded. My CSV-File has 9 columns that can be divided into two "datasets" where the first 5 columns need to be handled as one information and the other 4 need to be handled as another information. I cannot put the first 5 in one cell and the other ones in another cell. I would like to check whether or not the first dataset exists and if it does, process it. The same applies to the other dataset. And if both datasets do not exist already it should just update the Database with get_or_create.
Here is my views.py idea
def import_csv(request):
if request.method == "POST":
with open('C:/Users/admin/Desktop/djangoexcel/b.csv') as file:
reader = csv.reader(file)
for row in reader:
var = CSV_File4.objects.filter(
attr1=row[0], attr2=row[1], attr3=row[2], attr4=row[3], attr5=row[4],
)
if var.exists():
TemplateResponse(request, "documents/replace_entry.html", {'var' : var})
else:
for row in reader:
switch = CSV_File4.objects.filter(
attr6=row[5], attr7=row[6], attr8=row[7], attr9=row[8]
)
if var2.exists():
TemplateResponse(request, "documents/replace_entry.html", {'var2' : var2})
else:
for row in reader:
_, p = CSV_File4.objects.get_or_create(
attr1=row[0], attr2=row[1], attr3=row[2], attr4=row[3], attr5=row[4],
attr6=row[5], attr7=row[6], attr8=row[7], attr9=row[8]
)
return redirect('documents:index')
form = UploadFileForm()
return render(
request, "documents/csv_upload.html", {"form": form}
)
It should look something like this. How can I make this work. It was just an idea with filter() and exists() but is there a Python way to do something like this? Any help would be appreciated.
Currently, you are trying to recursively iterate through reader three times. That's not possible, because it is an Iterator, not a list. Anyway, you only need to do it once and then work on that particular line, before skipping to the next.
def import_csv(request):
if request.method == "POST":
with open('C:/Users/admin/Desktop/djangoexcel/b.csv') as file:
reader = csv.reader(file)
for row in reader:
ds1 = CSV_File4.objects.filter(
attr1=row[0], attr2=row[1], attr3=row[2], attr4=row[3], attr5=row[4],
).exists()
ds2 = CSV_File4.objects.filter(
attr6=row[5], attr7=row[6], attr8=row[7], attr9=row[8]
).exists()
if ds1:
pass # Process first dataset
if ds2:
pass # Process second dataset
if not (ds1 and ds2):
_, p = CSV_File4.objects.get_or_create(
attr1=row[0], attr2=row[1], attr3=row[2], attr4=row[3], attr5=row[4],
attr6=row[5], attr7=row[6], attr8=row[7], attr9=row[8]
)
return redirect('documents:index')
return render(
request, "documents/csv_upload.html", {"form": UploadFileForm()}
)

Django project show processed data instantly

I have one django project. It has one function in view.py to process the data from the inputs to give the output for other function. However the processing time for the function is kind of long. I want to fulfill the instant demonstration of the processed output. How could I achieved that? The following processing() function is for the processing purpose. And the output 'user_entries' is for the demonstration in results() as followed.
def processing(request):
import sys
n = []
for topic in Topic.objects.filter(owner=request.user).order_by("date_added"):
entries = topic.entries.all()
m = []
for p in entries:
q = p.text
m.append(q)
n.append(m)
list = []
start(list, n)
request.session['user_entries'] = list
return request.session['user_entries']
def results(request):
data = processing(request)
return render(request, "project/results.html", {"datas": data})
In the start() function of the processing() function. There is one part list.append() to add new output into list. But it seems that the new appended list cannot be transferred and show the instant results in project/results.html?
What you're doing could likely be done a lot more simply.
def results(request):
return render(
request,
"project/results.html",
{
"user_entries": Entry.objects.filter(topic__owner=request.user),
"start_values": "...", # Whatever start is appending...
},
)
Since you have a foreign key from entry to User, you could also use request.user.topic_set.all() to get the current user's topics.
Or, if you actually do need those lists nested...
# ...
"user_entries": (
topic.entries.all() for topic in
Topic.objects.filter(owner=request.user)
),
# ...
Just based on what you're showing us, it seems like your ordering -- for both Topic and Entry -- should probably have a sensible default set in, e.g., Topic.Meta.ordering, which in this case would probably look like this:
class Topic(models.Model):
# ...
class Meta:
ordering = ("date_added",)
# ...
That way, in this and most other cases, you would not have to apply .ordering(...) manually.

Getting 0 when using json.decode

I am a beginner in Django as well as Python.
I first generate 50 random numbers and store them in a list and then in a text field in model User.
def generate(request, user_id):
easy = [] * 55
cnt = 0
while cnt < 50:
random_id = random.randint(1, 200)
if random_id not in easy:
easy.append(random_id)
cnt += 1
current_user = User.objects.get(pk=user_id)
current_user.question_array = json.dumps(easy)
return render(request, 'comp/question.html', {'easy': easy[0], 'question_id': 1,'user_id':user_id})
But when I try to retrieve the value from field I get only 0.
When I try to use it as a list it shows an error of "int object cannot be subscript".
This is the code to retrieve it:
def next(request,user_id, question_id):
current_user = User.objects.get(pk=user_id)
jsonDec = json.decoder.JSONDecoder()
easy = jsonDec.decode(current_user.question_array)
return render(request, 'comp/question.html',
{'easy': easy, 'question_id': int(question_id) + 1,'user_id':user_id})
I have used the answer to this question given by mindthief to store a list in a table.
Edit:
My main problem is that the list is not getting stored in database. Any ideas why?
You need to add a .save() call to save the data to the db:
current_user = User.objects.get(pk=user_id)
current_user.question_array = json.dumps(easy)
current_user.save()
...
BTW, you can also use random.sample():
easy = random.sample(range(200), 50) # in python 2.x use xrange()
and json.loads():
easy = json.loads(current_user.question_array)
If you use PostgreSQL (highly recommended) you can even use a JsonField.
And finally, if the questions are stored in another model (Question), consider using a ManyToManyField instead.

search multiple fields django

I'm trying to build a search system, and I want to search by multiple fieldsname, state, city, in my django models. I wrote the below code, yet I've been unable to figure out how to go about it. I use Q but it seems not working:
views.py:
def data_consulting(request):
if request.method == 'POST':
form = FilterForm(request.POST)
if form.is_valid():
conditions = [('toBuy', form.cleaned_data['toBuy']), ('name__contains', form.cleaned_data['searchName']),(('price__gte', form.cleaned_data['searchPriceBegin']), ('price__lte',form.cleaned_data['searchPriceEnd'])),(('calories__gte', form.cleaned_data['searchCalorieBegin']), ('calories__lte', form.cleaned_data['searchCalorieEnd'])), (('date__gte',form.cleaned_data['DateBegin']), ('date__lte', form.cleaned_data['DateEnd']))]
all_products = Product.objects.filter(reduce(operator.or_, [Q(condition) for condition in conditions]))
send = True
all_products = Product.objects.filter(reduce(operator.or_, [Q(condition) for condition in conditions]))
else:
form = FilterForm()
all_products = Product.objects.all()
return render(request, 'mealManager/data_consulting.html', locals())
Have a think about what
reduce(operator.or_, [Q(condition) for condition in conditions])
becomes with e.g. [('toBuy', 'bread'), ('name__contains', 'bread')]. It becomes
Q(('toBuy', 'bread')) | Q(('name_contains', 'bread'))
which is obviously wrong syntax, since Q rather needs kwargs than a tuple:
Q(toBuy='bread') | Q(name__contains='bread')
that's where the ** operator comes to the rescue. If you get data like this:
[{'toBuy': 'bread'}, {'name__contains': 'bread'}]
which may be accomplished by simply changing the conditions assignment you can then do
reduce(operator.or_, [Q(**condition) for condition in conditions])
which translates in the particular case to
Q(toBuy='bread') | Q(name__contains='bread')
which is exactly what we need.

Categories