Cannot retrieve specific data from django? - python

I'm trying to create a simple page containing 1 video and as many comments as it has and each comment replies
I basically created three models, one for Video, one for comment and one for reply. then I tried to retrieve the data in the view file.
I successfully retrieved video and comments but failed to retrieve replies of each comment.
I'm using django 1.10.4
models.py
class Video(models.Model):
title = models.CharField(max_length=120)
embed_code = models.CharField(max_length=500)
slug = models.SlugField(null=True, blank=True)
category = models.ForeignKey("Category", null=True)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
active = models.BooleanField(default=True)
featured = models.BooleanField(default=False)
free_preview = models.BooleanField(default=False)
share_message = models.CharField(max_length=150, default=default_share_message)
objects = models.Manager()
# activemodel = ActiveModel()
featuresandactive = Features()
class Meta:
unique_together = ('slug', 'category')
def __str__(self):
return self.title
def get_absolute_url(self):
try:
return reverse('video_detail', kwargs={'vid_slug':self.slug, 'cat_slug':self.category.slug})
except:
return "/"
class Comment(models.Model):
user = models.ForeignKey(MyUser)
path = models.CharField(max_length=350)
video = models.ForeignKey(Video, null=True, blank=True)
text = models.TextField()
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
Timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
active = models.BooleanField(default=True)
objects = CommentManager()
def __str__(self):
return self.text
class Reply(models.Model):
user = models.ForeignKey(MyUser)
comment = models.ForeignKey(Comment,null=True, blank=True)
text = models.TextField()
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
Timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
active = models.BooleanField(default=True)
objects = ReplyManager()
def __str__(self):
return self.text
views.py
def video_detail(request, cat_slug, vid_slug):
cat = Category.objects.get(slug=cat_slug)
comments = Comment.objects.filter(video=obj)
replys = Reply.objects.filter(comment=comments)
context = {
"cat": cat,
"obj":obj,
"comments":comments,
"replys":replys,
}
return render(request, 'video_detail.html', context)
this is another view.py
I tried this also but didn't work
def video_detail(request, cat_slug, vid_slug):
cat = Category.objects.get(slug=cat_slug)
obj = Video.objects.get(slug=vid_slug)
comments = obj.comment_set.all()
replys = comments.reply_set.all()
context = {
"cat": cat,
"obj":obj,
"comments":comments,
"replys":replys
}
return render(request, 'video_detail.html', context)

When you do this:
comments = Comment.objects.filter(video=obj)
'comments' contains a QuerySet. What you want to do next is ask for every Reply with a comment that's on that QuerySet, instead of comparing using '=':
replies = Reply.objects.filter(comment__in=comments)
relevant documentation: https://docs.djangoproject.com/en/dev/ref/models/querysets/#in
edit: changed it to 'replies' instead of 'replys'
edit2: added docs link

Related

blog objects need to have a primary key value before you can access their tags

i am trying to create a blog by the admin panell. but i am not able to save. Can you please help.
Model.py
class blog(models.Model):
author = models.ForeignKey(User, null=True, on_delete=models.CASCADE)
city_id = models.AutoField(primary_key=True)
blog_title=models.CharField(max_length=200)
created_at = models.DateTimeField(auto_now_add=True)
slug = models.CharField(max_length=500, blank=True)
tags = TaggableManager()
blog_category_name=models.ForeignKey(blog_category,on_delete=models.CASCADE,null=True,blank=True)
blog_sub_category_name=models.ForeignKey(blog_sub_category,on_delete=models.CASCADE,null=True,blank=True)
written_by = models.CharField(max_length=200, default='sandeep')
image_banner= models.ImageField(upload_to='image_banner')
medium_thumbnail = models.ImageField(upload_to='medium_thumbnail')
content = RichTextField() # RichTextField is used for paragraphs
is_authentic=models.BooleanField(default=False)
class Meta: # Plurizing the class name explicitly
verbose_name_plural = 'blog'
def __str__(self): # Dundar Method
return self.blog_title
def save(self, *args, **kwargs): # Saving Modefied Changes
if not self.slug:
self.slug = slugify(self.blog_title)
view.py
def tags(request,tags):
blogs = blog.objects.filter(
Q(blog_title__icontains = tags.replace('-',' ')) |
Q(content__icontains = tags.replace('-',' '))
)
print(tags)
return render(request, 'services/blog-with-sidebar.html',
{'blogs': blogs,'media_url':settings.MEDIA_URL})
For some reason when I'm trying to save the tags and the data I'm getting this error:

How can I reach second level natural keys on django query?

I have this models on django with natural_keys functions declared.
class Comments(models.Model):
profile = models.ForeignKey('Profiles', models.DO_NOTHING)
book = models.ForeignKey(Books, models.DO_NOTHING)
date = models.DateTimeField()
text = models.TextField()
class Meta:
managed = False
db_table = 'comments'
class Profiles(models.Model):
alias = models.CharField(max_length=40)
mail = models.CharField(max_length=255)
mainimg = models.ForeignKey(Multimedia, models.DO_NOTHING)
birthdate = models.DateTimeField(blank=True, null=True)
country = models.CharField(max_length=30, blank=True, null=True)
password = models.CharField(max_length=255)
terms = models.IntegerField(blank=True, null=True)
device_token = models.CharField(max_length=500)
def natural_key(self):
return (self.pk, self.alias, self.country, self.mainimg)
class Meta:
managed = False
db_table = 'profiles'
class Multimedia(models.Model):
url = models.CharField(max_length=255)
title = models.CharField(max_length=100)
alt = models.CharField(max_length=150, blank=True, null=True)
description = models.CharField(max_length=150, blank=True, null=True)
mytype = models.CharField(max_length=20, blank=True, null=True)
extension = models.CharField(max_length=6, blank=True, null=True)
def natural_key(self):
return (self.pk, self.url)
class Meta:
managed = False
db_table = 'multimedia'
When I do a get comments query, I want a full response with the comment details, some book details, and profile details (including the picture). Everything goes fine except when I want the profile mainimg being serialized with natural keys.
The error response is
is not JSON serializable
when executing this:
def getcomments(request):
#Book get all comments - returns all comments on a book.
profilelogged = validtoken(request.META['HTTP_MYAUTH'])
if not profilelogged:
return HttpResponse('Unauthorized', status=401)
else:
index = request.GET.get('id', 0)
bookselected = Books.objects.filter(pk=index).first()
comments = list(Comments.objects.filter(book=bookselected).order_by('-date').all())
books_json = serializers.serialize('json', comments, use_natural_foreign_keys=True)
return HttpResponse(books_json, content_type='application/json')
Anyway I can get multimedia url on comment query on same response object serialized?
Thanks.
You are trying to convert ForeignKey object into JSON object which gives error as ForeignKey contains serialized data,
So you have to use safe parameter to convert your data into JSON.
return HttpResponse(books_json, content_type='application/json', safe=False)
if it doesn't work! Try this:
return HttpResponse(books_json, safe=False)
Otherwise you can always user JsonResponse as it is safer to user for propagation of JSON objects.
P.S:
Why your Profile ForeignKey in first Model is in quotes? Is it on purpose?
Thanks everyone.
I have reached what i want adding to the Profiles model natural_key function the Multimedia fields I want to use, insted of the full Multimedia model I do not need.
class Profiles(models.Model):
alias = models.CharField(max_length=40)
mail = models.CharField(max_length=255)
mainimg = models.ForeignKey(Multimedia, models.DO_NOTHING)
birthdate = models.DateTimeField(blank=True, null=True)
country = models.CharField(max_length=30, blank=True, null=True)
password = models.CharField(max_length=255)
terms = models.IntegerField(blank=True, null=True)
device_token = models.CharField(max_length=500)
def natural_key(self):
return (self.pk, self.alias, self.country, self.mainimg.pk, self.mainimg.url)
class Meta:
managed = False
db_table = 'profiles'
And now, the reponse is what I wanted.

Save a many to many object inside a django model?

I am still learning to use Django and so I am a bit unclear on something.
I have a product model and category model. A product can lie in multiple categories and multiple categories can have the same product.
So, its a many to many relationship. Now, I want to allow the user to select multiple categories from the html and then I want to save the categories and link them to the category object in my product model. I am completely lost about it.
One way would be to use Modelform but I dont want to go that way. Is there any other way I can accomplish this?
models.py:
class Category(models.Model):
name = models.CharField(max_length=50)
slug = models.SlugField(max_length=50, unique=True,
help_text='Unique value for product page URL, created from name.')
description = models.TextField()
is_active = models.BooleanField(default=True)
meta_keywords = models.CharField("Meta Keywords", max_length=255,
help_text='Comma-delimited set of SEO keywords for meta tag')
meta_description = models.CharField("Meta Description", max_length=255,
help_text='Content for description meta tag')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('catalog:categories', kwargs={'category_slug': self.slug})
class Meta:
ordering = ['-created_at']
verbose_name_plural = 'Categories'
class Product(models.Model):
name = models.CharField(max_length=255, unique=True)
slug = models.SlugField(max_length=255, unique=True,
help_text='Unique value for product page URL, created from name.')
brand = models.CharField(max_length=50)
sku = models.CharField(max_length=50)
price = models.DecimalField(max_digits=9, decimal_places=2)
old_price = models.DecimalField(max_digits=9, decimal_places=2, blank=True, default=0.00)
thumbnail = models.FileField(upload_to='static/images/products/thumbnails')
imageurls = models.CharField(max_length=1000)
is_active = models.BooleanField(default=True)
is_bestseller = models.BooleanField(default=False)
is_featured = models.BooleanField(default=False)
quantity = models.IntegerField()
description = models.TextField()
meta_keywords = models.CharField(max_length=255, help_text='Comma-delimited set of SEO keywords for meta tag')
meta_description = models.CharField(max_length=255, help_text='Content for description meta tag')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
categories = models.ManyToManyField(Category)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('catalog:products', kwargs={'product_slug': self.slug})
def sale_price(self):
if self.old_price > self.price:
return self.price
else:
return None
class Meta:
ordering = ['-created_at']
part of views.py:
if request.method =='POST':
print ('entered')
name = request.POST['name']
brand = request.POST['brand']
sku = request.POST['sku']
price = request.POST['price']
quantity = request.POST['quantity']
description = request.POST['description']
imageurls = request.POST['urls']
print('imageurls',imageurls)
categorylist = request.POST['categories']
print('categorylist',categorylist)
categories = re.findall(r"[\w']+", categorylist)
print categories
imageurls = imageurls.split('~')
print('iageurls',imageurls)
for x in categories:
categoryobj = Category.objects.filter(name=x).values()
print ('categoryobj',categoryobj)
# Product.objects.create(name=name,sku=sku,brand=brand,price=price,quantity=quantity,description=description,imageurls=imageurls,categories=categoryobj)
return HttpResponse('success')
Try to save the above way gives me error.
product=Product.objects.create(name=name,sku=sku,brand=brand,price=price,quantity=quantity,description=description,imageurls=imageurls)
category_queryset = []
for x in categories:
category = Category.objects.filter(name=x).first()
category_queryset.append(category)
product.categories.set(category_queryset)

Serializer field named incorrectly

I'm attempting to present some serialized data, and am getting a AttributeError when attempting to get a value for field name.
models.py:
class Resource(models.Model):
"""Initial representation of a resource."""
# ID from fixture resources, for internal dedupe
internal_id = models.CharField(max_length=20, null=True, blank=True)
name = models.CharField(max_length=200)
description = models.TextField(null=True, blank=True)
categories = models.ManyToManyField("Category")
neighborhoods = models.ManyToManyField("Neighborhood")
email_contact = models.EmailField(null=True, blank=True)
pdf = models.ManyToManyField("PDF")
phone = models.CharField(max_length=200, blank=True, null=True)
website = models.URLField(max_length=200, blank=True, null=True)
# address
street_address = models.CharField(max_length=400, null=True, blank=True)
city = models.CharField(max_length=100, null=True, blank=True)
state = models.CharField(max_length=10, null=True, blank=True)
latitude = models.FloatField(null=True, blank=True)
longitude = models.FloatField(null=True, blank=True)
zip_code = models.CharField(max_length=10, null=True, blank=True)
# meta
created_at = models.DateTimeField(auto_now_add=True)
modified_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
def __unicode__(self):
return u'{}'.format(self.name)
#property
def categories_str(self):
return [str(t) for t in self.categories.all()]
#property
def neighborhoods_str(self):
return [str(t) for t in self.neighborhoods.all() if t] or ["Houston"]
#property
def bookmark(self):
"""This is here to make it easier to serialize a standard resource."""
return getattr(self, "_bookmark", None)
#bookmark.setter
def bookmark(self, bookmark):
self._bookmark = bookmark
def indexing(self):
safe_zip = str(self.zip_code or "")
safe_neighborhood = [n for n in self.neighborhoods.all() if n] or ["Houston"]
obj = ResourceDoc(
meta={"id": self.id},
name=self.name,
resource_suggest=self.name,
email_contact=self.email_contact,
phone=self.phone,
description=self.description,
website=self.website,
categories=self.categories_str,
street_address=self.street_address,
city=self.city,
state=self.state,
zip_code=safe_zip,
neighborhoods=self.neighborhoods_str,
# TODO default to Houston for now but need a way to handle case where we don't know neighborhood or zip code
location_suggest=[str(attr) for attr in chain([safe_zip], safe_neighborhood) if attr],
created_at=self.created_at,
modified_at=self.modified_at,
)
if self.latitude and self.longitude:
obj.geo_coords = {
"lat": str(self.latitude),
"lon": str(self.longitude),
}
obj.save(index="welnity_production_2")
return obj.to_dict(include_meta=True)
serializers.py:
class ResourceSerializer(serializers.ModelSerializer):
bookmark = BookmarkMetaSerializer(read_only=True)
notes = PrivateNoteSerializer(read_only=True, many=True)
categories = CategorySerializer(read_only=True, many=True)
neighborhoods = NeighborhoodSerializer(read_only=True, many=True)
class Meta:
model = Resource
fields = '__all__'
view.py:
class BookmarkGroupView(View):
def get(self, request, *args, **kwargs):
# resources = Resource.objects.filter(bookmarks__user=request.user)
# resources = get_enriched_resources(request.user, resources)
group = BookmarkGroup.objects.get(name='food')
resources = group.bookmarks.all()
serialized = ResourceSerializer(resources, many=True)
context = {
"component": "groups.js",
"props": {
"resources": JSONRenderer().render(serialized.data)
}
}
return render(request, "groups.html", context)
the error is
Got AttributeError when attempting to get a value for field `name` on serializer `ResourceSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `Bookmark` instance.
Original exception text was: 'Bookmark' object has no attribute 'name'.
any help or direction would be much appreciated!
You are giving your ResourceSerializer the wrong model instances.
resources = group.bookmarks.all()
serialized = ResourceSerializer(resources, many=True)
Here you are telling your serializer to use group.bookmarks.all() as data source which are instances of Bookmark, not Resource.

Customising tags in Django to filter posts in Post model

Quick question - I'm not sure what would be the correct way to handle this. Essentially I wish to define a custom tag which handles some logic then returns all posts of model Post which has the is_featured field set to True. I have tried a number of avenues to get this working, but none have worked. My last coherant "guess" was the following:
templatetags/blog_tags.py:
#register.inclusion_tag('blog/post/featured_posts.html')
def show_featured_posts(count=4):
"""Return 4 of the most recent posts (of model: 'Post') that has the variable is_featured set to True."""
if Post.is_featured:
featured_posts = Post.published.order_by('-publish')[:count]
return { 'featured_posts': featured_posts}
models.py (useful bits):
class PublishedManager(models.Manager):
def get_queryset(self):
return super(PublishedManager, self).get_queryset().filter(status='published')
class Post(models.Model):
STATUS_CHOICES = (
('draft', 'Draft'),
('published', 'Published'),
)
POST_TYPES = (
('news', 'News'),
('feature', 'Feature'),
('review', 'Review'),
)
title = models.CharField(max_length=250)
slug = models.SlugField(max_length=250, unique_for_date='publish')
author = models.ForeignKey(UserProfile, related_name='blog_posts')
body = models.TextField()
lead_in = models.CharField(max_length=500, default='')
#These next items shall contain our development information for game reviews - this is much like the lead_in:
platform = models.CharField(max_length=1000, default='')
publisher = models.CharField(max_length=1000, default='')
developer = models.CharField(max_length=1000, default='')
release = models.DateTimeField(default=timezone.now)
is_featured = models.BooleanField(default=False)
#Out blog layout dictates each featurette has up to three scrolling images associated to it:
image_scroll_1 = models.ImageField(storage=site_media_upload_location, null=True, blank=True)
image_scroll_2 = models.ImageField(storage=site_media_upload_location, null=True, blank=True)
image_scroll_3 = models.ImageField(storage=site_media_upload_location, null=True, blank=True)
type = models.CharField(max_length=10,choices=POST_TYPES,default='review')
publish = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=10,choices=STATUS_CHOICES,default='draft')
rating = models.PositiveSmallIntegerField(default=10)
wrap_header = models.CharField(max_length=250, default='')
wrap_up = models.TextField(default='')
disclaimer = models.TextField(default='')
objects = models.Manager()
published = PublishedManager()
tags = TaggableManager()
class Meta:
ordering = ('-publish',)
def __str__(self):
"""Return the state title of the post"""
return self.title
def get_absolute_url(self):
"""Get absolute_url path specific to this post."""
return reverse('blog:post_detail', args = [self.publish.year, self.publish.strftime('%m'), self.publish.strftime('%d'), self.slug])
def get_image(self):
"""Get upload_to path specific to this photo."""
return self.image.url
That is everything I think I need to include - I have the featured_posts.html template all ready to go so I don't think the issue lies with that. It's purely in the blog_tags.py file.
replace the following code in blog_tags.py
if Post.is_featured:
featured_posts = Post.published.order_by('-publish')[:count]
to
featured_posts = Post.published.filter(is_featured=True).order_by('-publish')[:count]

Categories