django views - accessing a m2m field in a generic view - django

I've stumbled upon this issue and my noob brain got fried trying to resolve it. I feel like there's some basic concepts here that I'm missing.
So I have this "Films" model with category choice field and a m2m relationship to a "Directors" model, and I'm trying to write 2 different views, one that returns a list of films filtered by category and one that returns a list of films filtered by director.
The first one is easy, but I just don't know how to get the director model's name field to create the second filter.
So I have this models (i've taken the irrelevant stuff out including the category thing i mentioned above)
class Director(models.Model):
name = models.CharField(max_length=50)
web = models.URLField(blank=True, help_text= "opcional")
class Film(models.Model):
name = models.CharField(max_length=50)
slug = models.SlugField(max_length= 15)
director = models.ManyToManyField(Director, blank=True, help_text= "opcional")
this url
(r'^peliculas/director/(?P<director>\w+)/$', 'filtered_by_director'),
and this view
def filtered_by_director(request,director):
return list_detail.object_list(
request,
queryset = Film.objects.filter(director.name=director),
template_name ='sections/film_list.html',
template_object_name = 'film',
paginate_by = 3
)
The same template is supposed to be used by both views to render the relevant list of objects
The view doesn't like the filter i'm using at the queryset for the m2m field, but I have no clue how to do it really, I've tried whatever I could think of and it gives me a "keyword can't be an expression" error
Any help to this lowly noob will be appreciated.

Line queryset = Film.objects.filter(director.name=director),
needs to read: queryset = Film.objects.filter(director__name=director),
Field lookups are done by __ double underscore syntax:
http://docs.djangoproject.com/en/dev/topics/db/queries/#field-lookups

In your filter, try specifying the director name like (documentation):
filter(director__name=director)

Related

Django Model queries with relationships. How to do the right join

Let's say I have 2 Models:
class Auction(models.Model):
seller = models.ForeignKey(User, on_delete=models.CASCADE, related_name="seller")
title = models.CharField(max_length=64)
class Watchlist(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='user_watchlist')
auction = models.ForeignKey(Auction, on_delete=models.CASCADE, related_name='auction_watchlist')
The view receives a request, creates a context variable with the auction objects the are:
associated with the user who made the request and
that have been added to the Watchlist Model,
sends it to the template.
I have set up my view to work like this:
#login_required
def watchlist(request):
watchlist_objects = Watchlist.objects.filter(user=request.user)
auction_objects = Auction.objects.filter(auction_watchlist__in=watchlist_objects).all()
context = {'watchlist_auctions': auction_objects}
print(context)
return render(request, "auctions/watchlist.html", context)
-I make the first query to get the list of items in the watchlist associate with the user.
-Then I use that to get another query from the Auction Model and I pass it to the template.
In the template I can access the attributes of Auction to display them. (title, author, and others that I did not include for simplicity)
The question is:
Is this the "right way? Is there a better way to access the attributes in Auction from the first Watchlist query?
It seems to me that I'm doing something overcomplicated.
This is not that bad, considering that it will probably be executed as one query, because of the lazy queryset evaluations. You can skip the .all() if you already have .filter().
However, there is a more convenient way to do this, using lookups that span relationships.:
auction_objects = Auction.objects.filter(auction_watchlist__user_id=request.user.id)

Django orm: order post queryset by greatest number of tags from search

I want to order posts by the greatest number of tags a post has
my models:
class post(models.Model):
description = models.Charfield(max_length = 2000)
class tag(models.Model):
t = models.Charfield(max_length = 100)
class tags(models.Model):
tag = models.ForeignKey(tag, ...)
post = models.ForeignKey(post,...)
I know django's orm supports many to many fields I have other reasons for doing it this way.
When inputs a search, example: purple mountain flowers
I want to query for posts that have any of the tags and order the query by the posts with the most matching tags. I'm new to using aggregation in django and have no idea how to structure this. Any recommendations?
here's what I've tried so far which doesn't work if my db has more than one match:
qs = post.objects.annotate(num_of_tags =
Count(Subquery(tags.objects.filter(post = OuterRef('pk'),
tag__body__in = search_list).only('pk')))).filter(num_of_tags__gt
= 0).order_by('num_of_tags')
when there's more than one instance in my db it returns this error:
django.db.utils.ProgrammingError: more than one row returned by a subquery used as an expression
Firstly you should follow some python/Django standards for naming. Model class should be Titleized (Post, Tag, PostTag) and singular
You can use the option through to define your own model for m2m:
class post(models.Model):
description = models.Charfield(max_length = 2000)
post_tags = models.ManyToManyField(tag, through=tags)
After that you can make use of django m2m to let you query easier:
from django.db.models import Q, Count
qs = post.objects.annotate(
num_of_tags=Count('post_tags', filter=Q(post_tags__body__in=search_list)))
).filter(num_of_tags__gt=0).order_by('num_of_tags')

Django model design: editable help text for individual model fields. Is there a foreign field that references a specific field of a model?

I have several models with several fields in my app. I want to set up a way for the user to be able to modify a help text system for each field in the model. Can you give me some guidance on how to design the models, and what field types to use? I don't feel right about storing the model and field name in CharFields, but if that is the only way, I may be stuck with it.
Is there a more elegant solution using Django?
For a quick and silly example, with an app named jobs, one named fun, and make a new app named helptext:
jobs.models.py:
class Person(models.Model):
first_name = models.CharField(max_length=32)
.
.
interests = models.TextField()
def __unicode__(self):
return self.name
class Job(models.Model):
name = models.CharField(max_length=128)
person = models.ForeignKey(Person)
address = models.TextField()
duties = models.TextField()
def __unicode__(self):
return self.name
fun.models.py:
class RollerCoaster(models.Model):
name = models.CharField(max_length=128)
scare_factor = models.PositiveInteger()
def __unicode__(self):
return self.name
class BigDipper(RollerCoaster):
max_elevation = models.PositiveInteger()
best_comment_ever_made = models.CharField(max_length=255)
def __unicode__(self):
return super.name
Now, let's say I want to have editable help text on Person.interests, and Job.duties, RollerCoaster.scare_factor, and BigDipper.best_comment_ever_made. I'd have something like:
helptext.models.py:
from django.contrib.contenttypes.models import ContentType
class HelpText(models.Model):
the_model = models.ForeignKey(ContentType)
the_field = models.CharField(max_length=255)
helptext = models.CharField(max_length=128)
def __unicode__(self):
return self.helptext
So, what is the better way to do this, other than making HelpText.the_model and HelpText.the_field CharFields that have to be compared when I am rendering the template to see if helptext is associated with each field on the screen?
Thanks in advance!
Edit:
I know about the help_text parameter of the fields, but I want this to be easily edited through the GUI, and it may contain a LOT of help with styling, etc. It would be HTML with probably upwards of 50-60 lines of text for probably 100 different model fields. I don't want to store it in the field definition for those reasons.
I changed the HelpText model to have a reference to ContentType and the field a CharField. Does this seem like a good solution? I am not sure this is the most elegant way. Please advise.
Edit 2013-04-19 16:53 PST:
Currently, I tried this and it works, but not sure this is great:
from django.db import models
from django.contrib.contenttypes.models import ContentType
# Field choices for the drop down.
FIELDS = ()
# For each ContentType verify the model_class() is not None and if not, add a tuple
# to FIELDS with the model name and field name displayed, but storing only the field
# name.
for ct in ContentType.objects.all():
m = ct.model_class()
if m is not None:
for f in ct.model_class()._meta.get_all_field_names():
FIELDS += ((f, str(ct.model) + '.' + str(f)),)
# HelpText model, associated with multiple models and fields.
class HelpText(models.Model):
the_model = models.ForeignKey(ContentType)
the_field = models.CharField(max_length=255, choices=FIELDS)
helptext = models.TextField(null=True, blank=True)
def __unicode__(self):
return self.helptext
Doesn't feel like the best, but please advise if this is a solution that will bite me in the behind later on and make me filled with regrets... :*(
The solution works, and I have it implemented, but you have to be aware that sometimes the ContentTypes get out of sync with your models. You can manually update the content types with this:
python manage.py shell
>>> from django.contrib.contenttypes.management import update_all_contenttypes
>>> update_all_contenttypes(interactive=True)
This allows you to add the new ones and remove the old ones, if they exist.
The nice thing about the Field not being a foreign key is that I can put anything in it for help text. So, say I have a field "First Name." I can put a helptext connected to the Person model and the "first_name" field. I can also make something up, like "Something really confusing." The helptext is now associated with the Person model and the "Something really confusing" field. So, I can put it at the top of the form, instead of associating to a field with hard foreign keying. It can be anything arbitrary and will follow with that "field" anywhere. The hangup would be that you may change the name of the helptext field association inadvertently sending your original helptext into never land.
To make this easy, I created a TemplateTag, which I pass the name of the model and the name of the "field" I want to associate. Then anytime the template is rendered, that helptext is there, editable for anybody to get assistance with their user interface forms.
Not sure this is the best solution, but I couldn't really see any other way to do it, and got no responses.
Cheerio!

Django fetch all relations

I have an app with a similar structure as this snippet
class Blog(models.Model):
name = models.CharField(max_length=25)
class Category(models.Model):
name = models.CharField(max_length=25)
blog = models.ForeignKey(Blog)
class Entry(models.Model):
title = models.CharField(max_length=25)
category = models.ForeignKey(Category)
What is the most generic way, that i will be able to use in other apps to fetch all blogs with their category and entries?
I thought about creating a manager for the Blog model, that can fetch all the Categories for that blog, but it's hardcoding the model names
class BlogManager(models.Manager):
def categories(self):
return Category.objects.filter(blog=self)
Any suggestions?
What you want is a Select Related. It returns a QuerySet that will automatically "follow" foreign-key relationships, selecting that additional related-object data when it executes its query. Your query for Blogs would look something like:
Blog.objects.select_related().filter( something )
or
Blog.objects.select_related().get( something )
Why not use a standard way?
Filter using Blog's PK with FK relation.
Category.objects.filter(blog__pk=self.pk)

How can I use multiple queryset in a ModelChoiceField?

I'm just beginning to learn Django and I would like to use different queryset in a ModelChoiceField.
I have 3 models like that :
class Politic(models.Model):
name = models.CharField(max_length=100)
class Economic(models.Model):
name = models.CharField(max_length=100)
class Category(models.Model):
politic = models.ForeignKey(Politic, blank = True, null = True)
economic = models.ForeignKey(Economic, blank = True, null = True)
And a form like that :
class MyForm(forms.Form):
choice = forms.ChoiceField(choices = (("0", u"---------"), ("1", u"Politic"),
("2", u"Economic")),
required=False)
category = forms.ModelChoiceField(queryset=Economic.objects.all(),
required=False)
In my template, I use Ajax to populate my category field with a list of all Politic or Economic value according to my choice field.
But if I choose "Politic", I have a problem in the validation of my form because the queryset of my category field is Economic.objects.all(), not Politic.objects.all().
How can I change my dynamicaly queryset? Any ideas?
You can have 2 different selects One for politic and one for economic and show/hide them based on choice field.
Or maybe Abstract Model Inheritance would solve your problem
One possibility would be to use a Generic Relation in your Catagory model.
Thanks for your answers, I try to use your two solutions (Abstract Model and Generic Relation) but it doesn't resolve my problem.
So I create two differents ModelChoiceField (one for Politic and one for Economic) and I use hide/show effects of Jquery in my template (like you say Kugel).
But if you have any others ideas for my problem, I'm interessed.