Django get attribtues of foreign key - django

I have an intermediate model -
class Link_Book_Course(models.Model):
book = models.ForeignKey(Book)
course = models.ForeignKey(Course)
image = models.CharField(max_length = 200, null=True)
rating = models.CharField(max_length = 200,null=True)
def save(self,*args,**kwargs):
self.date_created = datetime.now()
super(Link_Book_Course,self).save(*args,**kwargs)
and I need to get the book name and title (which are attributes of Book) from a specified Link_Book_Course.
This is what I've come up with, but it doesn't work- instances don't have access to the manager apparently -
storedCourse = Link_Book_Course.objects.filter(course__name= nameAndNumberStore[0] + nameAndNumberStore[1])
storedLink = Link_Book_Course.objects.filter(course = storedCourse)[0]
storeOfAuthorNames = storedLink.objects.values('book__author')
storeOfBookNames = storedLink.objects.values('book__title')
EDIT-
Nevermind, I've figured it out- for reference sake- you can't get attributes through a foreign key relationship.
Instead I filtered the Books that had the course that the user searched for.

Here's an even easier way!
>>> course = Course.objects.filter(name= nameAndNumberStore[0] + nameAndNumberStore[1])
>>> links = course.link_book_course_set.all()
>>> BookAuthorNames = [(link.book.title, link.book.author) for link in links]
(('Book1','Author1'),('Book2','Author2'),...)
Remember, the django ORM is powerful!

Related

How to display database data to your website?

This is a very simple question that got me stuck. I have 2 tables that are connected: Dealershiplistings, Dealerships. On my website I need to display the Model, Make and year of the car (Which are all stored in the DealershipListing, so i have no problem wiht this part) but I also need to print the address that is stored in the Dealerships table. Can anyone help me with this?
this is what i have for my views.py
def store(request):
dealer_list = Dealer.objects.all()
car_list = DealershipListing.objects.all()
context = {'dealer_list': dealer_list, 'car_list': car_list}
return render(request, 'store/store.html', context)
i tried doing
{{%for car in car_list%}}
<h6>{{car.year}} {{car.make}} {{car.model}}</h6>
{% endfor %}
which works perfectly displaying those. But now how do i display the address of the dealership that is selling the car?
models.py
class Dealer(models.Model):
dealersName = models.TextField(('DealersName'))
zipcode = models.CharField(("zipcodex"), max_length = 15)
zipcode_2 = models.CharField(("zipCode"), max_length = 15)
state = models.CharField(("state"), max_length=5)
address = models.TextField(("Address"))
dealerId = models.IntegerField(("ids"), primary_key=True)
def __str__(self):
return self.dealersName
class DealershipListing(models.Model):
carID = models.IntegerField(("CarID"), primary_key=True)
price = models.IntegerField(('price'))
msrp = models.IntegerField(('msrp'))
mileage = models.IntegerField(('mileage'))
is_new = models.BooleanField(('isNew'))
model = models.CharField(("Models"), max_length= 255)
make = models.CharField(("Make"), max_length=255)
year = models.CharField(("Year"),max_length=4)
dealerID = models.ForeignKey(Dealer, models.CASCADE)
def __str__(self):
return self.year + " " + self.make + " " + self.model
So then it looks like your question is really How do I access data from a foreign key in a template?
The answer is refreshingly simple!
{{car.dealerID.address}}
On a side note, you might want to rename dealerID to dealer, django will handle the db column names how it sees fit, so while you might access the data with .dealer the db column would be named dealer_id by django automatically. Renaming the field also makes it more obvious that accessing it will give you a dealer and not its id.
calling with the model name is what I prefer to use
{{obj.related_table.field_name}}
I think this pattern may help you solve problem related to getting related field value

Is there any other way to avoid duplicate data while scraping and avoid storing the same data in database?

I have a simple model.
models.py
class Content(models.Model):
title = models.CharField(max_length = 300, unique = True)
category = models.CharField(max_length = 50)
def __str__(self):
return self.title
then I'm scraping the data from some sources and want to store in this table.
toi_r = requests.get("some source")
toi_soup = BeautifulSoup(toi_r.content, 'html5lib')
toi_headings = toi_soup.findAll("h2", {"class": "entry-title format-icon"})[0:9]
toi_category = toi_soup.findAll("a", {"class": ""})[0:9]
toi_news = [th.text for th in toi_headings]
toi_cat = [tr.text for tr in toi_category]
for th in toi_headings:
toi_news.append(th.text)
for tr in toi_category:
toi_cat.append(tr.text)
for title, category in zip(toi_news, toi_cat):
n = Content.objects.create(title=title, category=category)
So here, error is UNIQUE Constraint failed. So, If I remove the UNIQUE Constraint, then everything works but mulitple copies of data are stored as the page refreshes. Is there any other way to work with this?

Django-nonrel on Appengine

class BillList(models.Model):
username = models.ForeignKey(User)
billno = models.CharField(max_length=15)
class OrderDetails(models.Model):
billno = models.ForeignKey(BillList)
orderdetails = models.TextField()
User is the one within django.contrib.auth.models.
I need to retreive all billno of a particular user. How do I go about doing this simple query in Django-nonrel on Appengine?
If I do this:
iq = User.objects.filter(username = "name1")
BillList.objects.filter(username = iq)
Then I get an error: DatabaseError: Subqueries are not supported.
If I try this straight away BillList.objects.filter(username = "restaurant1"), then ValueError: invalid literal for long() with base 10: 'restaurant1'
I'm sure it must be possible to go about doing this simple query! Any workarounds?
The others are correct. But, there may be a fundamental problem here with your understanding of the ForeignKey. For example:
username = models.ForeignKey(User)
That's not really a "username" at all. It is a user object. More understandable would be something like:
user = models.ForeignKey(User)
The User object is what has the username property. So to get a person's username, you would use"
BillList.objects.get(billno = 12345).user.username
Then, your queries become:
iq = User.objects.get(username = "name1")
my_list = BillList.objects.all().filter(user = iq)
Or, more directly:
my_list = iq.billist_set.all()

How to filter django model by its objects in many-to-many field (exact match)?

I have this model in my code:
class Conversation(models.Model):
participants = models.ManyToManyField(User, related_name="message_participants")
and I need to filter this "Conversation" model objects by the "participants" many-to-many field.
meaning: I have for example 3 User objects, so I want to retrieve the only "Conversation" objects that has this 3 Users in it's "participants" field.
I tried doing this:
def get_exist_conv_or_none(sender,recipients):
conv = Conversation.objects.filter(participants=sender)
for rec in recipients:
conv = conv.filter(participants=rec)
where sender is a User object and "recipients" is a list of User objects.
it won't raise error but it gives me the wrong Object of Conversation.
Thanks.
edit:
A more recent try lead me to this:
def get_exist_conv_or_none(sender,recipients):
participants=recipients
participants.append(sender)
conv = Conversation.objects.filter(participants__in=participants)
return conv
which basically have the same problem. It yields Objects which has one or more of the "participants" on the list. but what Im looking for is exact match of the many-to-many object.
Meaning, an Object with the exact "Users" on it's many-to-many relation.
edit 2: My last attempt. still, won't work.
def get_exist_conv_or_none(sender,recipients):
recipients.append(sender)
recipients = list(set(recipients))
conv = Conversation.objects.annotate(count=Count('participants')).filter(participants=recipients[0])
for participant in recipients[1:]:
conv.filter(participants=participant)
conv.filter(count=len(recipients))
return conv
Ok so I found the answer:
In order to make an exact match I have to chain-filter the model and then make sure it has the exact number of arguments it needs to have, so that the many-to-many field will have in it all the objects needed and no more.
I will check for the objects number using annotation: ( https://docs.djangoproject.com/en/dev/topics/db/aggregation/ )
ended up with this code:
def get_exist_conv_or_none(recipients):
conv = Conversation.objects.annotate(count=Count('participants')).filter(participants=recipients[0])
for participant in recipients[1:]:
conv = conv.filter(participants=participant)
conv = conv.filter(count=len(recipients))
return conv
For fast search using database index, I use this code:
class YandexWordstatQueue(models.Model):
regions = models.ManyToManyField(YandexRegion)
regions_cached = models.CharField(max_length=10000, editable=False, db_index=True)
phrase = models.ForeignKey(SearchPhrase, db_index=True)
tstamp = models.DateTimeField(auto_now_add=True)
class YandexWordstatRecord(models.Model):
regions = models.ManyToManyField(YandexRegion)
regions_cached = models.CharField(max_length=10000, editable=False, db_index=True)
phrase = models.ForeignKey(SearchPhrase, db_index=True)
Shows = models.IntegerField()
date = models.DateField(auto_now_add=True)
#receiver(m2m_changed, sender=YandexWordstatRecord.regions.through)
#receiver(m2m_changed, sender=YandexWordstatQueue.regions.through)
def yandexwordstat_regions_changed(sender, **kwargs):
if kwargs.get('action') in ['post_add', 'post_remove']:
instance = kwargs.get('instance')
l = list(instance.regions.values_list('RegionID', flat=True))
l.sort()
instance.regions_cached = json.dumps(l)
instance.save()
This adds overhead when saving, but now I can perform fast filter with this snippet:
region_ids = [1, 2, 3] # or list(some_queryset.values_list(...))
region_ids.sort()
regions_cahed = json.dumps(region_ids)
YandexWordstatQueue.objects.filter(regions_cached=regions_cached)

jqgrid and django models

I have the following models
class Employee(Person):
job = model.Charfield(max_length=200)
class Address(models.Model):
street = models.CharField(max_length=200)
city = models.CharField(max_length=200)
class EmpAddress(Address):
date_occupied = models.DateField()
date_vacated = models.DateField()
employee = models.ForeignKey()
When I build a json data structure for an EmpAddress object using the django serialzer it does not include the inherited fields only the EmpAddress fields. I know the fields are available in the object in my view as I can print them but they are not built into the json structure.
Does anyone know how to overcome this?
Thanks
Andrew
Inheritance of Django models can get a little tricky. Unless you excplicitly require EmpAddress to be subclass of Address, you might just want to duplicate the fields and let duck typing handle the fact that you aren't following traditional object oriented design. E.g:
class Address(models.Model):
street = models.CharField(max_length=200)
city = models.CharField(max_length=200)
class EmpAddress(Address):
street = models.CharField(max_length=200)
city = models.CharField(max_length=200)
date_occupied = models.DateField()
date_vacated = models.DateField()
employee = models.ForeignKey()
Another shot in the dark you might try is to use jsonpickle (I'm one of the developers), which is "smarter" than the standard json module. The latest code has some great new features, thanks to davvid.
Take a look at: http://www.partisanpost.com/2009/10/django-jquery-jqgrid-example-one/1/ as a solution to your problem. The full serializer allows you to drill down into foreignkey relationships as far as you need to go. I wrote a tutorial example of how to use it to integrate django with JqGrid, which provides an example of just what you are faced with. Hope this helps.
John,
This is view code I am using along with the models is;
def address_grid(request):
employeeId = request.GET.get('employeeId')
if request.GET.get('sidx') == '':
order = 'date_occupied'
else:
order = request.GET.get('sidx')
if request.GET.get('sord') == 'asc':
sort_order = ''
else:
sort_order = '-'
order = sort_order + order
if request.GET.get('page'):
paginated = int(request.GET.get('page'))
else:
paginated = 1
items = int(request.GET.get('rows'))
addresses = EmpAddress.objects.filter(employee__id=employeeId)
for add in addresses:
log.write(add.city+'\n') # Field from address object
total = adresses.all().count()
if total % items > 0:
items_sum = 1
else:
items_sum = 0
pages = total / items + items_sum
if paginated > pages:
paginated = 1
addresses = addresses.order_by(order)[paginated-1)*items:paginated*items]
rows = serializers.serialize("json", addresses, indent=4,)
addresses = '{total:%(pages)s, page:%(page)s, records:%(total)s, rows:%(addresses)s' \
% {'pages':pages, 'page':paginated, 'total':total, 'addresses':rows}
log.write(rows+'\n') #json object no Address fields (city is not included)
#even it is present above
return HttpResonse(addresses, mimetype="application/json")
When I print the addresses objects after the
addresses = EmpAddress.objects.filter(employee__id=employeeId)
line I have all of the objects attributes (both the Address and EmpAddress fields).
But when I print the json object I only have the EmpAddress object attributes excluding the Address attributes.