showcasing one attribute of multiple instances from a model django/python - python

I have 2 models with multiple attributes and I would like to showcase a specific attribute which has multiple instances in another model:
class Carnet(models.Model):
....multiple attributes
class Consultation(models.Model):
....
date_cons = models.DateTimeField(default=datetime.now, blank=True)
There are multiple instances of date_cons. I would like to showcase the latest one added in an html code
The view method I used was this ( probably here is the problem )
def consultation(request, carnet_id):
consultation = Consultation.objects.all()
context = {
'consultation' : consultation
}
return render(request, 'carnets/carnet.html',context)
tried showcasing that attribute in an html code using this syntax
{{consultation.date_cons}}
but it doesn't showcase anything.
How do I showcase this attribute?

You are returning a list of consultation instances. Therefore you must display them in your html accordingly.
Try to use this in your html:
{% for instance in consultation %}
{{ instance.date_cons }}
{% endfor %}
For better readability, I'd use consultations (plural) for the name of the list, and use consultation for the instance in the for loop.

Related

Django - is it possible to iterate over methods?

I'm working on a Web Application in Django which works with products, prices and statistics etc.
EDIT:
More straighforward explanation: How to "group" or "mark" some of instance methods so I can iterate over them like for method in instance.name_of_the_group
To keep it simple - I have a model Product. Product has multiple attributes and methods. Some of those methods returns "statistics" data.
class Product(models.Model):
name = ...
...
def save(...
...
def get_all_colors(self):
....
def get_historical_average_price(self): #statistic method
price = <some calculation>
return price
def get_historical_minimal_price(self): #statistic method
...
return price
So there is a lot of methods like get_historical_average_price and get_historical_minimal_price.
Now I have to write labels and call these methods one by one in the project. For example when I generate a table or creating an XML export.
I would like to be able to somehow "mark" them that those are "statistic" methods, give them some name so I would be able to work with them using for loops etc.
Is there some way to do that?
Example on XML generator:
<products>
{% for product in products %}
<product>
<code>{{ product.code }}</code>
<name>{{ product.name }}</name>
<statistics>
<historical_average>{{ product.get_historical_average_price}}</historical_average>
<minimal_price>{{ product.get_historical_minimal_price}}</minimal_price>
</statistics>
</product>
{% endfor %}
</products>
So I would do something like:
<statistics>
{% for statistic_method in product.statistics %}
<{{ statistic_method.name }}>{{ statistic_method }}</{{ statistic_method.name }}>
{% endfor %}
</statistics>
instead of:
<statistics>
<historical_average>{{ product.get_historical_average_price}}</historical_average>
<minimal_price>{{ product.get_historical_minimal_price}}</minimal_price>
</statistics>
This is a great use case for using custom model managers as you can use or override the names that they use there.
So in your example, something like :
class StatisticsManager(models.Manager):
def historical_average_price(self):
...
class Product(models.Model):
name = ...
statistics = StatisticsManager()
Which would then be called in the form
product_price = Product.statistics.get_historical_average_price
and so on.
Edit:
I forgot - as you're overriding the default objects manager, I believe that you'll need to explicitly restate that as a manager, per this article - but you can have multiple managers on an object if desired, so objects, statistics, otherstuffhere.

How can I simplify this python statements

There's a model represents BBS.
I want to make change the value without update database. because I want to preserve the database value. To be precise at display time, I want it to be displayed as '[collabo]' + article.title this is what I am doing at the moment.
below is combine '[collabo]' and all of title with for loop
for article in articles:
article.title = '[collabo]'+article.title
is there any way to change the title value at one line of code? I don't want to change or update database. Or is there a better way.
If you want to do this in a single database query it's one line longer than what you have now!! but it's far more efficient.
from django.db.models import Value
from django.db.models.functions import Concat
Article.objects.annotate(new_title = Concat(V('[collabo]'),'title')))
The annotate method in the queryset is your friend here (with a little help from Concat and Value)
You could also do this at the template level
articles = Article.objects.all()
render('template.html',{'articles': articles})
And then
{% for article in articles %}
[collabo] {{ article.title }}
{% endfor %}
you may work with methods of the model class to give specific modification you want.
models.py
class Article(models.Model):
# some fields ...
def edited_title(self):
return '[collabo] {}'.format(self.title)
then you can exploit it in the templates with {{article.edited_title}}.

Django: How to return all models associated with a ForeignKey including all attributes of those models?

I have an app that I want to simply display all the URL links a page has associated with it when that page is visited.
It's similar to reddit in that there are many userpages (aka subreddits) and each page has an infinite possible amount of submitted links associated with it. The newlinkposts records are associated with a certain page via a ForeignKey.
Given a page, wow can I get all the related newlinkpost objects (including their corresponding likes, link comment, and post date) returned, in order to display them in a template?
My newlinkpost object is defined as follows:
class newlinkpost(models.Model):
newlink_tag = models.ForeignKey('userpagename') #tags link to which userpage it belongs to
link_comment = models.CharField(max_length=128) #comment to go along with post
post_date = models.DateField(auto_now=True, auto_now_add=False, null=False) #submission datestamp. later make it track editable posts if edit function is implemented
url = models.URLField(max_length = 1024, null=False) #actual submitted link
link_likes = models.IntegerField(null=False, default=0) #need to later create like button which will +1 the value
def __unicode__(self):
return self.url
When you add a ForeignKey within a model, as well as creating an attribute in the source model (in your case, newlinkpost) allowing you to find the one associated object, Django also creates a corresponding attribute inside the target model (in your case apparently userpagename).
By default this attribute is named after the source table, so in your case it will be newlinkpost_set.
That allows you to ask the question you're looking to answer: which newlinkpost objects have this userpagename?:
all_links = userpagename_instance.newlinkpost_set.all()
If you wish to apply additional filters, you can use the filter method instead:
some_links = userpagename_instance.newlinkpost_set.filter(...)
The newlinkpost_set attribute contains a RelatedManager object, which is a subtype of Manager, allowing you to use the same set of methods you could use on newlinkpost.objects, along with some additional methods allowing you to create new related objects.
Here's an example view using this technique: (this assumes you've got the model classes imported into the views module):
from django.shortcuts import render
def user_page(request, user_id):
page = userpagename.get(pk=user_id)
links = page.newlinkpost_set.all()
return render(
request,
"myapp/user_page.html",
{
page: page,
links: links,
}
)
...and here's an example of using that "links" variable in the template:
<ul>
{% for link in links %}
<li><a href="{{ link.url }}">{{ link.link_comment }} - {{ link.link_likes }} likes</li>
{% endfor %}
</ul>
You just use the reverse relationship.
my_userpagename.newlinkpost_set.all()

Using one model to filter another model in Django

I'm trying to access the information in my gadb_action model based on the action_ids in my gadb_vote model. I'm initially only getting the information for a particular legislator and then attempting to get the bills associated with the actions that legislator has voted on.
Right now, my action_list is only storing action_ids, but not the related information from the gadb_action model that I want to use in my template.
What is the best way to store that information outside of the for loop to be accessed by the template? Is there a way to write to an empty QuerySet?
Thanks in advance for any and all help!
view
def each_member(request,legislator_id):
each_member = get_object_or_404(gadb_legislator, legislator_id=legislator_id)
each_vote = gadb_vote.objects.filter(legislator_id=legislator_id)
action_list = []
for i in each_vote:
action = gadb_action.objects.filter(action_id=i.action_id)
action_list.append(action)
context = {
'each_member': each_member,
'each_vote': each_vote,
'action_list': action_list
}
return render(request, "eachmember.html", context)
models
class gadb_action(models.Model):
action_id = models.IntegerField(unique=False, max_length=4, primary_key=True)
bill_id = models.IntegerField(unique=False, max_length=12)
class gadb_vote(models.Model):
vote_id = models.IntegerField(unique=False, max_length=11,primary_key=True)
legislator_id = models.IntegerField(unique=False, max_length=11)
action_id = models.IntegerField(unique=False, max_length=11)
template
{% for i in action_list %}
{{i.bill_id}}
{{i.action_id}}
{% endfor %}
Your models are broken.
For a start, although it's not directly related to the question, you need to define your primary keys as AutoFields so that they are autoincremented every time a new entity is added. Otherwise you'll get all sorts of errors when you save a new row. (Even better, don't define the PK at all, and let Django add it automatically.)
Secondly, as lalo says, you should have ForeignKeys from Action to Bill, and from Vote to Action and Vote to Legislator. That way you can get the relevant information with a single query, and follow the foreign keys as required in your template.
(Also, Django already includes the app name in the underlying table name: no need to prefix everything with 'gadb'.)
class Action(models.Model):
bill = models.ForeignKey(Bill)
class Vote(models.Model):
legislator = models.ForeignKey(Legislator)
action = models.ForeignKey(Action)
View:
def each_member(request,legislator_id):
actions = Action.objects.filter(vote__legislator_id=legislator_id)
return render(request, "eachmember.html", {'action_list': actions})
Template:
{% for action in actions %}
{{ action.bill.name }}
{{ action.someotherfield }}
{% endfor %}

Extend Model's Queryset with additional attributes

I have simple Django model with some internet sessions (Radius logs). And want to show it in my template.
models.py:
class Radacct(models.Model):
radacctid = models.BigIntegerField(primary_key=True)
username = models.CharField(max_length=253)
nasipaddress = models.IPAddressField()
class Meta:
db_table = u'radacct'
view.py:
def ajax_radius_sessions(request, username):
radius_sessions = Radacct.objects.filter(username=username).order_by('-radacctid')
template.html:
{% for session in radius_sessions %}
{{ session.username }}, {{ session.nasipaddress }}</br>
{% endfor %}
In my template, I need to show the hostname based on user's ip-address (nasipaddress) as well.
Method 1:
Creation of Model's method.
I do not want to calculate Hostname as Model's method, because it will be triggered for every record, but the number of session for particular user can be very big — in this case it will cause huge amount of DNS-checks. 1000 sessions = 1000 DNS checks?..
Method 2a:
View level.
I was trying to this on View level, to check only unique IPs and get the "local" dictionary with IP-Hostname pairs:
#servers={'192.168.100.1':'alpha', '192.168.100.2':'beta', '192.168.100.3':'gamma'}
But I can not access this dictionary in the template, using the key as variable:
#Wrong!
{{ servers[session.nasipaddress] }}
Method 2b:
View level. Adding new attribute to the Queryset instance.
Maybe I can add a new attribute to my Radacct Model which is not connected with database. And fill it by hostname, in my View?
What is the proper way to calculate some "attribute" and then access it in the Template in Queryset {% for %} loop?
Again: it seems I can not do this as Model's method, so I think I should extend my database results with custom ones.
P.S. Sorry for a really looong post. This is my very first try on Stackoverflow. Thank you!
Model "method". Create a separate class that is responsible for looking up DNS entries and caching them, and refer to an instance of this class in a descriptor on the model.

Categories

Resources