Django retrieve all comments for a user - django

I'm using django-profiles and django.contrib.comments and I am trying to display all comments for a particular user in their profile.
This is using the default profile_detail view from django-profiles.
I've tried these two approaches and neither is returning any objects (although objects matching this query do exist):
{% for comment in profile.user.comment_set.all %}
and
{% for comment in profile.user.user_comments.all %}
In the source code for django.contrib.comments, the foreign key to user in the Comment model has the following related name:
user = models.ForeignKey(User, verbose_name=_('user'),
blank=True, null=True, related_name="%(class)s_comments")
Comments also has a custom manager:
# Manager
objects = CommentManager()
Which is defined as:
class CommentManager(models.Manager):
def in_moderation(self):
"""
QuerySet for all comments currently in the moderation queue.
"""
return self.get_query_set().filter(is_public=False, is_removed=False)
def for_model(self, model):
"""
QuerySet for all comments for a particular model (either an instance or
a class).
"""
ct = ContentType.objects.get_for_model(model)
qs = self.get_query_set().filter(content_type=ct)
if isinstance(model, models.Model):
qs = qs.filter(object_pk=force_unicode(model._get_pk_val()))
return qs
Is the custom manager causing the .all query not to return anything? Am I accessing the reverse relation correctly? Any help would be appreciated.

The related name is defined so the default name_set will not work. The purpose of related_name is to override that default reverse manager name.
user = models.ForeignKey(User, verbose_name=_('user'),
blank=True, null=True, related_name="%(class)s_comments")
So use this:
user.comment_comments.all()

Related

Django ManyToMany relationship, filter options of modelmultiplechoicefield

I am currently rewriting a web app that is utilizing a hierarchy of relationships which is making it extremely painful to create a reliable work flow for the creation of objects. The current set up is as follows:
Customer Hierarchy:
Organization -> Location -> Room
Contacts can belong to one or many of these entries at any level of the hierarchy. Ex Jim can be assigned to Organization and location.
With this I need to filter the django many to many field that is populated with any contact that doesn't belong anywhere OR belongs to a parent or child level of the customer hierarchy.
I have attempted inline formsets which fails on the many to many model as well as limit_choices_to={'Organization':_get_self_pk} . This works but doesn't allow for the use of django admin style on the fly creation of contacts. I have also attempted to use a queryset in the init function for create, but my form has a nested inline formset that doesn't allow me to use the self.field['contact'] to inject the queryset. (Key Error, contacts doesn't exist as a field)
Models.py
class Organization(AbstractExclusions, AbstractManyToManyCommonInfo, AbstractCommonInfo, AbstractOrganizationLocationCommonInfo, AbstractAcvitivyInfo):
....
contact = models.ManyToManyField('Contact', blank=True)
class Location(AbstractManyToManyCommonInfo, AbstractCommonInfo, AbstractOrganizationLocationCommonInfo, AbstractLocationRoomCommonInfo, AbstractAcvitivyInfo, AbstractExclusions):
....
contact = models.ManyToManyField('Contact', blank=True)
class Room(AbstractManyToManyCommonInfo, AbstractCommonInfo, AbstractLocationRoomCommonInfo, AbstractAcvitivyInfo, AbstractExclusions):
....
contact = models.ManyToManyField('Contact', blank=True)
class Contact(AbstractUserInfo):
phone_number = PhoneNumberField(verbose_name=_('Phone Number'))
is_user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.CASCADE, verbose_name=_('Link To Authenticated User'),)
role = models.ForeignKey(refModels.Role, verbose_name=_("Role"), on_delete=models.CASCADE, null=True, blank=True)
This question was answered by creating a special init function as shown below:
def __init__(self, *args, **kwargs):
super(OrganizationForm, self).__init__(*args, **kwargs)
if 'initial' in kwargs:
try:
self.fields['contact'].queryset = (custModels.Contact.objects.filter(Q(organization = None) | Q(organization = self.instance.id)))
except:
pass

foreignkey backwards manager not working django

This seems simple.. I have a Restaurant model and Recipe model, all I want is to be able to look up all the Recipes by a certain Restaurant. I am using the backwards manager FOO_set and cant seem to make it work:
models.py
class Restaurant(models.Model):
restaurant_user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='restaurant')
class Recipe(models.Model):
restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE, related_name='recipe')
views.py
def dashboard(request):
user = request.user
try:
user.restaurant
recipe_list = user.restaurant.recipe_set
return render(request, 'usermanage/dashboard_restaurant.html',{'recipe_list':recipe_list})
When i run this i get an exception in the dashboard view. Looking at my database the user.restaurant object has recipes associated with it. If i just do recipe_list = user.restaurant it returns the restaurant object. Just when I add recipe_set it fails. Also tried recipe_set.all and all(). I have migrated everything. Django 1.11
you set related_name so you need to use it:
replace:
recipe_list = user.restaurant.recipe_set
# ^^^^^
to
recipe_list = user.restaurant.recipe.all()
# ^^^^^^

How do I use a ModelManager on a Django ManyToMany through field?

Let's say I have the following models:
class Poll(model):
title = models.CharField()
class Option(model):
title = models.CharField()
polls = models.ManyToManyField(
Poll,
through='PollOption',
null=True,
blank=True,
related_name='options'
)
class PollOptionManager(models.Manager):
use_for_related_fields = True
def get_queryset(self):
return super(PollOptionManager, self).get_queryset().filter(
is_active=True
)
class PollOption(model):
poll = ForeignKey(Poll)
option = ForeignKey(Option)
is_active = BooleanField(default=True)
objects = PollOptionManager()
When I try to query Poll.options.all() I'm still getting Option instances for which PollOption.is_active is False. How can I get my model manager to appropriately filter my ManyToMany relationship based on a flag on the through field?
The problem is that the through model's (related) manager is never actually used in your scenario. In order to utilize the custom manager, you have to explicitly use it, e.g.:
class Poll(models.Model):
#property
def active_options(self):
return Option.objects.filter(id__in=self.polloption_set.values_list('option'))
Here, polloption_set filters out inactive options as intended. This, however, makes the manager kind of pointless because you can just as well put the extra filter in the custom property.

Django, best practice for associating model with author and how to do it

I'm making a django cms of sorts, and have got to the stage where I'm linking my model to the user id who created it. I only want to do this once, on subsequent updates the author field shouldn't change.
My model is blog. I presume I have to override the save() method, but I'm not sure what is best practice, or where I should be overiding the save method, ie in admin.py, in models.py or even maybe in forms.py?
from common.models import myUser #inherits from AbstractUser
class Blog:
title = models.CharField(max_length="100", null=True, blank=True)
author = models.ForeignKey(myUser, editable=False)
last_edit_by = models.ForeignKey(myUser, editable=False)
def save():
if self.author is None:
self.author = #how to get user id?
self.last_edit_by = ##how to get user id?
super(Features, self).save(*args, **kwargs)
else:
self.last_edit_by = #how to get user id?
Thanks in advance,
I think the best place to associate a user with some model data is in the views.
In your specific example, you can use a model form for blog.
class BlogForm(forms.ModelForm):
class Meta:
fields = ['title', 'last_edited_by']
Do not include author in the form if you do not want to do any validation based on value of author. In case you have to do any validation based on author you will have the include it the form fields and also add the author id value in the form post data.
Now in your view you can use this BlogForm for creating a blog instance with:
....
form = BlogForm(data)
if form.is_valid():
blog = form.save(commit=False)
blog.author = request.user
blog.save()
....
Now you have a blog with author.
Even if you really want to override the save method you can pass the author to the save method of Blog and associate it in the save method.
If you choose to include author in the form fields, to add the value of author in the post data you will have to make copy of the post data and then insert the value of author in the copied post data.

Filter products by attribute

I'm working on an eshop with Satchmo framework.
Does anyone know what steps should i follow in order to filter products according to a custom attribute(type of material) in order to present the products that have the same kind of material in a page(material.html)?
Should i make a material_view function
Should i override get_absolute_url function?
If you want to do this without touching the core code, I would make a local app localsite/product and in models.py:
class Material(models.Model):
product = models.ManyToManyField(Product, blank=True, null=True)
name = models.CharField(_("Name"), max_length=30)
slug = models.SlugField(_("Slug"), help_text=_("Used for URLs, auto-generated from name if blank"), blank=True, unique=True)
description = models.TextField(_("Description"), blank=True, help_text="Optional")
Add this new app to your admin, and to additionally make them available from the product page, add them as inline:
# if you have lots of products, use the nice horizontal filter from django's admin
class MaterialAdmin(admin.ModelAdmin):
filter_horizontal = ('product',)
class Material_Inline(admin.TabularInline):
model = Material.product.through
extra = 1
admin.site.register(Material, MaterialAdmin)
# Add material to the inlines (needs: from product.admin import Product, ProductOptions)
ProductOptions.inlines.append(Material_Inline)
admin.site.unregister(Product)
admin.site.register(Product, ProductOptions)
Then you can adapt your views/urls:
# urls.py
url(r'^material-list/([\w-]+)/$', material_list, {}, name="material_list"),
# view.py
def material_list(request, slug):
products = Product.objects.filter(material__slug='slug')
return render_to_response('localsite/material/list.html', {'products':products}, context_instance=RequestContext(request))
When you say "custom attribute" do you mean that you have modified the product.models.Product code to add another field?
If that is the case you'll probably want to create a custom view.
If your Product code is something like...
class Product(models.Model):
...
matieral_type = models.CharField(max_length=128)
...
...then you can build a view like this...
def material(request,material_type):
prods = Product.objects.filter(material_type=material_type)
return render_to_response('material.html',{'products',prods},RequestContext(request))