Combining model data to form url pattern - django

I am generating a generic list right now, with the following code:
views.py
class ServiceReportIndex(LoginRequiredMixin, ListView):
model = TblServiceRecords
context_object_name = 'all_servicereports'
login_url = 'login'
template_name = 'servicereport/servicereport_index.html'
def get_context_data(self, **kwargs):
context = super(ServiceReportIndex, self).get_context_data(**kwargs)
context['companies'] = TblCompanies.objects.all()
return context
In my template, I want to generate a URL using both of the models. The TblServiceRecords model contains a column that references the company_id, which is the primary key of the appropriate company in the TblCompanies model. I want to use the company_name from the Companies model in my list view. How would I go about doing that? I'm sure it's simple but I can't seem to get my url tags done correctly.
<div class="col-sm-4">
<p>Company Name</p>
{% for servicereport in all_servicereports %}
<p>{% for servicereport.company_id in companies.company_id %} {{ companies.company_name }} {% endfor %}</p>
{% endfor %}
</div>
Also, how can I be sure my views.py is set up correctly for multiple model functionality? I ask because if I put
{% for company_name in companies %}
{{companies.company_name}}
{% endfor %}
In my template, nothing comes up, but there are no errors either.

Probably you cannot see companies bacause of this:
{{companies.company_name}}
companies is queryset and it does not have company_name property.
Try this:
{% for company_name in companies %}
{{company_name.company_name}}
{% endfor %}

Related

How can i make a certain template visible only to confirmed users in Django?

I'm creating a site and I successfully added an email confirmation system using django-allauth. Now I would like to have some parts of my site available only to users who confirmed their email.
Suppose that part looks something like this:
{% extends "main/header.html" %}
{% if user.is_authenticated %}
{% block content %}
<body>
<div>
<p> Here are are a bunch of features etc... </p>
</div>
</body>
{% endblock %}
{% endif %}
Now, I know how to do that in theory, but not practically. I figured that I need to add a statement that checks if the email is confirmed. What I'm not understanding is where should I add this statement and what that should look like. Should it be on the template? Or should I create a view for this? Any advice is appreciated? Thanks in advance!
I think its best to put the login in your CustomUser Model:
class CustomUser(AbstractUser):
#property
def has_verified_email(self):
return self.emailaddress_set.filter(verified=True,primary=True).exists()
Then use in template:
{% if user.has_verified_email %}
// some lines
{% endif %}
If you haven't overridden your User model, then you can put it in a separate model which has a OneToOne relation to your User model:
class Profile(models.Model):
user = models.OneToOneField(User)
#property
def has_verified_email(self):
return self.user.emailaddress_set.filter(verified=True,primary=True).exists()
Then use it in template:
{% if user.profile.has_verified_email %}
// some lines
{% endif %}
Second best option would be to use in View, but you will need to put the same logic in every view. If you are using a Class Based View, you can make a Mixin and use it in them:
class SomeMixin(object):
def get_context_data(self, *args, **kwargs):
context = super(SomeMixin, self).get_context_data(*args, **kwargs)
context['has_verified_email'] = self.request.user.emailaddress_set.filter(verified=True,primary=True).exists()
return context
class ActualView(SomeMixin, TemplateView):
# subclassing from the mixin in
// template code
{% if has_verified_email %}
// some lines
{% endif %}

Receiving a list of related models from the list of objects (bound by a foreign key). Django

I have two very simple classes for products and photos. I would like to present products on the main page of my store along with photos related to a foreign key. But I do not know how to do this, I found many answers to get this in the view using a join like 'prefetch_related' but my ID changes for each case. So how do you present your photos for each product? are there any Django tags about which I do not know?
my models.py
class Product(models.Model)
name = models.CharField(max_length=10)
class Image(models.Model)
image = models.ImageField()
name_related = models.ForeignKay(Product, on_delate=models.CASCADE)
views.py
def home(request):
product_list = Product.objects.all()[:12]
#img = ??
context = {'product_list': product_list,
}
return render(request, 'home.html', context)
home.html
{% for product in product_list %}
{{ product.name }}
<!-- {{ product.imge }} ' element presenting the first photo for each 'product' model'???-->
{% endfor %}
Any help will be appreciated.
Since a foreign relation has been established you can iterate through the related models from the parent model.
The related models are already accessible from the parent model without doing anything explicit.
In your template you can do this:
{% for product in product_list %}
{{ product.name }}
{% for product_image in product.image.all %}
<!-- Iterate through this products related images -->
{{ product_image.image.url }}
{% endfor %}
{% endfor %}
For performance reasons, you will want to prefetch the relations, or else for every product you will do an additional query, so, in your view you will want to add this:
product_list = Product.objects.all().prefetch_related('image')[:12]
Just do
{% for product in product_list %}
{{ product.name }}
{% for image in product.image.all %}
<!-- {{ image.image.url }} -->?
{% endfor %}
{% endfor %}

Return multiple models from a view in Django

I am learning Django,
I am having a problem with fetching data from 2 different models with the same view.
My models are as follow :
#python_2_unicode_compatible
class Destination(models.Model):
roadtripname = models.CharField(max_length=100)
def __str__(self):
self.roadtripname
#python_2_unicode_compatible
class Trajectories(models.Model):
roadtripname = models.ForeignKey(Destination, on_delete=models.CASCADE)
place_text = models.CharField(max_length=100)
def __str__(self):
return self.place_text
my view class is this :
class IndexView(generic.ListView):
template_name = 'roadtrip/index.html'
context_object_name = 'roadtrip_list'
def get_queryset(self):
return Destination.objects.filter()
my html is :
{% for roadtrip in roadtrip_list %}
{{ roadtrip.roadtripname }}
{% endfor %}
I have tried to return my 2 models like this :
return Destination.objects.filter(), Trajectories.objects.filter()
and then in html doing
{% for roadtrip in roadtrip_list[0] %}
{{ roadtrip.roadtripname }}
{% endfor %}
but this does not work, I do not know how to be able to access both the Destination and Trajectories models. Could anyone point me in the right direction?
I could just loop through the data from the second set(trajectories) and save in an javascript array when it's equal to the select value.
You could but that is just awful and you're just opening yourself up to allow a client to modify something that they really don't need to.
With every django many-to-x relationship you can find all objects related to another with _set so just keep your initial get_queryset the same (returning destination) and then get trajectories for each object.
{% for roadtrip in roadtrip_list %}
{% for trajectory in roadtrip.trajectories_set.all %}
{# Use trajectories #}
{% endfor %}
{{ roadtrip.roadtripname }}
{% endfor %}
*I'm aware there are very simple optimizations that could be made here for performance improvements but I'm intentionally not including them

get request.session from a model method in django

Hay, is it possible to a get a request.session value from a model method in django?
MEGA UPDATE
Here is my model
class GameDiscussion(models.Model):
game = models.ForeignKey(Game)
message = models.TextField()
reply_to = models.ForeignKey('self', related_name='replies', null=True, blank=True)
created_on = models.DateTimeField(blank=True, auto_now_add=True)
userUpVotes = models.ManyToManyField(User, blank=True, related_name='threadUpVotes')
userDownVotes = models.ManyToManyField(User, blank=True, related_name='threadDownVotes')
votes = models.IntegerField()
def html(self):
DiscussionTemplate = loader.get_template("inclusions/discussionTemplate")
return DiscussionTemplate.render(Context({
'discussion': self,
'replies': [reply.html() for reply in self.replies.all().order_by('-votes')]
}))
def _find_users_who_have_voted(self):
user_list = []
for user in self.userDownVotes.all():
user_list.append(user.id)
for user in self.userUpVotes.all():
user_list.append(user.id)
return user_list
users_voted = property(_find_users_who_have_voted)
and my view is called like this
<ul>
{% for discussion in discussions %}
{{ discussion.html }}
{% endfor %}
</ul>
and the template
<li>
<small>
({{ discussion.votes }} votes)
{% if user_id not in discussion.users_voted %}
user not in list!
{% endif %}
</small>
<strong>{{ discussion.message }}</strong>
{% if replies %}
<ul>
{% for reply in replies %}
{{ reply }}
{% endfor %}
</ul>
{% endif %}
the value 'user_voted' returns a list of user ids who has voted on this discussion.
I want to see if the request.session['user'].id value is inside this list
Why don't you use Django's render_to_string inside a view, which would have request happily available to it, and avoid model method altogether?
UPDATE: after skimming your mega update, you should look into Django's inclusion tags and use the data from the model to fill a template, not use a model to render the template. Keep your model and your template separate - Django is an MVT / MCV framework for good reason :)
you can access the current user, and so their session using threadlocals middleware
http://code.arcs.org.au/gitorious/django/django-andsome/blobs/ee8447e3dad2da9383ff701ec640b44cd50d2b0a/middleware/threadlocals.py
but keep in mind:
http://code.djangoproject.com/wiki/CookBookThreadlocalsAndUser
There might be better solutions to your problem. Maybe you'd like to elaborate why you need request.session on model level?
UPDATE:
since you explicitly call some method - probably from a view - why don't you just put the request.user as parameter to your html method?
models.py:
def html(self, user):
your code...
views.py:
yourmodel.html(request.user)
UPDATE to your MEGA UPDATE:
This is exactly what {% include %} is for:
in your first template do this:
{% for discussion in discussions %}
{% include "discussion.html" }}
{% endfor %}
and the second template has request.user.id in its namespace:
{% if request.session.user.id not in discussion.users_voted %}
user not in list!
{% endif %}

django url from another template than the one associated with the view-function

Heyy there,
i have for example a view function like this:
def profile_view(request, id):
u = UserProfile.objects.get(pk=id)
return render_to_response('profile/publicProfile.html', {
'object_list': u,
},
context_instance=RequestContext(request))
and the url:
url(r'^profile_view/(?P\d+)/$',
profile_view,
name='profile_view'),
my problem is that i want to use the function's url in another template too, for example
in the search in blog template, where people see the posts of some persons, and they want to navigate to their profile.
the search view may look like that:
def searchn(request):
query = request.GET.get('q', '')
if query:
qset = (
Q(post__iexact=query)
)
results = New.objects.filter(qset).distinct()
else:
results = []
return render_to_response('news/searchn.html',{
'results': results,
'query': query},
context_instance=RequestContext(request))
and the template:
{% if query %}
Results for "{{ query|escape }}":
{% if results %}
<ul>
{% for object in results %}
<li>{{ object.post }} <a href='../../accounts/profile_view/{{object.id}}/'> {{ object.created_by }} </a> {{object.date}} </li>
{% endfor %}
</ul>
{% else %}
<p>No posts found</p>
{% endif %}
{% endif %}
there, in created_by, i'd like to put a link to my user profile, but the user profile view doesn't 'point' to this template.
What shoul i do?
Thanks!
You usually don't call model or view functions from a template, you link to URLs which in turn be dispatched to view functions.
Dana: I hope I understand your problem correctly, but if you want to use the data from two "functions", you could achieve the same method by creating a model that links the two data fields you are using together, using a foreign key.
So you'd have
class MyCustomModel(models.Model):
profile = models.ForeignKey(Profile, unique=True)
otherdata = models.CharField("Some other field", blank=True, null=True)
You could then call your view on this model.