theres's something I'm missing or don't understand, maybe a very basic concept.
I have two models Person and Student, related by a OneToOneField like this:
class Student(models.Model):
person = models.OneToOneField(
Person,
on_delete = models.CASCADE,
)
# fields definition
Should't I be able to access Student from Person with student_set?
Like this, but I get de error as follows:
>>> from people.models import Person
>>> p = Person.objects.get(pk=6)
>>> p.student_set.all()
Traceback (most recent call last):
File "<console>", line 1, in <module>
AttributeError: 'Person' object has no attribute 'student_set'
>>>
Thanks!
The answer you are looking for is literally in the term "One to One relationship", there is not set returned here but a direct relationship.
p.student is going to access the student object related the person
Related
Using autocomplete_fields/search_fields in Django's admin works well to cause a Select2 widget to be used for a ForeignKey field, but I'm getting an error when I set things up to have Select2 widgets rendered on a declared through model in a ManyToManyField relationship. My models are different than the following, but using the example from the Django docs where through models in the admin are discussed as a starting point, I have things set up something like this (the example in the docs has an implicit through model, but I have an explicitly declared through model):
class Person(models.Model):
first_name = models.CharField(max_length=128)
last_name = models.CharField(max_length=128)
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership', related_name='groups')
class Membership(models.Model):
person = models.ForeignKey('Person', ...)
group = models.ForeignKey('Group', ...)
and in admin.py:
class PersonAdmin(admin.ModelAdmin):
inlines = [MembershipInline,]
search_fields = ('first_name','last_name,)
class MembershipInline(admin.TabularInline):
model = Membership
autocomplete_fields = ('person',)
class GroupAdmin(admin.ModelAdmin):
inlines = [MembershipInline,]
When I go to the GroupAdmin and try to create a membership, the Select2 widget is rendered, but when I try to look up a person, I get this error:
Forbidden (Permission denied): /admin/autocomplete/
Traceback (most recent call last):
File "/virtualenvs/my_virtualenv/lib/python3.8/site-packages/django/utils/datastructures.py", line 84, in __getitem__
list_ = super().__getitem__(key)
KeyError: 'app_label'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/virtualenvs/my_virtualenv/lib/python3.8/site-packages/django/contrib/admin/views/autocomplete.py", line 79, in process_request
app_label = request.GET["app_label"]
File "/virtualenvs/my_virtualenv/lib/python3.8/site-packages/django/utils/datastructures.py", line 86, in __getitem__
raise MultiValueDictKeyError(key)
django.utils.datastructures.MultiValueDictKeyError: 'app_label'
I am using django-jazzmin, so the problem COULD be caused by it, but the Select2 widgets work fine in ForeignKey relationships that are not part of a through model. Someone encountered something similar in Grappelli a year ago, but I can't tell whether this problem is similar.
Any help is very much appreciated.
Not sure if the title is the correct one, sorry for the inconvenience.
I'm having a problem on sending a ManyToManyField from a model to a dictionary using the model_to_dict() Below is my code
models.py
from django.db import models
from django.forms import model_to_dict
from app_1.models import *
class Stuff(models.Model):
thing_1 = models.CharField(max_length=100, null=True, blank=True)
thing_2 = models.ManyToManyField(OtherStuff, blank=True, related_name="thing")
def toJSON(self):
item = model_to_dict(self)
item['thing'] = self.thing.toJSON()
return item
When I run a query and load my Stuff model, I get the following error:
from app_2.models import *
s = Stuff.objects.get(pk=1)
# here is where I send my model to a dictionary
s.toJSON()
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "P:\test\app\app_2\stuff\models.py", line 10, in toJSON
return item
AttributeError: 'ManyRelatedManager' object has no attribute 'toJSON'
I've come across multiple ways of sending a ManyToManyField to a dictionary, however, none of them use the model_to_dict(). I'd like to use this method due to it's simplicity of usage.
With this approach, you'll need to use this syntax:
item['thing'] = [t.toJSON() for t in self.thing_2.all()]
And also, implement the toJSON method for the OtherStuff model.
Or you can use model_to_dict for OtherStuff as well:
def toJSON(self):
item = model_to_dict(self)
item['thing'] = [model_to_dict(t) for t in self.thing_2.all()]
return item
Let's say I have AssetUser model looks like follow.
class AssetUser(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
my query set looks like follow.
qs = User.objects.get(pk=1)
when i run qs.assetuser_set i am getting error like follow.
Traceback (most recent call last):
File "", line 1, in
AttributeError: 'User' object has no attribute 'assetuser_set'
what mistake i made here.
Django models should be inherited from Model class, so you need to change your code to this:
class AssetUser(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
I am just exploring how to get around with Django, and i created two models in my Django app.
from django.db import models
#first model
class Person(models.Model):
name = models.CharField(max_length=40)
email = models.CharField(max_length=100)
title = models.CharField(max_length=100)
image = models.CharField(max_length=200)
def __str__(self):
return self.name
#second model
class Skill(models.Model):
person = models.ForeignKey(Person)
skill = models.CharField(max_length=60)
years = models.CharField(max_length=40)
def __str__(self):
return self.skill, self.person
The first model is Person and the second model is Skill. Now how the relation goes is that each Person will have many skills.
Now I can update the database with the data, the admin section of the site also works fine.
On the Django Shell, I try to run the command:
Skill.object.all()
and what i get is the following error:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\db\models\query.py", line 235, in __repr__
return '<QuerySet %r>' % data
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\db\models\base.py", line 572, in __repr__
u = six.text_type(self)
TypeError: __str__ returned non-string (type tuple)
or if i try the command:
Skill.objects.get(pk=1)
i get:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "C:\Program Files (x86)\Python36-32\lib\site-packages\django\db\models\base.py", line 572, in __repr__
u = six.text_type(self)
TypeError: __str__ returned non-string (type tuple)
However if i run a command such as :
Skill.objects.get(skill='Photoshop').person.name
I get the name of the person who has the skill "Photoshop."
I am trying to understand what I am doing wrong here; maybe I am not supposed to query a table with the foreign key this way? Or maybe I am doing something wrong.
Well, finally what I like to query is, I want to find all the skills of a Person with a given name or primary key.
__str__ should return a str. So Change something like this
return self.skill, self.person
to
return "%s-%s" %(self.skill, self.person.name)
Your __str__ method returns a tuple (self.skill, self.person), it must return those object's str representation. In order to achieve that, change:
return self.skill, self.person
to
return "{}, {}".format(self.skill, self.person)
This seems like a really trivial question, but it is killing me.
models.py
class Location(models.Model):
place = models.CharField("Location", max_length=30)
[...]
class Person(models.Model):
first = models.CharField("First Name", max_length=50)
[...]
location = models.ManyToManyField('Location')
From the shell:
>>> from mysite.myapp.models import *
>>> p = Person.objects.get(id=1)
>>> p
<Person: bob >
>>> l = Location(place='123 Main')
>>> p.location_set.add(l)
>>> p.save()
Traceback (most recent call last):
File "<console>", line 1, in <module>
AttributeError: 'Person' object has no attribute 'location_set'
I'm really not seeing what I'm missing.
Shouldn't you be using p.location.add()? location_set or <modelname>_set is the default name for the reverse lookup for that model.
location_set would be the default name for a backward relation, however since you've defined the ManyToManyField on the Person model, you can access the related manager via the field name:
p.location.add(l)
With this in mind, it makes more sense to name the ManyToManyField as a pluralised noun, e.g.
class Person(models.Model):
first = models.CharField("First Name", max_length=50)
[...]
locations = models.ManyToManyField('Location')
Also, from memory, when you try to add model instances to a many-to-many relationship, the instance must be saved prior to adding.