Re: Absolute beginner question -- recipes
On Mon, Feb 29, 2016 at 4:51 AM, Simon Gunacker wrote: > @Mike: the attempts (at least the ones I have seen) to store hierarchical > data in relations [1] don't seem very intuitive to me. At least when it > comes to query the data. Anyway: I would appreciate to be convinced by > something else. However, I am afraid to kick off a completely different > (yet interesting) discussion here. My current issue is how to access the > additional fields of my M2M relationship. In addition to that I will think > about hierarchical data in relational databases ;-) > > For Django-specific guidance, have a look at Django-treebeard, which has support for multiple hierarchical list strategies and a common API between each of the strategies. https://github.com/tabo/django-treebeard Django-mptt (Modified Preorder Tree Traversal) also has some good resources: https://github.com/django-mptt/django-mptt There's also a host of other packages to manage trees of data: https://www.djangopackages.com/grids/g/trees-and-graphs/ -James -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To post to this group, send email to django-users@googlegroups.com. Visit this group at https://groups.google.com/group/django-users. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/CA%2Be%2BciWQvWXcHa5C3RTEG95SdDhkLkKCTVUrWYsNv7-fZR6S7g%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.
Re: Absolute beginner question -- recipes
On 7/03/2016 2:17 AM, Mike Dewhirst wrote: On Thursday, March 3, 2016 at 3:22:04 AM UTC+11, Simon Gunacker wrote: Inspired by Mike Dewhirsts suggestion on building hierachical structures, Not sure we are on the same page regarding "hierarchical". In the early days hierarchical databases only had 1:n relationships IOW foreign keys only. That is a very limiting thing. You have to turn your thinking inside out to successfully represent the real world. That's what I meant. OTOH, RDBMS gives you everything you need to represent the real world.  I've made up another model: | classPart(models.Model):   parts =models.ForeignKey('Part',null=True,blank=True,default=None,related_name='pieces')   name =models.CharField(max_length=200) | For this to work in Django the table name should probably be 'self' rather than 'Part'. Haven't checked the docs on this recently. Your 'parts' FK lets any Part be connected to exactly one or (null=True) no other part. Is that what your real world is? If so, why did you use plural nouns as the fieldname and related_name identifiers? Choosing meaningful names is very helpful when you revisit your code in future. If your real world scenario is the "bill of materials" I mentioned earlier, you really need a many-to-many relationship between parts. That means any part could be in a number of different parts (ie assemblies) and assemblies themselves could actually be sub-assemblies in a finished product - which amounts to an assembly of sub-assemblies. If so, we might be getting close to your original recipes project. Consider that what we need behind the scenes to represent a many-to-many relationship is a bunch of records in a "through" table (let's call it "Parts" plural) and all it needs is two FKs. On rereading this, I should have said that for all the records (rows) in the "bunch" the fk1 always points to the same primary key in the Part table while every fk2 points to a different PK in the Part table. Lets say fk1 points to the precise row in the Part table which happens to be an assembly or sub-assembly. fk1 in the through table would never point to a stand-alone part. Then fk2 would point to another row in the Part table. That other row is a part as well. It could represent a sub-assembly or a stand-alone part but never a complete assembly. And further, I neglected to mention that Django manages all this for you when you put ... class Part(models.Model): parts = ManyToManyField(null=True, blank=True, related_name=pieces") ... and working with this requires a few round-trips to the docs. Mike So when you want to know what all the parts are for an assembly you need a view which understands your business logic and can run the appropriate query to retrieve the results you want into a queryset, list or whatever. Assuming the result you want is a list of an assembly's parts, you would first identify the assembly in the Part table then query the "through" table (Parts) for all the rows with fk1==Part  ||  Then I made my view: | classPartsView(generic.ListView):   context_object_name='parts'   model=Part | I have never tried generic views. My typical approach is to create an arbitrary object (eg class Assembly(object)) and use its __init__() method to instantiate an assembly object with the queryset, list or whatever generated by the code in the view. In the hypothetical example I'm conjuring up here we would pass in Part.name as assembly.name and the queryset as assembly.qs (or similar identifiers).  But how should I design my template now? | Parts {% for part in parts %}  {% endfor %} | Parts {{ assembly.name }} {% if assembly.qs %} |{% for item in assembly.qs %}| {{ item.fk2.name }} {% endfor %} {% else %} No parts {% endif %} (each item represents a row in the through table Parts with fk2 being the sub-assembly or part)  That is all fine and dandy but what if you wanted more information about the particular spot the part needed to be placed or the way it should be aligned in the assembly? That information doesn't belong in the Parts table for the part concerned because it might be in many assemblies. Likewise it doesn't belong in the Parts table for the assembly concerned because there could be heaps and heaps of parts involved. It actually belongs in the "through" table Parts (plural). A single row in that table uniquely defines the relationship between assembly and part. If we add extra fields in the Parts "through" table those fields can carry whatever extra info is required. Note that the queryset performed in the view retrieved records from the Parts table. That means if each row contains extra info you can simply show it in your template as follows ... |{% for item in assembly.qs %}| {{ item.fk2.name }} Alignment {{ item.fk2.alignment }} {% endfor %} Hope this helps Mike  I already found different answ
Re: Absolute beginner question -- recipes
On Thursday, March 3, 2016 at 3:22:04 AM UTC+11, Simon Gunacker wrote: > > Inspired by Mike Dewhirsts suggestion on building hierachical structures, > Not sure we are on the same page regarding "hierarchical". In the early days hierarchical databases only had 1:n relationships IOW foreign keys only. That is a very limiting thing. You have to turn your thinking inside out to successfully represent the real world. That's what I meant. OTOH, RDBMS gives you everything you need to represent the real world. > I've made up another model: > class Part(models.Model): > parts = models.ForeignKey('Part', null=True, blank=True, default=None, > related_name='pieces') > name = models.CharField(max_length=200) > > For this to work in Django the table name should probably be 'self' rather than 'Part'. Haven't checked the docs on this recently. Your 'parts' FK lets any Part be connected to exactly one or (null=True) no other part. Is that what your real world is? If so, why did you use plural nouns as the fieldname and related_name identifiers? Choosing meaningful names is very helpful when you revisit your code in future. If your real world scenario is the "bill of materials" I mentioned earlier, you really need a many-to-many relationship between parts. That means any part could be in a number of different parts (ie assemblies) and assemblies themselves could actually be sub-assemblies in a finished product - which amounts to an assembly of sub-assemblies. If so, we might be getting close to your original recipes project. Consider that what we need behind the scenes to represent a many-to-many relationship is a bunch of records in a "through" table (let's call it "Parts" plural) and all it needs is two FKs. Lets say fk1 points to the precise row in the Part table which happens to be an assembly or sub-assembly. fk1 in the through table would never point to a stand-alone part. Then fk2 would point to another row in the Part table. That other row is a part as well. It could represent a sub-assembly or a stand-alone part but never a complete assembly. So when you want to know what all the parts are for an assembly you need a view which understands your business logic and can run the appropriate query to retrieve the results you want into a queryset, list or whatever. Assuming the result you want is a list of an assembly's parts, you would first identify the assembly in the Part table then query the "through" table (Parts) for all the rows with fk1==Part > Then I made my view: > class PartsView(generic.ListView): > context_object_name='parts' > model=Part > > I have never tried generic views. My typical approach is to create an arbitrary object (eg class Assembly(object)) and use its __init__() method to instantiate an assembly object with the queryset, list or whatever generated by the code in the view. In the hypothetical example I'm conjuring up here we would pass in Part.name as assembly.name and the queryset as assembly.qs (or similar identifiers). > But how should I design my template now? > Parts > > > {% for part in parts %} > > {% endfor %} > > > Parts {{ assembly.name }} {% if assembly.qs %} {% for item in assembly.qs %} {{ item.fk2.name }} {% endfor %} {% else %} No parts {% endif %} (each item represents a row in the through table Parts with fk2 being the sub-assembly or part) That is all fine and dandy but what if you wanted more information about the particular spot the part needed to be placed or the way it should be aligned in the assembly? That information doesn't belong in the Parts table for the part concerned because it might be in many assemblies. Likewise it doesn't belong in the Parts table for the assembly concerned because there could be heaps and heaps of parts involved. It actually belongs in the "through" table Parts (plural). A single row in that table uniquely defines the relationship between assembly and part. If we add extra fields in the Parts "through" table those fields can carry whatever extra info is required. Note that the queryset performed in the view retrieved records from the Parts table. That means if each row contains extra info you can simply show it in your template as follows ... {% for item in assembly.qs %} {{ item.fk2.name }} Alignment {{ item.fk2.alignment }} {% endfor %} Hope this helps Mike I already found different answers on the net reaching from 'impossible' to > 'with-tag' or 'install some add-ons'. According to Mikes former suggestion, > I expected something easy and elegant here ... > > regards, Simon > > > -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To post to this group, send email to django-users@googlegroups.com. Visit this group at https://groups.google.com/group/django-users
Re: Absolute beginner question -- recipes
Inspired by Mike Dewhirsts suggestion on building hierachical structures, I've made up another model: class Part(models.Model): parts = models.ForeignKey('Part', null=True, blank=True, default=None, related_name='pieces') name = models.CharField(max_length=200) Then I made my view: class PartsView(generic.ListView): context_object_name='parts' model=Part But how should I design my template now? Parts {% for part in parts %} {% endfor %} I already found different answers on the net reaching from 'impossible' to 'with-tag' or 'install some add-ons'. According to Mikes former suggestion, I expected something easy and elegant here ... regards, Simon -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To post to this group, send email to django-users@googlegroups.com. Visit this group at https://groups.google.com/group/django-users. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/abcfeada-4bd6-496f-a3f8-4678b08d8440%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Absolute beginner question -- recipes
Thank you James. Taking your suggestion, I solved it! -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To post to this group, send email to django-users@googlegroups.com. Visit this group at https://groups.google.com/group/django-users. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/7c7494ec-8ee5-4d14-bfae-a52297696e59%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Absolute beginner question -- recipes
On Mon, Feb 29, 2016 at 5:57 AM, Simon Gunacker wrote: > Thank you Florian. After James pointed out that I can access my steps (and > the ingredients in some way) by just passing the recipe object to the > templates context, I thought of reducing the view to a DetailView again. > But I have to somehow access the ingredients from my template for now ... > The related models using a 'through' table also have access to the 'through' table itself. With your current setup, I think you can do this: {% for steping in step.stepingredient_set.all %} {{ steping.amount }} {{ steping.unit }} - {{ steping.ingredient }} {% empty %} No ingredients needed for this step. {% endfor %} Optionally, for style points (and better human readability of the code), you can also add a 'related_name' parameter to the FK's in the 'through' table: step = models.ForeignKey(Step, null=True, related_name='step_ingredients') ingredient = models.ForeignKey(Ingredient, null=True, related_name='ingredient_steps') That way, depending on the direction you are going, the call makes sense to a human: {% for steping in step.step_ingredients.all %} {{ steping.amount }} {{ steping.unit }} - {{ steping.ingredient }} {% empty %} No ingredients needed for this step. {% endfor %} I think that will work, although I haven't exactly tested this. I'd highly recommend going with DetailView if you can. That makes your view a whopping 2 or 3 lines. -James -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To post to this group, send email to django-users@googlegroups.com. Visit this group at https://groups.google.com/group/django-users. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/CA%2Be%2BciWYj42TNJ4KeF4vFS6_wi0cghdCee%2Bu-_QJ0VP2uzyg-Q%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.
Re: Absolute beginner question -- recipes
Thank you Florian. After James pointed out that I can access my steps (and the ingredients in some way) by just passing the recipe object to the templates context, I thought of reducing the view to a DetailView again. But I have to somehow access the ingredients from my template for now ... -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To post to this group, send email to django-users@googlegroups.com. Visit this group at https://groups.google.com/group/django-users. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/b0c1408e-92bf-41a6-887a-8b5d03bd51f7%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Absolute beginner question -- recipes
On 28/02/16 20:14, Simon Gunacker wrote: > | > def detail(request, pk): > recipe = Recipe.objects.get(id=pk) > recipe['steps'] = Steps.objects.filter(recipe_id=pk) > template = loader.get_template('recipe/recipe_detail.html') > context = { > 'recipe': recipe, > } > return HttpResponse(template.render(context,request)) > | OT: Have a look at the render shortcut: https://docs.djangoproject.com/en/1.9/topics/http/shortcuts/#render | return render(request, 'recipe/recipe_detail.html', context) Maybe you can simply use a generic DetailView: https://docs.djangoproject.com/es/1.9/ref/class-based-views/generic-display/#detailview -- Florian -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To post to this group, send email to django-users@googlegroups.com. Visit this group at https://groups.google.com/group/django-users. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/56D44106.1070704%40ist-total.org. For more options, visit https://groups.google.com/d/optout.
Re: Absolute beginner question -- recipes
@Mike: the attempts (at least the ones I have seen) to store hierarchical data in relations [1] don't seem very intuitive to me. At least when it comes to query the data. Anyway: I would appreciate to be convinced by something else. However, I am afraid to kick off a completely different (yet interesting) discussion here. My current issue is how to access the additional fields of my M2M relationship. In addition to that I will think about hierarchical data in relational databases ;-) Thanks, Simon -- http://www.slideshare.net/billkarwin/models-for-hierarchical-data -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To post to this group, send email to django-users@googlegroups.com. Visit this group at https://groups.google.com/group/django-users. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/ee0101a5-1949-462a-8fd1-d50674cfdd89%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Absolute beginner question -- recipes
On 29/02/2016 8:54 PM, Simon Gunacker wrote: Well, as far as I know hierarchical relationships are hard to model in relational databases; Definitely incorrect. Hierarchical is merely a subset of relational. Relational can handle hierarchical 1:n:m very easily plus n:1, n:m as well. Relational databases are the most widely used today because they can solve most real world modelling. On that topic you should try to ignore database design initially and instead try to understand the real world relationships between your data types. Only then should you model the solution you need to provide. I would be surprised if you couldn't solve most real world design problems with 1:1, 1:n, n:1 and n:m relationships. The closer your schema is to the real world, the easier it will be to represent it in a relational (ie Django ORM) database. I believe best practice is to ignore shortcuts aimed at performance initially and make your design perfectly represent the real world. Only when it displays performance problems not fixable with caching should you try and introduce corner cutting in your design. Mike -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To post to this group, send email to django-users@googlegroups.com. Visit this group at https://groups.google.com/group/django-users. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/56D432D6.9030005%40dewhirst.com.au. For more options, visit https://groups.google.com/d/optout.
Re: Absolute beginner question -- recipes
Ok ... but how can I access the additional information stored in StepIngredient then? And - to ask more general - is there a way to find all the "nested objects" attached to my current objects? Something to enter in the shell to see __all__ attributes; not just _meta.fields? -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To post to this group, send email to django-users@googlegroups.com. Visit this group at https://groups.google.com/group/django-users. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/f3863003-fb81-4765-9a56-f0d221bb5a62%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Absolute beginner question -- recipes
> Thank you James for pointing me at how to do my queries with django; I can finally list my steps using: > > {% for step in recipe.steps.all %} > > within my template. However, given the model above I am still not sure how to access a single steps ingredients ... any ideas or suggestions on my current model? Sure, just have another nested {% for ingredient in step.ingredients.all %} You should also change the 'ingredient' field to 'ingredients' in your Step model (reflected in my loop above). Makes it easier to read and indicate that you'll need the .all in the template (or elsewhere) if the attribute name is plural. Otherwise you are querying using step.ingredient, and expecting a list of multiple ingredients back. -James -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To post to this group, send email to django-users@googlegroups.com. Visit this group at https://groups.google.com/group/django-users. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/CA%2Be%2BciXjKnTgCpJcCT8hxP2gRgLOqA6DygkqT0WZr5Nqm8vQUQ%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.
Re: Absolute beginner question -- recipes
Hey everybody, thank you very much for your answers. I think I have already learned a lot from you! Well - there is quite a difference between stepping through a tutorial and trying to do something on my own. Regarding Mikes question whether a step of a recipe should be a sub-recipe. Well, as far as I know hierarchical relationships are hard to model in relational databases; that's why I kept my hands off! My decision to create a recipe app has a simple reason: I read some comparisons between django and ruby on rails and I decided to go for django since it seems to leave more freedom. I found a RoR tutorial on creating a recipe app some time ago and I am trying to do the same thing in django now. Concerning my model - this is how it looks like: from __future__ import unicode_literals from django.db import models class Unit(models.Model): abbreveation = models.CharField(max_length=5, primary_key=True) description = models.CharField(max_length=50) def __str__(self): return "%s (%s)" % (self.description, self.abbreveation) class Ingredient(models.Model): name = models.CharField(max_length=255) def __str__(self): return self.name class Step(models.Model): name = models.CharField(max_length=255, blank=True) recipe = models.ForeignKey('Recipe', related_name='steps', on_delete= models.CASCADE, null=True) description = models.TextField() ingredient = models.ManyToManyField(Ingredient, through='StepIngredient' ) def __str__(self): if (self.name == ''): return "Step %d" % self.id else: return "Step %d (%s)" % (self.id, self.name) # additional information for many to many relationship between schritt and zutat class StepIngredient(models.Model): class Meta: unique_together = (('step', 'ingredient'),) step = models.ForeignKey(Step, null=True) ingredient = models.ForeignKey(Ingredient, null=True) amount = models.DecimalField(max_digits=7, decimal_places=3) unit = models.ForeignKey(Unit, null=True) def __str__(self): return "%d %s %s" % (self.amount, self.unit.abbreveation, self. ingredient) class Recipe(models.Model): name = models.CharField(max_length=255) # file will be uploaded to MEDIA_ROOT/images # TODO: Upload works but link fails. Maybe sth. wrong with MEDIA_URL??? photo = models.ImageField(upload_to='images/', null=True) portionen = models.IntegerField(default=2) def __str__(self): return self.name Thank you James for pointing me at how to do my queries with django; I can finally list my steps using: {% for step in recipe.steps.all %} within my template. However, given the model above I am still not sure how to access a single steps ingredients ... any ideas or suggestions on my current model? Thanks, Simon -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To post to this group, send email to django-users@googlegroups.com. Visit this group at https://groups.google.com/group/django-users. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/cef5e940-6947-4fe2-b20b-1c805ea09572%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Absolute beginner question -- recipes
On Sun, Feb 28, 2016 at 11:45 PM, Rahul Gandhi wrote: > I might be wrong here, but this is what I understand: > > Let's say you have something like this: > > > class Recipe(models.Model): > name = models.CharField(max_length=255) > description = models.TextField() > > > class Step(models.Model): > step_number = models.IntegerField() > description = models.TextField() > recipe = models.ForeignKey(Recipe) > > > now, if I do the following in the shell: > > recipe = Recipe.objects.get(id=1) > recipe.steps > > wouldn't this give an error? > > To get the step, I could do something like > recipe.step_set > > but I don't think I'll be able to do recipe.steps > > Given that model, you're right, sorry about that. My brain was moving faster than my fingers. All of my mentions of recipe.steps were meant as a reference to recipe.step_set. In my head I had already set the related_name to 'steps', like so: recipe = models.ForeignKey(Recipe, related_name='steps') This way you can use recipe.steps rather than recipe.step_set. Both are equivalent, but the custom related_name is easier to track for a human. The relation does act like its own manager though, so you would actually have to say recipe.steps.all() to get all of the steps (since a separate query is used to pull all of the steps). The template code would also have to be adjusted to include the .all (no parenthesis there). Also be sure to determine whether or not you should use prefetch_related for your list views ( https://docs.djangoproject.com/en/1.9/ref/models/querysets/#prefetch-related ). However, this model does match what I assumed you had. I'm also assuming that you have a M2M relationship with Ingredient with a custom 'through' table so that you can match steps with ingredients and store other things like measurements on that relation? I would make a suggestion, though. Instead of using a 'step_number', you should look at using django-ordered-model instead. It does a very good job of keeping things, well, ordered. It also has other functionality like performing a renumber automatically if you decide that step 2 should actually be step 18 (and renumbers all of the other steps appropriately). The 'order' that is uses is zero-based, but you can add a simple property step_number that returns self.order + 1 (and sets the order correctly if you are renumbering by step). You'll also need to implement their 'order_with_respect_to', probably point it at the recipe field. https://github.com/bfirsh/django-ordered-model -James -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To post to this group, send email to django-users@googlegroups.com. Visit this group at https://groups.google.com/group/django-users. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/CA%2Be%2BciUw-Yqv3cK-M_n%2B%2BqutU8BDzbbYGhqJYxS3M%3DmX%2BqKYwA%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.
Re: Absolute beginner question -- recipes
I might be wrong here, but this is what I understand: Let's say you have something like this: class Recipe(models.Model): name = models.CharField(max_length=255) description = models.TextField() class Step(models.Model): step_number = models.IntegerField() description = models.TextField() recipe = models.ForeignKey(Recipe) now, if I do the following in the shell: recipe = Recipe.objects.get(id=1) recipe.steps wouldn't this give an error? To get the step, I could do something like recipe.step_set but I don't think I'll be able to do recipe.steps On Monday, February 29, 2016 at 8:08:35 AM UTC+5:30, James Schneider wrote: > > > > On Sun, Feb 28, 2016 at 11:14 AM, Simon Gunacker > wrote: > >> Dear Django Community, >> >> as a first django project I tried to write a site to manage cooking >> recipes. My model is quite simple: >> >> * 1 recipe has n steps >> * 1 step has a description and n ingredients, each of a certain amount >> defined by a certain unit >> >> all in all, I have 5 tables (Recipe, Step, Ingredient, Unit, >> StepIngredient). >> >> After reading through some documentation and trying around a little bit, >> I got my model and my admin site (I had to install django-nested-inline for >> the admin site to fit my expectations). >> >> Now I am struggeling with my views. There is a simple index view wich >> basically lists all recipes: >> >> class IndexView(generic.ListView): >> context_object_name = 'recipes_list' >> >> def get_queryset(self): >> return Recipe.objects.all() >> >> > You can actually get rid of the get_queryset() override entirely here by > properly setting the default view model to Recipe. > > > >> The hard part is setting up the details view. It is supposed to show the >> recipes name as a title and then list all the required ingredients and all >> the required steps. It tried something like: >> >> def detail(request, pk): >> recipe = Recipe.objects.get(id=pk) >> recipe['steps'] = Steps.objects.filter(recipe_id=pk) >> template = loader.get_template('recipe/recipe_detail.html') >> context = { >> 'recipe': recipe, >> } >> return HttpResponse(template.render(context, request)) >> >> but it seems I am not allowed to modify the recipes object. Any ideas how >> to pass all the data which belongs to recipe to the template? >> >> > Whoa...why are you manually setting recipe['steps']? Isn't there already a > relationship between Recipe (the model) and Step (Step should have a FK > back to Recipe)? You should not need an explicit second call to > Step.objects. If that call is necessary, then I would be highly suspicious > that your models are not defined properly (sanely). > > I would remove that second line where you set recipe['steps'] entirely. If > that breaks something, your models are probably incorrect. > > Assuming you run just the first line (recipe = Recipe.objects.get(id=pk)), > you should be able to do the following in the Django shell: > > recipe.steps # return a list of all of the steps associated with that > recipe > > recipe.steps[2].ingredients # return a list of ingredients for what is > presumably step 3 of the recipe > > There shouldn't be any need for manually querying for the steps or their > ingredients after the original Recipe.objects.get() call. > > -James > > > -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To post to this group, send email to django-users@googlegroups.com. Visit this group at https://groups.google.com/group/django-users. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/3e8828f2-a104-4855-a728-58c9b8362347%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Absolute beginner question -- recipes
On 29/02/2016 2:09 PM, James Schneider wrote: Again, I'm making some assumptions about your models. If the above code snippets don't work (aside from typos), please post up your models.py file(s) so that we can adjust accordingly. I think James is right. Maybe the answer to the above question is in your subject line. If I was doing a recipe app I would need to scratch my head. For example, do I permit an ingredient to also be a recipe? In other words, are ingredients simply raw materials or can they be separate concoctions. I'm no chef but I suspect recipes include separately prepared components which are brought together during the cooking process or at the latest just before serving. Maybe your "step" is a sub-recipe. So the real question is about your expertise. If you are a chef all you need here is how to do many-to-many relationships. There must be heaps of manufacturer apps out there. They generally go under the label of "bill-of-materials". It seems to me quite similar to recipes. Anyway ... I'm building a much simpler ingredients system with substances and mixtures where a mixture is a substance having relationships with other substances. Here is my setup: class Substance(models.Model): ingredients = models.ManyToManyField('self', symmetrical=False, blank=True, through='Substance_Ingredients') ... class Substance_Ingredients(models.Model): substance = models.ForeignKey('Substance', null=True, blank=True, related_name='base_substance') ingredient = models.ForeignKey('Substance', null=True, blank=True,) proportion = models.DecimalField(null=True, blank=True) ... Hope this helps Mike -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To post to this group, send email to django-users@googlegroups.com. Visit this group at https://groups.google.com/group/django-users. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/56D3C15E.5050507%40dewhirst.com.au. For more options, visit https://groups.google.com/d/optout.
Re: Absolute beginner question -- recipes
On Sun, Feb 28, 2016 at 12:23 PM, Simon Gunacker wrote: > Thank you Rahul, > > I actually tried that an this is possible for the relationship between a > recipe and its steps. But when it comes to the ingredients for a single > step, I cannot do this any more since the ingredients depend on steps > again. After reading your suggestion I thought about it once more and I > came up with the following solution: > > def detail(request, pk): > recipe = Recipe.objects.get(id=pk) > steps = Step.objects.filter(recipe_id=pk) > > ingredients = dict() > for step in steps: > ingredients[step.id] = StepIngredients.objects.filter(step_id=step > .id) > > template = loader.get_template('recipe/rezept_detail.html') > context = { > 'recipe': recipe, > 'steps': steps, > 'ingredients': ingredients > } > return HttpResponse(template.render(context, request)) > > Please review how the Django ORM works. You're creating much more work for yourself and your application. 50% of the code in this block can be removed. https://docs.djangoproject.com/en/1.9/intro/tutorial02/#playing-with-the-api https://docs.djangoproject.com/es/1.9/topics/db/queries/ https://docs.djangoproject.com/en/1.9/topics/db/queries/#related-objects def detail(request, pk): recipe = Recipe.objects.get(id=pk) template = loader.get_template('recipe/rezept_detail.html') context = { 'recipe': recipe, } return HttpResponse(template.render(context, request)) I've already mentioned that separate calls to Step.objects are not necessary, because recipe.steps contains the results of such a query already. The same applies to the ingredients for each step. for step in recipe.steps: print('Ingredients: '.format(step.ingredients)) # or for ingredient in step.ingredients: print(ingredient) There is no need to have separate context variables within the template context for each piece of the recipe. All of the information that you are manually extracting is already available in the original object that was requested. The only exception that I would make is if you needed a separate list of all ingredients for all steps in one big list, which is much more difficult to extract. Even then, though, that sore of query is probably better handled by a model manager method that can be accessed via the template. Of course, everything I'm saying is predicated on a decent model design. It could be that your current model structure doesn't allow for taking advantage of the ORM capabilities. If that's the case, though...you may want to review it. > However, when it comes to the view, it does not work any more: > {{ recipe.name }} > > > {% for step in steps %} > > > > {% for ingredient in ingredients.step.id %} > {{ ingredient.amount }} > {% endfor %} > > > {{ step.description }} > > > {% endfor %} > > > According to what I found on google, the django template language cannot > deal with accessing dictionary entries using variables as keys. What is the > django-way of solving this problem? Any ideas? > Yes, the template syntax is limited, intentionally. Assuming that you take my previous advice and utilize the recipe object directly: {{ recipe.name }} {% for step in recipe.steps %} {% for ingredient in step.ingredients %} {{ ingredient.amount }} {% endfor %} {{ step.description }} {% endfor %} I have no idea why you are referring to ingredients.step.id in your template, it doesn't even make sense with the code you have (which is probably why things aren't behaving the way you'd expect). There really shouldn't be a need to ever refer to .id or .pk within a template, unless you are specifically printing out those values for an input field name or using {% url %}. Again, I'm making some assumptions about your models. If the above code snippets don't work (aside from typos), please post up your models.py file(s) so that we can adjust accordingly. -James -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To post to this group, send email to django-users@googlegroups.com. Visit this group at https://groups.google.com/group/django-users. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/CA%2Be%2BciWPFUqwe9VXKTFWBJhQQUuNAEgtMFOjGxpxBtongM2SSg%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.
Re: Absolute beginner question -- recipes
On Sun, Feb 28, 2016 at 11:47 AM, Rahul Gandhi wrote: > You could do something like this: > > def detail(request, pk): > recipe = Recipe.objects.get(id=pk) > steps = Steps.objects.filter(recipe_id=pk) > template = loader.get_template('recipe/recipe_detail.html') > context = { > 'recipe': recipe, > 'steps': steps > } > return HttpResponse(template.render(context, request)) > > And make appropriate changes to your template. > > There's really no point is doing this. Within the template, {{ recipe.steps }} should already contain everything that {{ steps }} would contain in this instance. All you've done is created extra work for the ORM and added complication to the code. Your context should only contain { 'recipe': recipe } at this point. Frankly, I'm not sure if it even needs that if you are using the built-in class-based views such as DetailView. -James -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To post to this group, send email to django-users@googlegroups.com. Visit this group at https://groups.google.com/group/django-users. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/CA%2Be%2BciX0hufY9%2ByfGpM12%3DCzQK7q2AfDTxikJupppoTeXk%2BdiA%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.
Re: Absolute beginner question -- recipes
On Sun, Feb 28, 2016 at 11:14 AM, Simon Gunacker wrote: > Dear Django Community, > > as a first django project I tried to write a site to manage cooking > recipes. My model is quite simple: > > * 1 recipe has n steps > * 1 step has a description and n ingredients, each of a certain amount > defined by a certain unit > > all in all, I have 5 tables (Recipe, Step, Ingredient, Unit, > StepIngredient). > > After reading through some documentation and trying around a little bit, I > got my model and my admin site (I had to install django-nested-inline for > the admin site to fit my expectations). > > Now I am struggeling with my views. There is a simple index view wich > basically lists all recipes: > > class IndexView(generic.ListView): > context_object_name = 'recipes_list' > > def get_queryset(self): > return Recipe.objects.all() > > You can actually get rid of the get_queryset() override entirely here by properly setting the default view model to Recipe. > The hard part is setting up the details view. It is supposed to show the > recipes name as a title and then list all the required ingredients and all > the required steps. It tried something like: > > def detail(request, pk): > recipe = Recipe.objects.get(id=pk) > recipe['steps'] = Steps.objects.filter(recipe_id=pk) > template = loader.get_template('recipe/recipe_detail.html') > context = { > 'recipe': recipe, > } > return HttpResponse(template.render(context, request)) > > but it seems I am not allowed to modify the recipes object. Any ideas how > to pass all the data which belongs to recipe to the template? > > Whoa...why are you manually setting recipe['steps']? Isn't there already a relationship between Recipe (the model) and Step (Step should have a FK back to Recipe)? You should not need an explicit second call to Step.objects. If that call is necessary, then I would be highly suspicious that your models are not defined properly (sanely). I would remove that second line where you set recipe['steps'] entirely. If that breaks something, your models are probably incorrect. Assuming you run just the first line (recipe = Recipe.objects.get(id=pk)), you should be able to do the following in the Django shell: recipe.steps # return a list of all of the steps associated with that recipe recipe.steps[2].ingredients # return a list of ingredients for what is presumably step 3 of the recipe There shouldn't be any need for manually querying for the steps or their ingredients after the original Recipe.objects.get() call. -James -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To post to this group, send email to django-users@googlegroups.com. Visit this group at https://groups.google.com/group/django-users. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/CA%2Be%2BciWUCC3QfHdzCCEE8o9H8i%2BX1XoyFyf%2BOhBhF8BMh%2Bv5%2Bg%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.
Re: Absolute beginner question -- recipes
Thank you Rahul, I actually tried that an this is possible for the relationship between a recipe and its steps. But when it comes to the ingredients for a single step, I cannot do this any more since the ingredients depend on steps again. After reading your suggestion I thought about it once more and I came up with the following solution: def detail(request, pk): recipe = Recipe.objects.get(id=pk) steps = Step.objects.filter(recipe_id=pk) ingredients = dict() for step in steps: ingredients[step.id] = StepIngredients.objects.filter(step_id=step. id) template = loader.get_template('recipe/rezept_detail.html') context = { 'recipe': recipe, 'steps': steps, 'ingredients': ingredients } return HttpResponse(template.render(context, request)) However, when it comes to the view, it does not work any more: {{ recipe.name }} {% for step in steps %} {% for ingredient in ingredients.step.id %} {{ ingredient.amount }} {% endfor %} {{ step.description }} {% endfor %} According to what I found on google, the django template language cannot deal with accessing dictionary entries using variables as keys. What is the django-way of solving this problem? Any ideas? Thank you! -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To post to this group, send email to django-users@googlegroups.com. Visit this group at https://groups.google.com/group/django-users. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/c0974be2-ad5b-44bd-b08b-2fa0a18eee5a%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Absolute beginner question -- recipes
You could do something like this: def detail(request, pk): recipe = Recipe.objects.get(id=pk) steps = Steps.objects.filter(recipe_id=pk) template = loader.get_template('recipe/recipe_detail.html') context = { 'recipe': recipe, 'steps': steps } return HttpResponse(template.render(context, request)) And make appropriate changes to your template. On Monday, February 29, 2016 at 1:00:25 AM UTC+5:30, Simon Gunacker wrote: > > Dear Django Community, > > as a first django project I tried to write a site to manage cooking > recipes. My model is quite simple: > > * 1 recipe has n steps > * 1 step has a description and n ingredients, each of a certain amount > defined by a certain unit > > all in all, I have 5 tables (Recipe, Step, Ingredient, Unit, > StepIngredient). > > After reading through some documentation and trying around a little bit, I > got my model and my admin site (I had to install django-nested-inline for > the admin site to fit my expectations). > > Now I am struggeling with my views. There is a simple index view wich > basically lists all recipes: > > class IndexView(generic.ListView): > context_object_name = 'recipes_list' > > def get_queryset(self): > return Recipe.objects.all() > > The hard part is setting up the details view. It is supposed to show the > recipes name as a title and then list all the required ingredients and all > the required steps. It tried something like: > > def detail(request, pk): > recipe = Recipe.objects.get(id=pk) > recipe['steps'] = Steps.objects.filter(recipe_id=pk) > template = loader.get_template('recipe/recipe_detail.html') > context = { > 'recipe': recipe, > } > return HttpResponse(template.render(context, request)) > > but it seems I am not allowed to modify the recipes object. Any ideas how > to pass all the data which belongs to recipe to the template? > > Thank you, > > Simon > -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To post to this group, send email to django-users@googlegroups.com. Visit this group at https://groups.google.com/group/django-users. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/607fb0d4-844a-41c8-99e2-a914401b65ae%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Absolute beginner question -- recipes
You could do something like this: Instead of recipe['steps'] = Steps.objects.filter(recipe_id=pk) Do this: steps = Steps.objects.filter(recipe_id=pk) context = { 'recipe': recipe, } On Monday, February 29, 2016 at 1:00:25 AM UTC+5:30, Simon Gunacker wrote: > > Dear Django Community, > > as a first django project I tried to write a site to manage cooking > recipes. My model is quite simple: > > * 1 recipe has n steps > * 1 step has a description and n ingredients, each of a certain amount > defined by a certain unit > > all in all, I have 5 tables (Recipe, Step, Ingredient, Unit, > StepIngredient). > > After reading through some documentation and trying around a little bit, I > got my model and my admin site (I had to install django-nested-inline for > the admin site to fit my expectations). > > Now I am struggeling with my views. There is a simple index view wich > basically lists all recipes: > > class IndexView(generic.ListView): > context_object_name = 'recipes_list' > > def get_queryset(self): > return Recipe.objects.all() > > The hard part is setting up the details view. It is supposed to show the > recipes name as a title and then list all the required ingredients and all > the required steps. It tried something like: > > def detail(request, pk): > recipe = Recipe.objects.get(id=pk) > recipe['steps'] = Steps.objects.filter(recipe_id=pk) > template = loader.get_template('recipe/recipe_detail.html') > context = { > 'recipe': recipe, > } > return HttpResponse(template.render(context, request)) > > but it seems I am not allowed to modify the recipes object. Any ideas how > to pass all the data which belongs to recipe to the template? > > Thank you, > > Simon > -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To post to this group, send email to django-users@googlegroups.com. Visit this group at https://groups.google.com/group/django-users. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/90fe91f6-f752-45aa-9ea9-04d16da71178%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Absolute beginner question -- recipes
Dear Django Community, as a first django project I tried to write a site to manage cooking recipes. My model is quite simple: * 1 recipe has n steps * 1 step has a description and n ingredients, each of a certain amount defined by a certain unit all in all, I have 5 tables (Recipe, Step, Ingredient, Unit, StepIngredient). After reading through some documentation and trying around a little bit, I got my model and my admin site (I had to install django-nested-inline for the admin site to fit my expectations). Now I am struggeling with my views. There is a simple index view wich basically lists all recipes: class IndexView(generic.ListView): context_object_name = 'recipes_list' def get_queryset(self): return Recipe.objects.all() The hard part is setting up the details view. It is supposed to show the recipes name as a title and then list all the required ingredients and all the required steps. It tried something like: def detail(request, pk): recipe = Recipe.objects.get(id=pk) recipe['steps'] = Steps.objects.filter(recipe_id=pk) template = loader.get_template('recipe/recipe_detail.html') context = { 'recipe': recipe, } return HttpResponse(template.render(context, request)) but it seems I am not allowed to modify the recipes object. Any ideas how to pass all the data which belongs to recipe to the template? Thank you, Simon -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To post to this group, send email to django-users@googlegroups.com. Visit this group at https://groups.google.com/group/django-users. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/13050a08-1f80-41d0-9739-bf9dae9ef0d3%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.