0

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').

M. Gar
  • 889
  • 4
  • 16
  • 33
  • It's hard to follow. Do you have `OneToOneField` relationship or not? What do you pass to the context as `user`? – vishes_shell Mar 02 '16 at 08:23
  • The `OneToOneField` relationship are between `User` and `Profile` models and the `user` is an instance of the `User` model from the the currently logged-in user https://docs.djangoproject.com/en/1.8/topics/auth/default/#users – M. Gar Mar 02 '16 at 16:01
  • 1
    And piece of advice, it's better not to name your class `Property`, it is reserved name(in lowercase). – vishes_shell Mar 02 '16 at 19:41
  • @vishes_shell Don't worry that's just the name I use in this example not the real name I use for my class. – M. Gar Mar 02 '16 at 19:50

3 Answers3

1

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

Gocht
  • 9,924
  • 3
  • 42
  • 81
  • @M.Gar Try printin `{{user.user_property}}` I think this has no value. – Gocht Mar 01 '16 at 20:21
  • 1
    @M.Gar You need to use `up_us` because this is a reverse relationship. – Gocht Mar 01 '16 at 22:02
  • ok using the `{{user.up_us}}` shows me `App.User_Property.None` that's I think that indicates that now have ccess to that model. – M. Gar Mar 01 '16 at 22:36
  • 1
    @M.Gar Yes, but keep in mind that could be many `User_Property` objects pointing to the same `User` object, so when you call `user.up_us` it will give you a set not an object, you can test this in your view using `request.user.up_us.all()` – Gocht Mar 01 '16 at 22:38
  • but how can I use that to create the condition that I need? – M. Gar Mar 02 '16 at 00:00
  • 1
    @M.Gar You can choose the `User_Property` in your view and send it to the view: `request.user.up_us.get(pk=1)` this will give the `User_Property` object with `id=1`, add it to your context and use it in your template. – Gocht Mar 02 '16 at 02:43
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.

Community
  • 1
  • 1
vishes_shell
  • 22,409
  • 6
  • 71
  • 81
  • Tried with the `related_name` but nothing – M. Gar Mar 01 '16 at 22:23
  • @M.Gar can you try to `print(request.user.up_us.prop.name)` in your _view_. Because i think there is no way that this can work in other way. Be sure that your user is authenticated and there is `User_Property` which related to current user and have desired `prop` with needed `name`. – vishes_shell Mar 02 '16 at 19:34
1

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.

arcegk
  • 1,480
  • 12
  • 15
  • Gives me `TemplateSyntaxError Could not parse the remainder: '(prop__name="the name")' from 'user.up_us.filter(prop__name="the name")'` – M. Gar Mar 01 '16 at 23:26
  • Do it in the views.py and pass it in the context. – arcegk Mar 02 '16 at 00:00
  • Can I do that if the elements wich I apply the condition are from my base.html template and don't use a view to pass context? – M. Gar Mar 02 '16 at 00:08
  • 1
    Sure, take a view to context processors in django -> [docs](https://docs.djangoproject.com/en/1.9/ref/templates/api/#writing-your-own-context-processors) – arcegk Mar 02 '16 at 03:22
  • Thanks @arcegk, just created my own context_processor to have access to the instance of `User_Property` in my base.html – M. Gar Mar 04 '16 at 17:13