Here's the bit that's giving me an issue: error 'QuerySet' object has no attribute 'address'
bdns = Business.objects.filter(name='slow')
addx = bdns.address
addr = Address.objects.get(id=addx)
What should I do?
My model for Business:
class Business(models.Model):
phone = PhoneNumberField()
address = models.ForeignKey(Address)
name = models.CharField(max_length=64)
A queryset is a collection, even if that collection only contains one element. When you do Model.objects.filter(), it returns a queryset.
If you want to return a single object, use Model.objects.get().
So, for your purposes:
bdns = Business.objects.filter(name='slow') # returns a collection
b = dbns[0] # get the first one
the_address = b.address # the address
# or...
try:
bdns = Business.objects.get(name='slow') # get single instance
except Business.DoesNotExist:
bdns = None # instance didnt exist, assign None to the variable
except Business.MultipleObjectsReturned:
bdns = None # the query returned a collection
if bdns is not None:
the_address = bdns.address
# the_address is an instance of an Address, so no need to do the lookup with the id
print the_address.id # 7
print the_address.street # 17 John St
print the_address.city # Melbourne
bdns = Business.objects.filter(name='slow')
Returns you a QuerySet (the collection of Business objects) You need to iterate to get each element with address.
addr = Address.objects.get(id=addx)
Should work
Related
I have the following code in a view:
lp_detail = LearningPathDetail()
pos_in_path = 1
lp_detail.lpheader_id = pk
lesson_ids = request.POST["lesson_ids"].split(",")
for lesson_id in lesson_ids:
lp_detail.id = ""
lp_detail.lesson_id = lesson_id
lp_detail.pos_in_path = pos_in_path
lp_detail.save()
pos_in_path += 1
pk is the ID from the header table that points back to the header record that identifies all of the detail records associated with it.
lesson_ids is a list of DB ids that need to be inserted into the lp_detail table.
What I think the code should do (according to the manual) based on the id being blank (I have also tried setting it to None)
is create the record, but instead I get an error:
Field 'id' expected a number but got ''.
Here is the model for the LearningPathDetail table:
class LearningPathDetail(models.Model):
lpheader = models.ForeignKey(LearningPathHeader, on_delete=models.CASCADE)
lesson = models.ForeignKey(Lesson, on_delete=models.CASCADE, blank=True, null=True)
pos_in_path = models.IntegerField(default=1)
I am not sure what I have incorrect here.
Why would you want to set value of id to empty string? Just delete this row:
lp_detail.id = ""
And let Django find good id by itself.
Also, I thin you want this:
lp_detail = LearningPathDetail()
Inside the loop. You might need new object with every iteration.
Pk / Primary Key / Row Number cannot be blank.
It should just be something like: (and Django will take care of all the PK stuff
# get header
headerObj = LearningPathHeader.objects.get(pk=pk)
lesson_ids = request.POST["lesson_ids"].split(",")
pos_in_path = 1
for i in lesson_ids:
# Get lesson Object
lessonObj = Lesson.objects.get(pk=i)
# create detail Obj
LearningPathDetail.objects.create(
lpheader= headerObj,
lesson= lessonObj,
opos_in_path= pos_in_path.
)
pos_in_path += 1
if LearningPathHeader is unique to the LearningPathDetail. (Example only 1 path can have the header 'science') Then you'd just want to remove all the previous paths
lesson_ids = request.POST["lesson_ids"].split(",")
headerObj = LearningPathHeader.objects.get(pk=pk)
# delete all the old Path!
LearningPathDetail.filter(lpheader=headerObj).delete()
pos_in_path = 1
for i in lesson_ids:
lessonObj = Lesson.objects.get(pk=i)
LearningPathDetail.objects.create(
lpheader= headerObj,
lesson= lessonObj,
opos_in_path= pos_in_path.
)
pos_in_path += 1
When trying to execute a select query via SQL-Alchemy, I am presented with the following error:
ArgumentError: Object <hello.models.User object at 0x106763210> is not legal as a SQL literal value
models.py
Base = declarative_base()
Base.query = db_session.query_property()
#login_manager.user_loader
def get_user(uid):
user = User.query.filter_by(id=uid).first()
return user
#Where code error ocurrs
class User(Base, UserMixin):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(120))
email = db.Column(db.String(120), unique=True)
company = db.Column(db.String(120))
password = db.Column(db.String(90))
admin = db.Column(db.Boolean, nullable=False, default=False)
In my case i executed a query which has an object instead a specific value.
This is how i got the error.
user=Users.query.filter_by(id=someid).first()#this was not a problem,
but the second query was like
friends=Friends.query.filter_by(user).first()#this is where i got ht problem
saying
flask-sqlalchemy-argumenterror-object-is-not-legal-as-a-sql-literal-value.
This means,that
i am trying to execute a query which has an object users, instead user.id(or something like that which should be a value)
So when i realize this i changed my query to
Friends=Friends.query.filter_by(user.id).first()#worked fine
Here you have to find some information about your problem: link
The typing system now has specific checks for passing of SQLAlchemy
“inspectable” objects in contexts where they would otherwise be
handled as literal values.
I had the same problem here:
def increase_relation(cls, previous, current):
current = DBSession.query(cls).filter_by(left_sound_id=previous, right_sound_id=current).first()
rate = int((100 - current.weight) - (100 - current.weight) / 1.618)
DBSession.query(cls).\
filter(cls.left_sound_id==previous).\
filter(cls.right_sound_id==current).\ # error is here
update({"weight": cls.weight + rate})
As you can see, I get "current" as a parameter and overwrite it on the next line, which is wrong.
And I fixed it this way:
def increase_relation(cls, previous_id, current_id):
current_rel = DBSession.query(cls).filter_by(left_sound_id=previous_id, right_sound_id=current_id).first()
rate = int((100 - current_rel.weight) - (100 - current_rel.weight) / 1.618)
DBSession.query(cls).\
filter(cls.left_sound_id==previous_id).\
filter(cls.right_sound_id==current_id).\
update({"weight": cls.weight + rate})
Check your "uid", does it have the correct type?
I have below two models,
class user_files(models.Model):
Filename = models.CharField(max_length=50)
Browse = models.FileField(upload_to='img/')
user_uploaded = models.CharField(max_length=50, blank=True)
class share_files(models.Model):
select_file = models.CharField(max_length=300)
from_user = models.CharField(max_length=50)
select_user = models.CharField(max_length=50,default=None)
user_files stores file uploaded by respective user.
and share_files stores shared file name yo user xx by user bb.
I want to show shared files with logged in user in template,
my function for it in view.py is,
def user_files_all(request):
if not request.user.is_authenticated:
return render(request, 'accounts/logout.html')
else:
data = user_files.objects.filter(user_uploaded=request.user)
data1 = share_files.objects.filter(select_user=request.user)
data2 = user_files.objects.filter(Filename=data1.select_file,user_uploaded=data1.from_user)
args = {'data': data,'data1':data1}
return render(request, 'accounts/files.html', args)
but i am getting error for line,
data2 = user_files.objects.filter(Filename=data1.select_file,user_uploaded=data1.from_user)
as attribute select_file is not present for data1. I want data from user_files model for all users and filename selected in data1. And then want to render that in template.
How to achieve that? Need help.
Thanks in advance.
filter(...) is a model manager method, it returns a queryset instead of an object. So you can do:
Use first() or last() method after using filter. Because these methods return a object from the queryset:
data_list = user_files.objects.filter(user_uploaded=request.user)
data1_list = share_files.objects.filter(select_user=request.user)
if data_list.exists():
data= data_list.first()
else:
data = None
if data1_list.exists():
data1 = data1_list.first()
data2 = user_files.objects.filter(Filename=data1.select_file,user_uploaded=data1.from_user) # its a queryset btw
else:
data1 = None
data2 = None # or user_files.objects.none()
.filter() returns a list of objects. So your data1 variable is a list. You cannot just get value of any attribute.
To achieve what you want you could try something like -
data2 = []
for d in data1:
ufs = user_files.objects.filter(Filename=d.select_file,user_uploaded=d.from_user)
for uf in ufs:
include = True
for d2 in data2:
if d2.pk == uf.pk:
include = False
break
if include:
data2.append(uf)
On a side note - your model design does not look good. Consider using ForeignKey. For more refer this.
Hope it helps.
EDIT
If you are using version 1.11 you can use union()
data2 = []
for d in data1:
ufs = user_files.objects.filter(Filename=d.select_file,user_uploaded=d.from_user)
data2 = data2.union(ufs)
I haven't tested the above codes but you get the idea. For more info on union(), look into this.
I have the following situation:
class Professor(models.Model):
default_address = models.OneToOneField('Address')
class Address(models.Model):
name = models.CharField()
street_address = models.CharField()
# ...
professor = models.ForeignKey("Professor", related_name="addresses")
Basically, one Professor can have many Addresses associated with it, but only one default_address selected. However, things aren't working right when I save things with my view, things don't get associated just right:
form = forms.ProfileEditForm(request.POST)
if form.is_valid():
address = professor.default_address or models.Address()
address.name = "Default" if address.name == None else address.name
address.street_address = form.cleaned_data['street_address']
address.street_address_2 = form.cleaned_data['street_address_2']
# ...
address.save()
professor.default_addresss = address
professor.save()
After I save it, professor.default_address is None. What am I doing wrong here?
You have a typo in your code:
professor.default_addresss = address
Should be
professor.default_address = address
Basically, nothing happens on save() for non model attributes.
It looks like you're making the address "default" if no name is supplied. If that's the case, why not just get rid of the One-To-One field and simply create an instance method on the Professor model that gets you the address with the name of "default."
Or, you could create a boolean field on the Address model called is_default (or something along those lines) and make that True if no name is supplied.
I needed to set user_profile on both the Address and the PhoneNumber before saving:
address.user_profile = user.profile
address.save()
phone_number.user_profile = user.profile
phone_number.save()
user.profile.default_address = address
user.profile.default_phone_number = phone_number
user.profile.save()
I'm matching the name in Album Model. And Its working just fine. But Some time It does not match. And It raise error message Album matching query does not exist. I want if no match is found. Then don't display any error message. Is it possible? Thanks
def movie_details(request,slug):
movies = get_object_or_404(Movie,slug=slug)
# calculating wikipedia directory structer for images
#image_name = movies.image
name = movies.title
album_name = Album.objects.get(name__exact=name)
album_id = album_name.id
song_list = Song.objects.filter(album=album_id)
#image_path = generateWikiImage(image_name)
#
return render_to_response('base_movies.html',locals(),
context_instance=RequestContext(request)
)
Error message
Album matching query does not exist
UPDATE:
def movie_details(request,slug):
movies = get_object_or_404(Movie,slug=slug)
# calculating wikipedia directory structer for images
#image_name = movies.image
name = movies.title
try:
album_name = Album.objects.get(name__exact=name)
album_id = album_name.id
song_list = Song.objects.filter(album=album_id)
except:
pass
Thanks F.C.
As suggested in the comment above, you need to catch the exception that's raised. In your case, it'd be:
try:
album_name = Album.objects.get(name__exact=name)
except Album.DoesNotExist:
pass
If you want to set album_name to some default value if you can't find it, replace pass with code to set it to your default value.
(This StackOverflow post also deals with a similar issue.)