1

To keep my project cleaner I decided (maybe wrongly) to split my one Django app into two. One app for the management of information, the other for display. And for this I thought using Django Proxy Models in the display App would be the best way. However, I've come across a problem with the ForeignKey fields within certain models and forcing those foreign keys to use a proxy-model, instead of its originating model.

Here's some examples to make it clearer:

App_1-model.py

class Recipe(models.Model):
    name = models.CharField(max_length=200)
    slug = models.SlugField()
    ...

class Ingredient(models.Model):
    name = models.CharField(max_length=200)
    recipe = models.ForeignKey(Recipe)
    weight = models.IntegerField()

App_2-model.py (Imports App_1 models)

class RecipeDisplayProxy(Recipe):

    class Meta:
        proxy = True

    @property
    def total_weight(self):
        # routine to calculate total weight
        return '100g'


class IngredientDisplayProxy(Ingredient):

    class Meta:
        proxy = True

    @property
    def weight_lbs(self):
        # routine to convert the original weight (grams) to lbs 
        return '2lb'

App_2.views.py

def display_recipe(request, slug):
    recipe = get_object_or_404(RecipeDisplayProxy, slug=slug)

    return render(
        request,
        'display_recipe/recipe.html',
        {'recipe': recipe}
        )

App_2-template.html

<h2 class="display-4">{{ recipe.name }}</h2>
<p>{{ recipe.total_weight }}</p> <!-- This works fine, as expected //-->

<ul>
{% for recipe_ingredient in recipe.ingredient_set.all %}
<li>{{recipe_ingredient.ingredient}} &ndash;

{{recipe_ingredient.weight_lbs}}</li>

<!-- 
The above line doesn't return anything as the 'Ingredient' model, not the "IngredientDisplayProxy' is being returned. (As expected) 
-->

{% endfor %}
</ul>

What's happening here is that I'm successfully returning the RecipeDisplayProxy model as specified in the view, but when I access ingredient_set it returns the Ingredient model, rather than the IngredientDisplayProxy (as expected).

So how do I force ingredient_set to return IngredientDisplayProxy models instead?

I tried implementing the code found here: Django proxy model and ForeignKey

But had no luck. I then started digging into the init() method for RecipeDisplayProxy - to see if I could overwrite the models used in the ingredient_set, but couldn't find anything that would give me the right response.

So any ideas?

Or, am I just taking this down a bad path - and should be considering a different design altogether?

lalithkumar
  • 3,480
  • 4
  • 24
  • 40
SumYungGuy
  • 13
  • 2
  • Try declaring a property that wraps ingredient_set access by setting the queryset's model to the proxy model as shown in the last example of the accepted answer here: https://stackoverflow.com/questions/3891880/django-proxy-model-and-foreignkey#answer-6988506 – fips May 31 '17 at 05:07

2 Answers2

0

From the view you are returning the recipe instance, but in the template you are accessing the ingredient through the recipe, but it should be the other way round, from ingredient you can access the recipe.Now for the proxy model, better read this documentation

AR7
  • 366
  • 1
  • 16
0

Looks like I Was doing some things wrong, and so on the advice of fips I went back and did the following:

class RecipeDisplayProxy(Recipe):

    class Meta:
        proxy = True

    @property
    def total_weight(self):
        # routine to calculate total weight
        return '100g'

    @property
    def ingredient_set(self):
        qs = super(RecipeDisplayProxy, self).ingredient_set
        qs.model = IngredientDisplayProxy
        return qs

It was that simple :'( so thank you for the help and suggestions.

SumYungGuy
  • 13
  • 2