I suppose this must be possible judging by this post but I can't seem to work out the syntax. I need to get the blog object with the picture field via the author foreign key.
Is this possible with get_object_or_404, and if so how?
#models.py
class Blog(models.Model):
author = models.ForeignKey(MyUser)
#author
class MyUser(AbstractUser):
picture = models.ImageField()
blog = get_object_or_404(Blog, pk=blog_id)
The query you want is like so (from the docs):
from django.db import models
class City(models.Model):
# ...
pass
class Person(models.Model):
# ...
hometown = models.ForeignKey(City)
class Book(models.Model):
# ...
author = models.ForeignKey(Person)
And then your query is:
b = Book.objects.select_related('author__hometown').get(id=4)
p = b.author # Doesn't hit the database.
c = p.hometown # Doesn't hit the database.
b = Book.objects.get(id=4) # No select_related() in this example.
p = b.author # Hits the database.
c = p.hometown # Hits the database.
except in your case your query would be: Picture.objects.select_related('author__blog').get(picture_name='somefilename.jpg')
You're saying I want the picture (and while your at it, the Author and their Blog) that relates to the picture name 'somefilename.jpg'. At least if I've understood your question and DB structure it is.
As Pureferret suggested in his answer
you can do it in following way,
blog = Blog.objects.get(pk=blog_id)
author = blog.author
and if you want to show that image in template just use
{{ auther.picture.url }}
Related
How do I get a queryset of specific child classes? It doesn't look like going through related_name is the answer. Using Django 3.2.6 btw.
Here is my setup:
class Quiz(models.Model):
name = # char field
class Question(models.Model):
# a quiz has many questions
quiz = models.ForeignKey(Quiz, related_name = '%(class)s')
# etc...
class TFQuestion(Question):
is_true = models.BooleanField(...)
class MCQuestion(Question):
n_choices = models.IntegerField(...)
What I want is to get a queryset of just MC Questions and process them as such.
I feel the need to emphasize that Question is NOT abstract. So the question model has its own related_name but the specified '%(class)s' pattern does not seem to propagate down to the child classes. All the other threads I've seen suggest using that pattern but it only works for abstract models! not when using multi-table inheritance.
From what I've seen, I can't just do:
quiz1 = Quiz.objects.get(id=1)
# this works; returns queryset of Question objects
allquestions = quiz1.question.all()
# doesn't work
all_mcqs = quiz1.mcquestion.all()
You can .filter(…) [Django-doc] with:
MCQuestion.objects.filter(quiz=quiz1)
For inheritance of a concrete model, Django will make tables for the Question, TFQuestion and MCQuestions, so three tables. The MCQuestion will have a "hidden" OneToOneField to Question.
self answer (kinda)
a couple workarounds i've seen, but jankier than just using a related_name:
A.) using classname__isnull:
quiz1 = Quiz.objects.get(id=1)
# get quiz1's MCQuestions as Questions
qs1 = quiz1.question.filter(mcquestion__isnull = False)
# returns: <QuerySet[<Question>,...]>
qs1.first().mcquestion.n_choices
B.) using InheritanceManager and classname__isnull:
from model_utils.managers import InheritanceManager
class Question(models.Model):
# ...
objects = InheritanceManager()
# django shell
quiz1 = Quiz.objects.get(id=1)
# get quiz1's MCQuestions as MCQuestions
qs1 = quiz1.question.select_subclasses().filter(mcquestion__isnull = False)
# returns: <InheritanceQuerySet[<Question>,...]>
qs1.first().n_choices
I made some models which have ManyToMany, OneToMany relationships, and then I tried to make appropriate class in views.py, so that one can see sub models related to the chosen model.
But in terms of connecting models-serializers-views-urls, I just couldn't figure out how to make it work...
So, what I want to do is : (simplified)
There are 3 models.
Party
People
Food
So Party has ManyToMany relationship with People, and OneToMany relationship with Food. When I reached url like /party_id/people_id, then I want to get specific person's information from given party id.
Here goes my code.
models.py
class Party(models.Model):
par_id = models.TextField()
par_people = models.ManyToManyField(People)
class People(models.Model):
peo_id = models.TextField()
peo_name = models.TextField()
peo_type = models.TextField()
class Food(models.Model):
foo_id = models.TextField()
foo_party = models.ForeignKey(Party, on_delete=models.CASCADE)
serializers.py
class PartySerializer(serializers.ModelSerializer):
class Meta:
model = Party
fields = ('par_id', 'par_people')
# People, Food has same structure...
views.py
class PartyList(generics.ListAPIView):
queryset = Party.objects.all()
serializer_class = PartySerializer
# People, Food has same structure...
urls.py
Here's the part where I got lost
#redundancy reduced...(e.g. import)
urlpatterns = [
path('party/<int:par_id>/<int:peo_id>', views.PartyList.as_view()),
path('party/<int:par_id>/<int:foo_id>', views.PartyList.as_view()),
]
So If I reach website/party/1/3, I want to see person's information(whose peo_id is 3) of party(whose par_id is 1). For food, It goes the same.
Should I make new class in views.py to make it work? But how can url check par_id and foo_id at the same time if I use PartyList view class..? Any help would be much appreciated.
I think something like this should work. The basic principle if work out if using peo_id or foo_id and then filter the queryset on that basis.
def get (self, *args, **kwargs):
id = kwargs.get(peo_id, None)
if id:
self.queryset.filter(par_people__peo_id=id)
else:
id = kwargs.get(foo_id, None)
self.queryset.filter(foo_party=id)
I am messing about with Django trying to learn more and I'm hitting a bit of a roadblock with understanding of the model design. I'm attempting to create an app that is like the facebook "wall" but it's purely albums with photos and videos, with comments and votes. My struggle is understanding how to design the relationship for items that could have many relationships. As an example, you can upvote photos, videos, comments, albums, and whatever else. What is the appropriate model design to address non-specific items? Here is my proposed structure thus far.
Album --primary
--id
--datetime
--created by
--title
--photo(s)
--comment(s)
--+1(s)
photo
--id
--foreignkey album
--datetime
--uploaded by
--caption
--comment(s)
--path
--+1(s)
video
--id
--foreignkey album
--datetime
--caption
--comment(s)
--path
--+1(s)
comments
--id
--user
--datetime
+1(s)
+1s
--id
--user
Sounds like you want a GenericForeignKey:
https://docs.djangoproject.com/en/1.11/ref/contrib/contenttypes/
The ContentType model allows you to make
It'd look something like this
from django.db import models
from django.contrib.auth.models import User
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
class Upvote(models.Model):
user = models.ForeignKey(User)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
You're looking for GenericForeignKey, example:
class Vote(models.Model):
class Meta:
db_table = "votes"
index_together = [
["content_type", "object_id"],
]
# The following 3 fields represent the Comment or Post
# on which a vote has been cast
# See Generic Relations in Django's documentation
content_type = models.ForeignKey(ContentType, on_delete=models.PROTECT)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
voter = models.ForeignKey(User, on_delete=models.PROTECT)
type_of_vote = models.IntegerField(choices = (
(UPVOTE, 'Upvote'),
(DOWNVOTE, 'Downvote'),
(FLAG, 'Flag'),
))
submission_time = models.DateTimeField(auto_now_add=True)
Here, ContentType model represent and store information about the models installed in your project (Album,Photo,Video...), and new instances of ContentType are automatically created whenever new models are installed.
Now we do not need to keep Foreign Key to other Django models we want to track. Using the GenericRelations, we can now track those votes to any model we want without having to modify the Vote model.
The reverse relation will be the part of the models we need to track. For example:
class Post:
...
...
votes = GenericRelation(Vote)
...
...
class Comment:
...
...
votes = GenericRelation(Vote)
...
...
Now, If we put a little thought to our existing Post and Comment models, we would observe that the two models should behave more or less in the same fashion. For instance, both of them can be upvoted, downvoted, flagged, unflagged and so they should provide interfaces to do so.
Hence we can create a base class for them as Votable and push the common behaviours and attributes to it. The Post and Comment will then be concrete classes and will inherit from Votable.
class Votable(models.Model):
""" An object on which people would want to vote
Post and Comment are concrete classes
"""
class Meta:
abstract = True
votes = GenericRelation(Vote)
author = models.ForeignKey(User, on_delete=models.PROTECT)
# denormalization to save database queries
# flags = count of votes of type "Flag"
upvotes = models.IntegerField(default=0)
downvotes = models.IntegerField(default=0)
flags = models.IntegerField(default=0)
def upvote(self, user):
....
....
def downvote(self, user):
....
....
class Post(Votable):
# post specific implementation
...
...
class Comment(Votable):
# comment specific implementation
...
...
Source
more info
I'm been trying to create an app that allows users to follow each other profile since yesterday and today and I haven't been successful so far.
I'm having trouble creating a following function that allows me to retrieve users from a particular user he follows.
Example . If John follows Diana . I want to able to retrieve the user called Diana and use it with my modules.
I'm really sorry if this doesn't make sense . I'm trying my hardest to explain my situation.
class Person(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=100)
image = models.FileField(upload_to="images/",blank=True,null=True)
class Board(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=100)
def __unicode__(self):
return self.name
Most of these solutions gave me no query
This was one of the solutions I tried.
class UserLink(models.Model):
from_user = models.ForeignKey(User , related_name = "following_set")
to_user = models.ForeignKey(User , related_name = "follower_set")
date_added = models.DateTimeField(default = datetime.now)
def __unicode__(self):
return "%s is following %s" % (self.from_user.username,self.to_user.username)
def save(self,**kwargs):
if self.from_user == self.to_user:
raise ValueError("Cannot follow yourself ")
super(UserLink , self).save(**kwargs)
class Meta:
unique_together = (('to_user','from_user'),)
I tried to retrieve the users that a particular user followed and use it against my modules such as Person but it gave me an error No query exist.
def Follow(request,username=""):
if request.method == "POST":
username = request.POST.get('follow',False)
user = User.objects.get(username=username)
UserLink.objects.create(from_user=request.user,to_user=user)
return HttpResponseRedirect(reverse('world:Profile'))
return HttpResponseRedirect(reverse('world:Profile'))
I also tried this following function but it only followed himself and I changed self to User but it didn't allow me to put the person to follow
class UserProfile(models.Model):
user = models.OneToOneField(User)
follows = models.ManyToManyField('self', related_name='followed_by', symmetrical=False)
>>>from pet.models import *
>>>from django.contrib.auth.models import User
>>>user = User.objects.get(username='Peter')
>>>user1 = User.objects.get(username='Sarah')
>>>p = UserProfile.objects.filter(user=user,follows=user1)
>>>Error no field called follows
How can I create a following class that allows retrieve the people that they followed and use it with my modules such as Person?
Can someone help me . Thannk you community!
If I understand correctly, youu are on the right track with the many to many relationship. What you need is to modify your existing Person class to include this information.
Since information about who someone follows or is following is essentially information about that person and so you shouldn't really need to define a new class to implement that functionality.
I would suggest modifying your Person like so.
class Person(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=100)
image = models.FileField(upload_to="images/",blank=True,null=True)
following = models.ManyToManyField('self', related_name='followers', symmetrical=False, blank=True, null=True)
What this line does is makes a many to many relationship between the class Person and its self.
Many to many relationships work a little different to other relationships and I suggest you read the Django documentation https://docs.djangoproject.com/en/dev/topics/db/examples/many_to_many/.
But you should now be able to setup and access the relationship like this.
>>>john = Person.objects.get(name="John")
>>>diana = Person.objects.get(name="Diana")
>>>john.following.add(diana)//setup the many to many relationship
>>>john.save()
>>>john.following.all()
//This should return a queryset of Person objects which john is following.
//eg Diana
>>>diana.followers.all()
//This should return a queryset of Person objects which are following Diana.
//eg. John.
Easy, how awesome is Django!
I have created a Profile model including the Gender info. There is also models called Dorm and Registration (not used for user registration) like this:
class Registration(models.Model):
user = models.ForeignKey(User)
pref1 = models.ForeignKey(Dorm, related_name="pref1",verbose_name=u"Preference 1",null=True)
...
friend1 = models.CharField(u"Friend 1", max_length=15,blank=True)
class Dorm(models.Model):
name = models.ForeignKey(Building)
gender = models.CharField(u"Gender", max_length=1, blank=True, choices=GENDER_CHOICES)
Now, i am trying to generate a form for this Registration model with forms.ModelForm like this:
class RegistrationForm(forms.ModelForm):
dorms = Dorm.objects.filter(gender='M')
pref1 = forms.ModelChoiceField(queryset=dorms, empty_label=None)
...
class Meta:
model = Registration
exclude = ('user')
as you can see in the second line, i am querying the dorms with a hardcoded gender value M. Instead of the hardcoded value, I need to get the users' gender, and query the database with that gender information.
I have been searching the documentation but I could not find anything. Can you help me? How can I learn the logged-in User' profile information in Django Forms?
So without using some sort of monkeying around of the init function a "form_factory" is probably the best approach.
def RegFormFactory(user)
dorms = Form.objects.filter(gender = "user.gender")
class _RegistrationForm(forms.ModelForm):
pref1 = forms.ModelChoiceField(queryset = dorms, empty_label=None)
class Meta:
model = Registration
exclude = ('user')
return _RegistrationForm
then use:
formclass = RegFormFactory(user)
form_inst = formclass()
...
form_inst = formclass(request.POST)
This is described very nicely in a blog post here: So you want a dynamic form.
James Bennett wrote a blog post that should explain perfectly what you need: So you want a dynamic form