cannot retrieve values from database django - python

I have a table I am trying to retrieve values from. It has two foreign keys and that is it.
I use get_or_create on the table and create an object. I verify with the admin panel that the object is there. Then, I try to retrieve it but I do not get the values even though I can see them in the admin panel.
Here is the table:
class req(models.Model):
to = models.ForeignKey(User,on_delete=models.CASCADE)
from = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return "request sent"
In the piece of code below, I am retrieving from the database and I try to display it as it is in the p tag(html). In the template, I tried {{ req.to }} and {{ req.from.first_name }} but in vain, I did not see any values when html is rendered.
def get(self, request):
u = get_user(request)
try:
my_requests = req.objects.get(from=u)
except req.DoesNotExist:
fr = None
if fr == None:
return redirect(reverse('myapp:index'))
if my_requests != False:
context_dict['req'] = my_requests
return render(request, 'myapp/req.html', context=context_dict)
Can anybody see the problem that I cannot and comment ?

There are couple of issues in your code. here is the updated version which address your issue :-
def get(self, request):
req_obj, created = req.objects.get_or_create(from=request.user)
if created:
context_dict['req'] = my_requests
return render(request, 'myapp/req.html', context=context_dict)
return redirect(reverse('myapp:index'))

Related

How to display Uploaded file to the user who upload it in Django?

I am trying to build a system where users can upload their CSV file in the Django backend. But I am facing a problem, I want to display CSV file only to the user who uploaded it. I make a field in the models which can trace the user who uploaded the file. Here are some of my codes.
CSV file model:
class Data(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,default=1)
filename = models.CharField(max_length=40,blank=False)
csv_file = models.FileField(upload_to='documents/',blank=False)
def __str__(self):
return self.filename
And the view logic:
def accounts(request):
user = Data.objects.values('user')
if user == request.user:
main_data = Data.objects.all()
else:
main_data = ""
dict = {'main_data':main_data, 'name' : request.user.username}
return render(request, 'accounts.html',dict)
I am only getting that else value ' main_data=" " '.
Simply we can do:
try:
data = request.user.data
except Data.DoesNotExist:
data = ''
Also, check the example of one-to-one relationships in Django's Official Documentation.
You are trying to compare the request.user to a queryset and then also returning all Data objects. You need to use the request.user and then return only the objects linked to that user.
def accounts(request):
main_data = Data.objects.filter(user=request.user)
dict = {'main_data': main_data}
return render(request, 'accounts.html', dict)
Also you wont need the 'name' : request.user.username in your dict. You can access the username through the main_data

obj.authors.all() doesn't show anything

I'm trying to make a django site in the latest version of django, but when i use the obj.authors.all() it returns nothing.
I have tried getting rid of the all() but returns empty Queryset.
views.py
def menu(request):
obj = Book.objects.get(id=1)
obj = obj.authors.all()
else:
obj=""
return render(request, 'menu.html',
{'obj':obj,'numautgors':authors})
models.py
class Book(models.Model):
name = models.CharField(max_length=100,unique=True)
authors = models.ManyToManyField(User)
text = models.TextField(unique=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('model-detail-view', args=[str(self.id)])
I expect it to return the authors, but it returns nothing.
Sorry if a duplicate. And one more question can i show all book written by a specific author or in this case User?
You can try :
Books.objects.all().values('authors')
And suppose you want to show a book written by specific author then in that case your query should be :
Books.objects.filter(authors__username=request.user.username)
also you can use get based on your scenario
Taking assumption that your User model has username field.
I think you are sending the wrong context, so try like this:
def menu(request):
obj = Book.objects.get(id=1)
authors = obj.authors.all()
return render(request, 'menu.html', {'obj':obj,'numautgors':authors})
Alternatively you can show the authors in template directly(you don't need to pass authors to template with context at all):
{% for author in obj.authors.all %}
{{ author.id }}
{% endfor %}
You are overwriting your variables
Firstly with
obj = Book.objects.get(id=1)
You are assigning the Book object retrieven from the database to the obj variable.
Then with
obj = obj.authors.all()
You assign authors to obj again, and then you are returning authors, a variable that does not exist.
Your naming seems confusing.
If you want the authors of the book with id 1, you could do this:
authors = Book.objects.filter(id=1).authors.all()

Django objects.get matching query does not exist

I'm trying to get all attributes of a single object. I keep getting a "Devices matching query does not exist." I just cannot figure out my issue.
Models.py
`class Devices(models.Model):
category_id = models.ForeignKey(Category, on_delete=models.CASCADE)
device_description = models.CharField(max_length=100)
device_status = models.CharField(max_length=50)
device_date = models.DateTimeField()
device_user = models.CharField(max_length=50)`
Views.py
def view_status(request, pk=None):
device = Devices.objects.get(pk=pk)
return render(request, 'homesite/device_status.html', device)
urls.py
url(r'^viewstatus/$', views.view_status, name='ViewStatus'),
here is the url I use to call http://localhost:8000/homesite/viewstatus/?pk=1
device_satus.html
{% extends "base.html" %}
{% block head %}
<title>Device Status</title>
{% endblock%}
{% block body %}
<h3>Device Status Detail</h3>
{{ devices.device_description }}
{{ devices.device_status }}
{{devices.device_date|date:"Y-m-d H:m:s"}}
{% endblock %}
There are 4 records in my able so I know there is a match for PK=1.
Note, that this is not the usual way to build an URL for accessing a specific object. Below I present first the approach that integrates pk in the URI and second the one passing pk as a parameter.
1. Approach
Here you put the pk in the URI and request something like http://localhost:8000/homesite/viewstatus/1/. If you do so, you need to adapt your urls.py by specifying what part of the URI is the pk you want:
# urls.py
url(r'^viewstatus/(?P<pk>\d+)/$', views.view_status, name='ViewStatus'),
The way you wrote the view is fine:
def view_status(request, pk=None):
if pk is not None:
device = Devices.objects.get(pk=pk)
else:
device = None
return render(request, 'homesite/device_status.html', {'device' : device})
Now, views.view_status will be called with both the request object and the pk as arguments and objects.get will behave as you expected, if the pk you put in the URI exists in you database.
Note that this is the preferred way to get an object.
2. Approach
In this case you pass the pk as a parameter, so call http://localhost:8000/homesite/viewstatus/?pk=1, for example. Now pk is a parameter of a GET request. In this case:
# urls.py
url(r'^viewstatus/$', views.view_status, name='ViewStatus'),
And the view only takes the request object as argument. Within the view you can get the pk as follows:
def view_status(request):
pk = request.GET.get('pk', None)
if pk is not None:
device = Devices.objects.get(pk=int(pk))
else:
device = None
return render(request, 'homesite/device_status.html', {'device' : device})
So in this case your view does not take any arguments other than the request object.
Another issue is in your view function: Django's shortcut render takes a dict object for the optional argument context. Currently you directly pass a Devices object. You need to update your return statement in view_status:
return render(request, 'homesite/device_status.html', {'device' : device})
Hope that helps!
I get an error 'Devices' object is not iterable
urls.py
this is how the url is set up.
url(r'^viewstatus/$', views.view_status, name='ViewStatus'),
but is should be like this
url(r'^viewstatus/(?P<pk>\d+)/$', views.view_status, name='ViewStatus'),
so that I can call like this correct? http://localhost:8000/homesite/viewstatus/1/
views.py
def view_status(request):
pk = request.GET['pk']
device = Devices.objects.get(pk=pk)
return render(request, 'homesite/device_status.html', device
so i need the corresponding views.py code to work with
http://localhost:8000/homesite/viewstatus/1/
I've stared at this for hours so I know I'm missing something simple.
Try changing your view function:
def view_status(request):
pk = request.GET['pk']
device = Devices.objects.get(pk=pk)
return render(request, 'homesite/device_status.html', device)
Let me know if it helps :)

Django: Delete model object using template

I am currently using models to have users enter data, using templates (not admin) that is then stored, at which point the users can then see all the data they entered. I would like to also give users the ability to delete specific entries, this would be done using object ids to identify and delete specific objects.
Here is my views.py:
#login_required(login_url='/login/')
def fav(request):
context = RequestContext(request)
#This returns all of the data the user has entered
favorites_list = StockTickerSymbol.objects.filter(user=request.user).order_by('-added_date')
`
#This is to try to get the ID of every object in favorites_list and append it to a list
for obj in favorites_list:
stock_id = []
stock_id.append(obj.id)
#Here is where the form is processed to save the data the user has entered
if request.method == 'POST':
form = FavoritesForm(request.POST)
if form.is_valid():
stock = form.save(commit=False)
stock.user = request.user
stock.save()
return redirect(fav)
else:
print form.errors
else:
form = FavoritesForm()
context_dict = {'favorites': favorites_list, 'form':form, 'stock_id':stock_id}
return render_to_response('favorites/favorites.html', context_dict, context)
def delete(request, id):
stock_to_delete = get_object_or_404(StockTickerSymbol, pk=id).delete()
return redirect(fav)
Here is my urls.py:
url(r'^favorites/$', views.fav, name='favorites'),
url(r'^add_favorites/$', views.add_fav, name='add favorites'),
url(r'^delete/(?P<id>\d+)/$', views.delete, name='delete')
And this is the part of my template file responsible for deleting
{% for id in stock_id %}
<div align="right">Delete</div>
{% endfor %}
My problem with this code, is that the delete link in my template only gives the first object ID for all the links. For example if there are three submissions for the user, and there id's are 1,2,3. The delete link will read "/delete/1" for all the submissions, thus only allowing users to delete their first submission. Any idea on how I can solve this?
Your problem is here:
for obj in favorites_list:
stock_id = []
stock_id.append(obj.id)
You are reinitializing inside the loop.
Try this
stock_id = []
for obj in favorites_list:
stock_id.append(obj.id)
Note that you can also do:
favorites_list = StockTickerSymbol.objects.filter(user=request.user).order_by('-added_date')
stock_ids = list(facorites_list.values_list('id', flat=True)) #IMO - It is a good idea to name a list with plural for readability
Also, in your delete method - See if the user does have permission to delete the object. If not, anyone can hit this url with some random id and start deleting the objects in the database.
I would start off by adding the login_required decorator, followed by adding a created_by or attaching a group associated with the model, which need to be verified before allowing the user to delete the object.
EDIT
{% for fav in favorite_list %}
<div class="fav">
{{fav.name}}
</div>
Delete me
{% endfor %}
Now you can do away with the id list.

Paginating the results of a Django forms POST request

I'm using Django Forms to do a filtered/faceted search via POST, and I would like to Django's paginator class to organize the results. How do I preserve the original request when passing the client between the various pages? In other words, it seems that I lose the POST data as soon as I pass the GET request for another page back to my views. I've seen some recommendations to use AJAX to refresh only the results block of the page, but I'm wondering if there is a Django-native mechanism for doing this.
Thanks.
If you want to access the store data in later request, you would have to store it somewhere. Django provides several ways to archive this:
1) You can use sessions to store the query: Every visitor who visits your site will get an empty session object and you can store whatever you want inside this object, which acts like a dict. Drawback: A single visitor can't do multiple searches with pagination concurrently.
2) Use cookies: If you set a cookie which is stored on the client side, the browser will append the data of the cookie to each request where you can access it. Cookies are more server friendly, because you don't need a session manager for them on the server, but the data stored in cookies is visible (and editable) to the client. Drawback: same as before.
3) Use hidden fields: You can add a form with some hidden fields on your search-result page and store the query inside them. Then, the client will resend the query whenever you submit the form. Drawback: You must use a form with submit buttons for the pagination on your page (simple links wont work).
4) Create Links which contain the query: Instead of using POST, you can also use GET. For example, you could have a link like "/search/hello+world/?order=votes" and "paginated links" like "/search/hello+world/2/?order-votes". Then the query can be easily retrieved from the URL. Drawback: The maximum amount of data you can send via GET is limited (But that shouldn't be a problem for a simple search).
5) Use a combination: You might want to store all the data in a session or a database and access them via a generated key which you can put in the URL. URLs might then look like "/search/029af239ccd23/2" (for the 2nd page) and you can use the key to access a huge amount of data which you have stored before. This eliminates the drawback of solution 1 as well as that of solution 4. New drawback: much work :)
6) Use AJAX: With ajax you can store the data inside some js-variables on the client side, which can then passed to the other requests. And since ajax will only update your result list, the variables aren't getting lost.
Reading the very nice answer from tux21b I decided to implement the first option, i.e., to use the session to store the query. This is an application that searches real estate databases. Here is the view code (using django 1.5):
def main_search(request):
search_form = UserSearchForm()
return render(request, 'search/busca_inicial.html', {'search_form': search_form})
def result(request):
if request.method == 'POST':
search_form = UserSearchForm(request.POST)
if search_form.is_valid():
# Loads the values entered by the user on the form. The first and the second
# are MultiChoiceFields. The third and fourth are Integer fields
location_query_list = search_form.cleaned_data['location']
realty_type_query_list = search_form.cleaned_data['realty_type']
price_min = search_form.cleaned_data['price_min']
price_max = search_form.cleaned_data['price_max']
# Those ifs here populate the fields with convenient values if the user
# left them blank. Basically the idea is to populate them with values
# that correspond to the broadest search possible.
if location_query_list == []:
location_query_list = [l for l in range(483)]
if realty_type_query_list == []:
realty_type_query_list = [r for r in range(20)]
if price_min == None:
price_min = 0
if price_max == None:
price_max = 100000000
# Saving the search parameters on the session
request.session['location_query_list'] = location_query_list
request.session['price_min'] = price_min
request.session['price_max'] = price_max
request.session['realty_type_query_lyst'] = realty_type_query_list
# making a query outside the if method == POST. This logic makes the pagination possible.
# If the user has made a new search, the session values would be updated. If not,
# the session values will be from the former search. Of course, that is what we want because
# we want the 'next' and 'previous' pages correspond to the original search
realty_list_result = FctRealtyOffer.objects.filter(location__in=request.session['location_query_list']
).filter(price__range=(request.session['price_min'], request.session['price_max'])
).filter(realty_type__in=request.session['realty_type_query_lyst'])
# Here we pass the list to a table created using django-tables2 that handles sorting
# and pagination for us
table = FctRealtyOfferTable(realty_list_result)
# django-tables2 pagination configuration
RequestConfig(request, paginate={'per_page': 10}).configure(table)
return render(request, 'search/search_result.html', {'realty_list_size': len(realty_list_result),
'table': table})
Hope it helps!If anyone has any improvement to suggest, be welcome.
As #rvnovaes, a way to use session to solve the matter.
The drawback of his solution is that if there are many search fields you have to write many lines of code, and also if you show the search form in the result page, all the fields will be blank, while they should keep their values.
So I'd rather save all the post data in session, and at the beginning of the view force the value of request.POST and request.method if a session is defined:
""" ... """
if not request.method == 'POST':
if 'search-persons-post' in request.session:
request.POST = request.session['search-persons-post']
request.method = 'POST'
if request.method == 'POST':
form = PersonForm(request.POST)
request.session['search-persons-post'] = request.POST
if form.is_valid():
id = form.cleaned_data['id']
""" ... """
More info here
I did this in my web application with get parameters Maybe i can help you :
Views.py
class HomeView(ListView):
model = Hotel
template_name = 'index.html'
paginate_by = 10 # if pagination is desired
def get_queryset(self):
qs = super().get_queryset()
kwargs = {}
if 'title' in self.request.GET:
title = self.request.GET.get('title')
if title != '':
kwargs['title__icontains'] = title
if 'category' in self.request.GET:
category = self.request.GET.get('category')
if category:
kwargs['category_id'] = category
if 'size' in self.request.GET:
size = self.request.GET.get('size')
if size:
kwargs['size_id'] = size
if 'service' in self.request.GET:
service = self.request.GET.get('service')
if service:
kwargs['service_id'] = service
if 'ownership' in self.request.GET:
ownership = self.request.GET.get('ownership')
if ownership:
kwargs['ownership_id'] = ownership
qs = qs.filter(**kwargs)
return qs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
form_init = {}
form = SearchForm()
if self.request.GET.items():
try:
parameters = self.request.GET.items()
except KeyError:
parameters = {}
for key, value in parameters:
for field in form.fields:
if key == field:
form_init[key] = value
form.initial = form_init
if 'title' in self.request.GET:
title = self.request.GET.get('title')
if title != '':
context.update({
'title': title
})
if 'category' in self.request.GET:
category = self.request.GET.get('category')
context.update({
'category': category
})
if 'size' in self.request.GET:
size = self.request.GET.get('size')
context.update({
'size': size
})
if 'service' in self.request.GET:
service = self.request.GET.get('service')
context.update({
'service': service
})
if 'ownership' in self.request.GET:
ownership = self.request.GET.get('ownership')
context.update({
'ownership': ownership
})
context.update({
'search_form': form
})
return context
Pagination file html
<div class="row">
{% if is_paginated %}
<nav aria-label="...">
<ul class="pagination">
{% if page_obj.has_previous %}
<li class="page-item"><a class="page-link" href="?category={{category}}&size={{size}}&service={{service}}&ownership={{ownership}}&page={{ page_obj.previous_page_number }}">Previous</a></li>
{% else %}
<li class="page-item disabled"><span class="page-link">Previous</span></li>
{% endif %}
<span class="page-current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
<li class="page-item"><a class="page-link" href="?category={{category}}&size={{size}}&service={{service}}&ownership={{ownership}}&page={{ page_obj.next_page_number }}">Next</a></li>
{% else %}
<li class="page-item disabled"><span class="page-link">Next</span></li>
{% endif %}
</ul>
</nav>
{% endif %}
</div>
You can ask request object if it's ajax, simply request.is_ajax. This way you can detect, whether it's first post request or further questions about the next pages.
Have the search form and the results display on one single django template. Initially, use css to hide the results display area. On POSTing the form, you could check to see if the search returned any results and hide the search form with css if results exist. If results do not exist, use css to hide the results display area like before. In your pagination links, use javascript to submit the form, this could be as simple as document.forms[0].submit(); return false;
You will need to handle how to pass the page number to django's paging engine.
My suggestion would be to store the post request using a session or a cookie. In case the post data is sensitive, you should use session to store it. The code below contains my logic to implement it using session.
def index(request):
is_cookie_set = 0
# Check if the session has already been created. If created, get their values and store it.
if 'age' in request.session and 'sex' in request.session:
age = request.session['age']
sex = request.session['sex']
is_cookie_set = 1
else:
# Store the data in the session object which can be used later
request.session['age'] = age
request.session['sex'] = sex
if(request.method == 'POST'):
if(is_cookie_set == 0): # form submission by the user
form = EmployeeForm(request.POST)
sex = form.cleaned_data['sex']
age = form.cleaned_data['age']
if form.is_valid():
result = Employee.objects.all(sex=sex,age_gte=age) # filter all employees based on sex and age
else: # When the session has been created
result = Employee.objects.all(sex=sex,age_gte=age)
paginator = Paginator(result, 20) # Show 20 results per page
page = request.GET.get('page')
r = paginator.get_page(page)
response = render(request, 'app/result.html',{'result':result})
return response
else:
form = EmployeeForm()
return render(request,'app/home.html',{'form':form})
You should also check if the post fields are empty or not and change the logic according to it. You can also store the whole post request in the session as suggested by #abidibo.
You can also use cookies for the same. I have explained it here
The Below code is working, the first request is a GET request, which accesses the form, will go directly to the else block.
Once the user puts up a search query, results will be shown, which will be a post request, and 2nd if block will be activated, this request we will store in a session.
When the user accesses 2nd search page, it will be a GET request, but we are checking whether there is an active pagination session, and also checking whether it's not a page request of GET. At this point 1st if block will be trigerred.
def search(request):
if not request.method == "POST" and 'page' in request.GET:
if 'search-query' in request.session:
request.POST = request.session['search-query']
request.method = 'POST'
if request.method == 'POST':
form = Search_form(request.POST)
request.session['search-query'] = request.POST
if form.is_valid():
search_query = form.cleaned_data.get('search_query')
search_parameter = form.cleaned_data.get('search_parameter')
print(search_query, search_parameter)
queryset_list = CompanyRecords.objects.filter(**{f'{search_parameter}__icontains': search_query}).exclude(
company_name__isnull=True).exclude(description__isnull=True).exclude(phones__isnull=True).exclude(
emails__isnull=True)[:5]
page = request.GET.get('page', 1)
paginator = Paginator(queryset_list, 2)
try:
queryset = paginator.page(page)
except PageNotAnInteger:
queryset = paginator.page(1)
except EmptyPage:
queryset = paginator.page(paginator.num_pages)
return render(request, 'search/search_results.html', {'queryset': queryset})
else:
context = {
'form': Search_form()
}
return render(request, 'search/search.html', context)

Categories

Resources