Access to models with a foreign key in the template - python

I have a profile model with a one-to-one relationship to the User model so I can access to both models in the templates tanks to the user variable like this:
template.html
{% if user.profile.phone == 1234567890 %}
Show something
{% endif %}
That works fine, the condition gives True and show something but I have too the models Property and User_Property, the User_Property model have as Foreignkey the ids from User and Property.
models.py
class Property(models.Model):
name = models.CharField(max_length=50, unique=True)
class User_Property(models.Model):
us = models.ForeignKey(User, related_name='up_us')
prop = models.ForeignKey(Property, related_name='up_prop')
So if I try to access to the User_Property model like this:
{% if user.user_property.prop == 1 %}
Show something
{% endif %}
I can't access it shows nothing like it was False even when it's True, I have tried with user.user_property.prop_id == 1 too. It is beacause the relationship with the Profile model was made with the OneToOneField and the relationship with User_Property was made with the ForeignKey field and I need to pass in the context the User_Property model?
And it is possible to access to Property model like if I use a JOIN SQL statement in the template? something like this:
{% if user.user_property.property.name == 'the name of the property' %}
Show something
{% endif %}
Sorry for the long Post but I tried to add all the need info.
EDIT: Ok if someone need something similar this is what I did to solve the problem.
Create a context_processor.py to return a instance of User_Property and add it to my settings.py in this way I can access to the instance in all my templates even if I don't pass it as context in the views.
context_processors.py
from App_name.models import User_Property
from django.contrib.auth.models import User
def access_prop(request):
user = request.user.id #add the .id to no have problems with the AnonymousUser in my logg-in page
user_property = User_Property.objects.filter(us=user).values_list('prop', flat=True) #this stores the list of all the properties for the logg-in user
return {
'user_property': user_property,
}
settings.py
from django.conf.global_settings import TEMPLATE_CONTEXT_PROCESSORS
TEMPLATE_CONTEXT_PROCESSORS += ('App_name.context_processors.access_prop',)
Then in the template check if the user have a especific property
template.html
{% if 'property name' in user_property %}
Show something
{% else %}
This is not for you
{% endif %}
To can check in especific for the name instead of the id just add to_field='name' in my prop field in the model User_Property like this: prop = models.ForeignKey(Property, related_name='up_prop', to_field='name').

From the docs
You should use the related_name that you set in the ForeignKey and the built-in methods of the relationships:
try this:
user.up_us.filter(prop__name="the name")
EDIT
for using the .filter(prop__name="the name") method you have to do it in a .py file.

Give this a try: {% if user.user_property.prop.id == 1 %}

You've set related_name in us = models.ForeignKey(User, related_name='up_us'), so you need to use it
{% if user.up_us.prop.name == 'the name of the property' %}
Show something
{% endif %}
This answer has a good explanation of how to use and what related_name for.
And try to exclude to much logic from templates.

Related

Use is_authenticated using OneToOneField relation with User

I have built a model which have a OneToOne relation with the User object in Django like this :
class Student(models.Model):
user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
But in the HTML file, the filter {% if user.student.is_authenticated %} does not work but the filter {% if user.is_authenticated %} works. I thought that the Student class inherits the attributes from the User class.
Is there an other possibility to create custom users from the User class with the possibility to use {% if user.student.is_authenticated %} ? I want also to have the possibility to use for example {% if user.teacher.is_authenticated %}.
I thought that the Student class inherits the attributes from the User class.
No, it does not inherit, these are just two models (tables) where one of the tables refers to the others by specifying the primary key.
You thus check this with:
{% if user.is_authenticated %}
…
{% endif %}
or if you want to know whether the user of a student is authenticated, you can work with:
{% if mystudent.user.is_authenticated %}
…
{% endif %}

Creating Forms dynamically from a model

I'm learning Django as I go right now, but I'm trying to do something more dynamically.
Basically I've got multiple models defined as so:
class Group(models.Model):
name = models.CharField(max_length=255)
type = models.CharField(max_length=255) # Ignore this, is used somewhere else
class User(models.Model):
name = models.CharField(max_length=255)
group = models.ForeignKey(Group, verbose_name='group', on_delete=models.CASCADE)
(there are more models than these two)
I feel like writing a different view for each of these models isn't really a Django way to do it, but I'm struggling to find a different way. Basically I want to automatically create forms depending on what fields the model has.
So on /department/ there should be an text input for name and type.
But on /user/ there should be an text input for name and an selection for group.
All that rather in the same template. If possible ofcourse.
If it isn't possible, what's the best way to do this? Since creating a different template for each model doesn't seem right.
EDIT:
I've now got my CreateView working (very basic still). Now I want to create a ListView in a similar fashion. I've seen this issue, Iterate over model instance field names and values in template but it wasn't able to help me out...
forms.py
class ModelCreate(CreateView):
fields = '__all__'
template_name = 'polls/models/model_create.html'
def get_form(self, form_class=None):
try:
self.model = apps.get_model('polls', self.kwargs['model'])
except LookupError:
raise Http404('%s is not a valid model.' % self.kwargs['model'])
return super(ModelCreate, self).get_form(form_class)
model_create.html
{% extends 'polls/core.html' %}
{% block content %}
<form method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit">
</form>
{% endblock %}
Would it be possible to create a ListView in a similar fashion? So that I get field names and values dynamically (bit like {{ form }})

Django order_with_respect_to reverse foreign_key

I got troubles on CBW with Django 1.8. I use CBW, and if possible I'd like to avoid using views at all. But I'm stuck in a attempt to order the results I have with default queries.
so, more infos and the example : working on django 1.8.3
Got a few models, bands, that can go touring on events, in different venues
myapp/models.py >
from django.db import models
class Band(models.Model):
name = models.CharField(max_length=512)
class Venue(models.Model):
name = models.CharField(max_length=512)
class Meta:
order_with_respect_to = 'VenueEvents'
class Event(models.Model):
datetime = models.DateTimeField()
name = models.CharField(max_length=512)
venue = models.ForeignKey(Venue, trough='VenueEvents')
band = models.ForeignKey(Band)
class Meta:
ordering ['venue', 'datetime']
myapp/view.py >
#Empty
myapp/url.py >
from django.conf.urls import url, patterns
from django.views.generic import DetailView
from myapp.models import Band
urlpatterns = patterns('',
url(r'^bands/(?P<pk>[\d]+)$', DetailView.as_view(model=Band), name='venue')
and then the template file directly :
template/myapp/venue_detail.html >
<html><body><ul><li>
{{ band.name }}
{% for event in band.event_set.all %}
{% ifchanged event.venue %}
{% if not forloop.first %}
</li><li>
{% endif %}
{{ event.datetime }}
{% endif %}
{{ event.name }}
{% endfor %}
</li></ul></body></html>
I want on that page to have all the venues a band toured at listed, and I want them ordered by event_set.datetime. Meaning the first Venue listed is the one where they last played at.
I tryied a few different things, all not working :
adding through parameters to the ForeignKey. did not work
trying to stick the logic in the template. did not work (and who would do that ? )
having in Venue : ordering ['event_set']
So, I'd really like to have a solution with no view.py, but only if it is possible. So, what would be the best idea to solve this ?
Maybe is there a simple way to add a new table to help me order those things ?
Maybe can i add a method on my class Venue that would accept a band as argument and would be the thing i can order at, except django doesn't allow to order thing by a method.
Maybe I have to override the objects manager to add this possibility, but is there an easy way to do this ?
Or is just the only solution to skip views-less CBW ?
Or is there any other solution ?
Seems like you are using order_with_respect_to wrong.
You should probably order_with_respect_to = 'venue' on Event instead.
Have a look at https://docs.djangoproject.com/en/1.8/ref/models/options/#order-with-respect-to to see how it works.

Getting and displaying related objects in Django

I know this is simple, but I can't get my head around how to join some models together to display in my template in Django. I have "groups" that can have several "contacts".
So far I've got:
class Group(models.Model):
group_name = models.CharField()
class Contact(models.Model):
contact_name = models.ForeignKey(Group)
In my view, at first I assumed that simply getting my groups would also get any attached contacts, however that doesn't appear to be happening as expected:
def get_queryset(self):
groups = Group.objects.all()
return groups
I was expecting to do something like this in my template:
{% for group in groups %}
<h2>{{ group.group_name }}</h2>
{% for c in group.contact %}
<h3>{{ c.contact_name }}</h3>
{% endfor %}
{% endfor %}
This isn't working - what am I doing wrong? What is the correct query in my view to make sure the contact(s) for each group is getting retrieved?
Well, it looks like you've got some of your code from a different place so just so you can fully understand, you can do this in 2 different ways:
1) To access a related object of any kind, being a simple ForeignKey or ManyToMany you just need to go from the opposite model and use _set like this example:
class Group(models.Model):
group_name = models.CharField()
class Contact(models.Model):
contact_name = models.ForeignKey(Group)
{{ group.contact_set.all }}
2) You can set up a name different than the default _set changing Contact like this:
class Contact(models.Model):
contact_name = models.ForeignKey(Group, related_name='contacts')
So, related_name kwarg set a new name for you instead of the _set one:
{{ group.contacts.all }}
I hope I manage to make it clearer about simple access on models related objects.

Querying Many to many fields in django template

This may not be relevant but just wanted to ask,
IF an object is passed from views to template and in the template will i be able to query many to many fields
Models code:
class Info(models.Model):
xls_answer = models.TextField(null=True,blank=True)
class Upload(models.Model):
access = models.IntegerField()
info = models.ManyToManyField(Info)
time = models.CharField(max_length=8, null=True,blank=True)
error_flag = models.IntegerField()
def __unicode__(self):
return self.access
Views:
// obj_Arr contains all the objects of upload
for objs in obj_Arr:
logging.debug(objs.access)
logging.debug(objs.time)
return render_to_response('upload/new_index.html', {'obj_arr': obj_Arr , 'load_flag' : 2})
In template is it possible to decode the many to many field since we are passing the object
Thanks..
In general, you can follow anything that's an attribute or a method call with no arguments through pathing in the django template system.
For the view code above, something like
{% for objs in obj_arr %}
{% for answer in objs.answers.all %}
{{ answer.someattribute }}
{% endfor %}
{% endfor %}
should do what you're expecting.
(I couldn't quite make out the specifics from your code sample, but hopefully this will illuminate what you can get into through the templates)
It's also possible to register a filter like this:
models.py
class Profile(models.Model):
options=models.ManyToManyField('Option', editable=False)
extra_tags.py
#register.filter
def does_profile_have_option(profile, option_id):
"""Returns non zero value if a profile has the option.
Usage::
{% if user.profile|does_profile_have_option:option.id %}
...
{% endif %}
"""
return profile.options.filter(id=option_id).count()
More info on filters can be found here https://docs.djangoproject.com/en/dev/howto/custom-template-tags/

Categories

Resources