how to get the file name? - python

please help to get the file name.
I uploaded the images to the database. model:
class AvtoPark(models.Model):
title = models.CharField(max_length=100)
date = models.DateField()
image = models.FileField(upload_to='avtos/static/uploads/')
#classmethod
def get_all_entries(self):
return self.objects.all()
field "IMAGE" contains addresses like:
avtos/static/uploads/img1_b.png
template I bring them as follows:
{% for entrie in all_entries_avtopark %}
{{ entrie.image.url }}
{% endfor %}
the result is displayed:
avtos/static/uploads/img1_b.png
I need to display:
img1_b.png

In your model add this:
import os
...
class AVTPark(models.Model):
...
#property
def image_name(self):
return os.path.basename(self.image.name)
In your template:
{% for entrie in all_entries_avtopark %}
{{ entrie.image_name }}
{% endfor %}

Edited :
You can create your own method in your models.py class.
class AvtoPark(models.Model):
title = models.CharField(max_length=100)
date = models.DateField()
image = models.FileField(upload_to='avtos/static/uploads/')
#classmethod
def get_all_entries(self):
return self.objects.all()
def get_image_name(self):
# here you can apply your logic what you want to display
# try to do same like below i am doing
return str(self.image.url).split('/')[-1]
while in template you can call directly like :
{% for entrie in all_entries_avtopark %}
{{ entrie.get_image_name( }}
{% endfor %}

Related

How to check if an identical element exists in another table in Django?

I have two models: CaseRequest and Case. The CaseRequest object has values name and datebirth. I need to check if the same values exists for name and datebirth in Case. For instance, The result should be like this:
Case:
Name DateBirth
Don Honn 01.03.1959
Freak Hu 04.11.1993
Wend Don 06.03.1988
CaseRequest:
Name DateBirth
Tom Hawk 01.05.1999 - no
Don Honn 01.03.1959 - yes
Fold Len 03.07.1967 - no
Freak Hu 04.11.1993 - yes
Wend Don 13.12.1956 - no
My code:
Models.py
class CaseRequest(models.Model):
name = models.CharField(max_length=255)
datebirth = models.DateField()
status = models.CharField(max_length=255)
timeapplication = models.DateField()
category = models.CharField(max_length=255)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('caserequest')
class Case(models.Model):
name = models.CharField(max_length=255)
datebirth = models.DateField()
def __str__(self):
return self.name + ' | ' + str(self.datebirth)
def get_absolute_url(self):
return reverse('case_list')
Views.py
class CaseRequestView(ListView):
model = CaseRequest
template_name = 'caserequest.html'
caserequest.html
<div>
{% for caserequest in object_list %}
<div>
<p>{{ caserequest.name }}, {{ caserequest.datebirth }}</p>
<!-- The result should be here: YES or NO -->
</div>
{% endfor %}
</div>
You can simply create a #property decorator, say for example case_exists in the models so:
class CaseRequest(models.Model):
name = models.CharField(max_length=255)
datebirth = models.DateField()
status = models.CharField(max_length=255)
timeapplication = models.DateField()
category = models.CharField(max_length=255)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('caserequest')
#property
def case_exists(self):
return Case.objects.filter(name=self.name, datebirth=self.datebirth).exists()
Then in the template use it as:
<div>
{% for caserequest in object_list %}
<div>
<p>{{ caserequest.name }}, {{ caserequest.datebirth }} - {% if caserequest.case_exists %} Yes {% else %} No {% endif %}</p>
</div>
{% endfor %}
</div>
I think you must to create a py file called utils.py or similar in same directory where you have view.py with following code:
from django import template
from ptii.models import Case
register = template.Library()
#register.simple_tag
def get_case(caserequest_name, caserequest_datebirth):
if Case.objects.filter(name=caserequest_name).filter(
datebirth=caserequest_datebirth).exists():
return('Yes')
else:
return('No')
and in your html you have to load the file utils.py and use the function like this:
{% load utils.py %} {# load the file #}
{% get_case caserequest.name caserequest_datebirth as exist %} {# get Yes or No #}
Then you can use exist field in yout html as this:
{{ exist }}

How do you get the max value for a foreign key value in models.py file?

This is my html file
{% for member in member_list %}
{% for batting in batting_list %}
{% if member.id == batting.member.id %}
{{ batting }}
<br>
{{ batting.match.id }}
<br>
{{ batting.runs }}
<br>
<hr>
{% endif %}
{% endfor %}
{% endfor %}
This is my models.py file
class Member(models.Model):
name = models.CharField(max_length=40, default='')
def __str__(self):
return str(self.name)
class Batting(models.Model):
member = models.ForeignKey(Member, on_delete=models.CASCADE, default='')
runs = models.IntegerField(blank=True, null=True)
match = models.ForeignKey(Match, on_delete=models.CASCADE, default='')
def __str__(self):
return str('{0} {1} scored {2} runs'.format(self.member, self.match.date, self.runs))
I am trying to figure out how I show the max runs for a member x in the html file. Currently I have been able to do it for the whole Batting table but not for the individual member! Any help please
You can query with:
from django.db.models import Max
member.batting_set.aggregate(
max_runs=Max('batting__runs')
)['max_runs']
This will be None if no related Battings exist.
You can annotate the Members queryset with:
from django.db.models import Max
member_list = Member.objects.annotate(
max_runs=Max('batting__runs')
)
and thus then render this with:
{% for member in member_list %}
{{ member.max_runs }}
{% endfor %}
You can use annotate over members to get their batting with highest runs value.
from django.db.models import Max
Member.objects.annotate(max_runs=Max("batting_set__runs"))
Then show {{ member.max_runs }} on your template.
You need to create annotation in your queryset which will contain highest runs for a member.
from django.db.models import Max
Member.objects.annotate(max_runs=Max('batting__runs'))
You can access it like a regular field
member_object.max_runs
I'm not sure about your view, but for a ListView the class will look like this
class MemberView(ListView):
template_name = 'tmp.html'
model = Member
def get_queryset(self):
return Member.objects.annotate(max_runs=Max('batting__runs')).all()

Django foreign key form field rendering in template

I would like to create a view for multiple object deletion. For this, I thought I could use a modelformset_factory.
This are my models:
class Item(models.Model):
rfid_tag = models.CharField()
asset = models.OneToOneField('Assets', default=None, null=True,
on_delete=models.SET_DEFAULT,)
date = models.DateTimeField(name='timestamp',
auto_now_add=True,)
...
class Assets(models.Model):
id = models.AutoField(db_column='Id', primary_key=True)
assettag = models.CharField(db_column='AssetTag', unique=True, max_length=10)
assettype = models.CharField(db_column='AssetType', max_length=150)
...
class Meta:
managed = False
db_table = 'Assets'
ordering = ['assettag']
def __str__(self):
return f"{self.assettag}"
def __unicode__(self):
return f"{self.assettag}"
Below is the form and formset factory:
class ItemDelete(forms.ModelForm):
asset = forms.CharField(required=True,
help_text= "Item asset tag",
max_length=16,
)
delete = forms.BooleanField(required=False,
label="Delete",
help_text='Check this box to delete the corresponding item',
)
class Meta:
model = Item
fields = ['asset']
ItemDeleteMultiple= forms.modelformset_factory(model=Item,
form=ItemDelete,
extra=0,
)
The view:
class DeleteMultipleView(generic.FormView):
template_name = *some html file*
form_class = ItemDeleteMultiple
success_url = *some url*
def form_valid(self, form):
return super().form_valid(form)
And the template:
{% extends "pages/base.html" %}
{% block title %}
<title>Delete Multiple</title>
{% endblock %}
{% block static %}
{% load static %}
{% endblock %}
{% block content %}
<h1>Delete Multiple Items</h1>
<form class="item_delete_multiple_form" action ="." method="POST"> {% csrf_token %}
<table border="2">
<tr><th colspan="3" scope="row">Select Items to Delete</th></tr>
{% for item_form in form %}
<tr>
{% if item_form.non_field_errors %}
<td>{{ item_form.non_field_errors }}</td>
{% endif %}
{% if item_form.asset.errors %}
<td>{{item_form.asset.errors}}</td>
{% endif %}
<td><label for="{{ item_form.asset.id_for_label }}">AssetTag {{forloop.counter}}:</label></td>
<td>{{item_form.asset}}</td>
{% if item_form.delete.errors %}
<td>{{item_form.delete.errors}}</td>
{% endif %}
<td>{{item_form.delete}}</td>
</tr>
{% endfor %}
</table>
</form>
{% endblock %}
{% block script %}
{% endblock %}
The template is not very easy to the eye, so here is the important part: <td>{{item_form.asset}}</td>.
The issue is the following:
If I don't add the asset = CharField() part in the ItemDelete form, the template will render what the __str__ / __unicode__ method of the Assets model will return (the assettag field) in a choice field.
If the asset field is a CharField in the form, the template will render the id of the Assets. The database entry in the Item table.
I would like to render asset.assettag in a CharField (read only text input). Is it possible to do this?
Or is there a better way to achieve the multiple delete operation, using a list of objects and a checkbox?
I have came to the following solution:
class ItemDelete(forms.ModelForm):
asset = forms.CharField(required=True,
help_text= "Item asset tag",
max_length=16,
disabled=True,
)
delete = forms.BooleanField(required=False,
label="Delete",
help_text='Check this box to delete the corresponding item',
)
def __init__(self, *args, **kwargs):
super(ItemDelete,self).__init__(*args, **kwargs)
self.initial['asset'] = Assets.objects.get(id=self.initial['asset']).assettag
class Meta:
model = Item
fields = ['asset']
Given that the input field is used just for presentation purposes (is disabled and cannot be edited), I think it will do. The downside is that it will hit the database for every object (being a formset, every object will have it's own form).
I am still open to better suggestions.

How to display multiple ForeignKey filtered items in a single view in django?

I'm trying to understand the best way to display ForeignKey filtered data in a Django model.
I have three models reduced to this:
// models.py
class Publisher(models.Model)
def publisher_name = models.TextField()
def publisher_slug = models.SlugField()
def founded_year = models.IntegerField()
class Album(models.Model)
def album_name = models.TextField()
def publisher = models.ForeignKey('Publisher', related_name='albums')
class Song(models.Model)
def song_name = models.TextField()
def album = models.ForeignKey('Album', related_name='songs')
def published_year = models.IntegerField()
I have a URL that is composed of: /<publisher>/<published_year>/
The view I'm having trouble composing is supposed to be details like this:
Title of: Publisher.publisher_name
List of All Albums by the publisher: List of All songs from that album published the same year as the publisher__published_year: List of All songs from that album published as the url
The way, I've tried to do this that works right now is similar to this:
// views.py
class SongYearView(TemplateView):
def get_context_data(self, **kwargs):
context = super(SongYearView, self).get_context_data(**kwargs)
context['publisher'] = Publisher.objects.get(slug=kwargs['publisher_slug']
album_list=[]
for album in context['publisher'].albums.all():
single_album = dict()
single_album['album'] = album
single_album['publisher_year_song'] = album.songs.filter(published_year=context['publisher'].published_year)
single_album['filtered_year_song'] = album.songs.filter(published_year=kwargs['published_year']
album_list.append(single_album)
context['albums'] = album_list
return context
Then in the template I'm doing (with stripped out formatting)
// template.html
{{ publisher.name }}
{% for album in albums %}
{{ album.album.album_name }}
{% for song in album.publisher_year_song %}
{{ song.song_name }}
{% endfor %}
{% for song in album.filtered_year_song %}
{{ song.song_name }}
{% endfor %}
{% endfor %}
While this does work, it's not pretty and I'm pretty sure there are better ways of doing this.
This is an odd example, but just a basic example of my more detailed models. The way to think about it is Publisher -> Album -> Song or A -> B -> C. And I'm trying to get a view of all B items, that are only linked with a specific A item and then get two sets of C items for each B item, where one set is filtered on an A property and the other set is filtered on a passed argument from a URL.
I tried to get a custom model.Manager to help get this constructed, but didn't have much luck.
You could do add a custom template filter of_year:
#register.filter
def of_year(songs, year):
return songs.filter(published_year=year)
And change your template to
// template.html
{{ publisher.name }}
{% for album in publisher.albums %}
{{ album.album.album_name }}
{% for song in album.songs|of_year:publisher.founded_year %}
{{ song.song_name }}
{% endfor %}
{% for song in album.songs|of_year:filtered_year %}
{{ song.song_name }}
{% endfor %}
{% endfor %}
And clean your view:
// views.py
class SongYearView(TemplateView):
def get_context_data(self, **kwargs):
context = super(SongYearView, self).get_context_data(**kwargs)
context['publisher'] = Publisher.objects.get(slug=kwargs['publisher_slug'])
context['filtered_year'] = kwargs['published_year']
return context
Edit: rename the template filter

Haystack search on a many to many field is not working

I'm trying to run a search on a model that has a many to many field, and I want to filter the search using this field.
here is my current code:
search_indexes.py
class ListingInex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
business_name = indexes.CharField(model_attr='business_name')
category = indexes.MultiValueField(indexed=True, stored=True)
city = indexes.CharField(model_attr='city')
neighborhood= indexes.CharField(model_attr='neighborhood')
state = indexes.CharField(model_attr='state')
address = indexes.CharField(model_attr='address')
zip_code = indexes.CharField(model_attr='zip_code')
phone_number = indexes.CharField(model_attr='phone_number')
def get_model(self):
return listing
def index_queryset(self, using=None):
return self.get_model().objects.all()
def prepare_category(self, obj):
return [category.name for category in obj.category_set.all()]
listing_text.txt
{{ object.business_name }}
{{ object.state }}
{{object.city}}
{{object.zip_code}}
{{object.phone_number}}
{{object.neighborhood}}
{% for category in obj.category.all %}
{{ category.name }}
{% endfor %}
I'm trying to do a simple search like:
search_results = SearchQuerySet().filter(category=query_text).filter
it returns an empty list. Thanks in advance.
Reading your code I think the problem is here:
{% for category in obj.category.all %}
{{ category.name }}
{% endfor %}
Category is not an object, is a MultiValueField. Maybe if you try something like:
{% for category in object.category.all %}
{{ category.name }}
{% endfor %}
object.category.all instead of obj.category.all. I'm not sure the solution is this, but I'm pretty sure the error could be in this 3 lines.

Categories