Reverse ForeignKey lookup - python

I'm new to Django and am still trying to break old PHP habits. Below are two models. To make things confusing they live in separate files, in different apps...
#article.models
from someapp.author.models import Author
class Article(model.Model):
...
author = models.ForeignKey(Author)
# author.models
class Author(model.Model):
...
From this schema I want to be able to get all the articles by an author. Something like:
author = Author(pk=1)
articles = author.articles
My first reaction was to write a method that did a simple look up in the article model based on the authors ID. What happened here was a never ending inclusion loop because of the separate files. Article needed Author imported to use for the ForeignKey and Author needed article included to use for the model look up. This felt hacky and wrong. I would much rather do it the right way... So, what is the Django way?

I think this is what you're asking for...
class Article(model.Model):
...
author = models.ForeignKey(Author, related_name='articles')
On a side note, by default without changing anything you've got, I think this would work for you...
article.author_set
But to maintain the article.authors syntax you mention above, you can specify that yourself with related_name.

Related

What side should a django 'many-to-many' relationship reside on

Lets say I have a recipe website with two basic models, 'User' and 'Recipe'
class User(models.Model):
username= models.CharField()
email = models.CharField()
class Recipe(models.Model):
name = models.CharField()
description = models.CharField()
I would like to add the functionality so that users can 'favorite' a recipe.
In this case, I need to use a many-to-many relationship. My question is, how do I decide which model to add the relationship to?
For example, each user could have a list of 'favorite' recipes:
class User(models.Model):
favorites = models.ManyToManyField(Recipe)
Alternatively, each recipe could have a list of users who Favorited the recipe:
class Recipe(models.Model):
user_favorites = models.ManyToManyField(User)
What is considered the best practice? Is either one better for query performance?
It makes no difference from the database point of view, as pointed out in the comments.
But I have had two arguments where it did matter to me.
First (maybe less important), the built-in admin treats the two models differently by default. The model on which you define the relationship gets a widget for choosing the related objects. And a '+' for conveniently adding new objects of the related type.
secondly, you have to import one of the models in the file of the other one, if they are in different files. This matters if you want to write a reusable app that does not depend on anything outside. It mattered to me also because:
I once (well, not just once actually :)) broke my app/database/etc such, that I decided to start a new project and copy the code there. In this case you have to comment out some settings.INSTALLED_APPS to test step for step that everything works. Here it is important not to have circular includes (to include a commented-out app raises an error). So I try to import the "most basic" into the others, and not the other way round.
This not a simple answer to your question, but two points which I consider. Maybe some more experienced users can correct me if it's wrong in some sense.

How to describe parameters in DRF Docs

I'm using Django REST Framework v3.6 built-in interactive documentation django_rest_framework.documentation (not django-rest-swagger).
Basically, I'm following the official documentation and use this in my URLset configuration:
from rest_framework.documentation import include_docs_urls
urlpatterns = [
url(r"^", include_docs_urls(title="My API")),
...
]
Everything seems to work and I get a nice interactive documentation page, but I have a ViewSet with lookup_field = "slug" and one thing about the generated documentation bothers me:
I want to have some useful information it that description, like "an unique permanently-assigned alphanumeric ID" or something among those lines, but can't find any documentation where this data comes from.
There is a workaround but I really don't want to define all the schema explicitly. I want to declare my classes with nice docstrings and have docs auto-generated. I've also found an suggestion to put slug -- here goes the description in the docstring but it doesn't seem work - the text just appears with the rest of the Markdown-formatted description.
So... I wonder about two things:
(A specific question) Where do I fill this path parameter description?
(More generic version of the same question) What's the best way to learn how schemas are auto-generated from code?
Oh, I found it. Answering my own question.
DRF documentation isn't verbose on this matter (or I've missed the piece where it is), but it mentions rest_framework.schemas.SchemaGenerator class and it seems that this class really does all the introspection stuff. Fortunately, the source code is well-structured and easy to read.
Those path fields are generated by get_path_fields method (I found it by tracing the execution path: get_schema → get_links → get_link), and I found that descriptions come from model fields's help_text attribute.
So in my model I've specified:
class MyResource(models.Model):
slug = models.CharField(unique=True, help_text=_("unique alphanumeric identifier"))
...
And it worked!
One important thing was not still covered. It is true that a description comes from the help_text attribute, but this is not enough. I have found that the schema generator rely on view's queryset attribute to determine a model. So, keep in mind that you need define it even if you don't need it. For example in case of using APIView.

Which Dynamic Internationalisation system to use in Django projects?

I am developing a new project from scratch with Django. I see that there are many apps for handling translation of dynamic content.
Django-multilingual
Django-pluggable-model-i18n
Django-modeltranslation
Transdb
Django-multilingual-model-
Django-transmeta
to name few.
Transdb, transmeta and multilingual sounded fair, but I want to read some personal experiences.
Which one of them should I choose?
I agree with S.Lott in that you will want to think about what you need from internationalization. However, this is a very good run-down of all of the mentioned packages:
http://blog.muhuk.com/2010/01/06/dynamic-translation-apps-for-django.htm
My personal pick thus far is "none of the above". I am currently prototyping with datatrans:
http://github.com/citylive/django-datatrans
http://www.botondus.com/dynamic-translation-with-django-datatrans/
But I may yet choose another solution.
There are 2 kinds of model translation:
Adding extra columns/fields to the model to translate
Using a second table for translations
The 1st approach is more efficient because you don't use extra joins. And the 2nd one is less intrusive because it doesn't modify the original model table. I personally like the 1st option better and that's one of the main reasons why I use django-modeltranslation.
You can also have a look to this comparison grid.
Django-nani is a brand-new application, which is fast, and well-written using probably the best design approach.
It's still in development but works well and has a very complete documentation.
This is a snippet to see how the multilingual models are defined:
from django.db import models
from nani.models import TranslatableModel, TranslatedFields
class DjangoApplication(TranslatableModel):
name = models.CharField(max_length=255, unique=True)
author = models.CharField(max_length=255)
translations = TranslatedFields(
description = models.TextField(),
description_author = models.CharField(max_length=255),
)
def __unicode__(self):
return self.name
I'm using the django i18n for a bilingual project: I'm really really satisfied of this one and I definitely would recommend it, but I've got to say that I've never tried one of the others...

Django -- How to filter objects with an "author" from a set of "authors"(users)?

How to filter objects with an "author" from a set of "authors"(Users)?
The "objects" are Posts, having an author(ForeignKey to User).
I'm pretty much stumped by this, so I'd appreciate help with it. Of course one could go about this the naive way, by manually filtering them, but that would hit the database real hard. Thanks anyway.
EDIT:
Listing of Post:
class Post(models.Model):
'''A Post or a Status Update.
'''
content=models.CharField(max_length=200)
author=models.ForeignKey(django.contrib.auth.models.User, related_name="author")
tags=models.ManyToManyField(Tag)
replyTo=models.ManyToManyField(django.contrib.auth.models.User, related_name="replyTo")
# Snip model methods
Clarification: I'm trying to filter based upon a set of users and not a single user (which is trivially easy to do)
when=models.DateTimeField(auto_now=True)
Thanks to everyone who helped with the previous question. Now I have one final thing to ask:
Code excerpt from UserProfile (connected to User):
def get_updates():
return Post.objects.filter(author__in=(list(self.friends.all()) + [self]))
Is this the most efficient way to get all the posts by an author and its friends? (Note: This is a naive implementation, as it doesn't handle pagination, etc. Will do that later)
Something like:
Post.objects.filter(author=user)
Where user is the relevant user should work, but it's hard to give a good answer with no models
EDIT
Now that I understand your question, try this:
Post.objects.filter(author__in=users)
Where users is the set of users
Post.objects.filter(author__in=setofusers)
Post.objects.filter(attribute__in = list_of_ids)

How can I programmatically obtain the max_length of a Django model field?

Say I have a Django class something like this:
class Person(models.Model):
name = models.CharField(max_length=50)
# ...
How can I programatically obtain the max_length value for the name field?
Person._meta.get_field('name').max_length will give you this value. But having to use _meta suggests this is something you shouldn't do in normal usage.
Edit: as Carl pointed out, this naming is misleading and it does seem quite acceptable to use it: http://www.b-list.org/weblog/2007/nov/04/working-models/
Read more at Django Docs:
https://docs.djangoproject.com/en/dev/ref/models/meta/#django.db.models.options.Options.get_field
The question is regarding models, but for people trying to do the same for forms (that's how I ended up in this thread), I think this approach is quite simple and clear:
1. In a template:
{{form.name.field.max_length}}
2. In python code (e.g. in the view)
form.name.field.max_length

Categories

Resources