How to render multiple objects using class based views - django

I try to render multiple objects using class based views but I get an error.
Here are my codes:
class AssociatedList(WizardRequiredMixin, TemplateView):
template_name = "profile/associated_accounts.html"
def get_context_data(self, **kwargs):
context = super(AssociatedList, self).get_context_data(**context)
all_envelopes = Envelope.objects.filter(
user=request.user).exclude_unallocate()
free_limit = account_limit(request, 15, all_envelopes)
facebook = FacebookProfile.user_profiles(request.user)
google = GoogleProfile.user_profiles(request.user)
twitter = TwitterProfile.user_profiles(request.user)
context.update = ({
'facebook': facebook,
'google': google,
'twitter': twitter,
'free_limit': free_limit,
})
return context
Error:
local variable 'context' referenced before assignment

I've always overridden get_context_data by calling super at the beginning of the function and then appending context -
def get_context_data(self, *args, **kwargs):
context = super(AssociatedList, self).get_context_data(*args, **kwargs)
all_envelopes = Envelope.objects.filter(
user=self.request.user).exclude_unallocate()
free_limit = account_limit(self.request, 15, all_envelopes),
facebook = FacebookProfile.user_profiles(self.request.user),
google = GoogleProfile.user_profiles(self.request.user),
twitter = TwitterProfile.user_profiles(self.request.user),
context.update({
'facebook': facebook,
'google': google,
'twitter': twitter,
'free_limit': free_limit,
})
return context
This is the pattern used in the docs here.
UPDATE
The error you've just added suggests an error with your class. It sounds like you need to define either a queryset attribute or a model attribute.
The ListView class that you're inheriting from requires you to either define the model that the View returns (ie YourModel.objects.all()). Or else the specific queryset to be returned (eg YourModel.objects.filter(your_field=some_variable)).

Because this is a ListView, you need to tell it what you are going to list with either a model or queryset. You don't want to use a ListView in this case since you are overriding get_context_data so you should probably use a TemplateView or something similar.

Try something like this:
class AssociatedList(WizardRequiredMixin, ListView):
template_name = "profile/associated_accounts.html"
model = Envelope
def get_queryset(self):
return Envelope.objects.filter(user=self.request.user).exclude_unallocate()
def get_context_data(self, **kwargs):
context = super(AssociatedList, self).get_context_data(**kwargs)
context.update({
'facebook': FacebookProfile.user_profiles(self.request.user),
'google': GoogleProfile.user_profiles(self.request.user),
'twitter': TwitterProfile.user_profiles(self.request.user),
'free_limit': account_limit(self.request, 15, context['envelope_list']),
})
return context
You don't need model having queryset, but it is good practice to define it.
In template use object_list or envelope_list instead of all_envelopes and you should be good to go.
P.S. http://ccbv.co.uk/ good source of knowledge about CBV.

Related

Django - Filtering Field In DetailView

Hi all,
I've been building a Django app that allows users to stream and download music. However, there is one issue that I'm having with the artists profile pages; I'm trying to request the songs by the artist only in a DetailView as I'm treating it like a blog system.
Is this possible in a DetailView? Or do I need to make a filter? I've been searching the web for days now and didn't really understand what I can do or how to get the specific data field from the model.
Any help or guidance would be highly appreciated!
class musicartist(DetailView):
model = MusicArtist
template_name = 'RS_MUSIC/artist.html'
# override context data
def get_context_data(self, *args, **kwargs):
context = super(musicartist, self).get_context_data(*args, **kwargs)
# add extra field
current_band = MusicItems.objects.all().filter(artist=MusicArtist.title)[:1]
context["songs"] = MusicItems.objects.filter(artist=MusicArtist.objects.all().filter(title=current_band)[:1])
return context
Managed to figure it out. Just needed the following code:
class musicartist(DetailView):
model = MusicArtist
template_name = 'RS_MUSIC/artist.html'
def get_context_data(self, **kwargs):
context = super(musicartist, self).get_context_data(**kwargs)
context_related = MusicItems.objects.filter(artist=self.object.title)
context['related'] = context_related
return context

How to add data to context object in DetailView?

I need to write a DetailView in Django. I achieved this functionality. However, I need to add some more data along with the context object. How will I achieve this.
My generic view is:
class AppDetailsView(generic.DetailView):
model = Application
template_name = 'appstore/pages/app.html'
context_object_name = 'app'
I need to add one more variable to the context object:
response = list_categories(storeId)
How about using get_context_data
class AppDetailsView(generic.DetailView):
model = Application
def get_context_data(self, **kwargs):
context = super(AppDetailsView, self).get_context_data(**kwargs)
context['categories'] = list_categories(storeId)
return context

Filter model based of context data using django filter

I have a detail view of a model that I want to display together with a list of products and Im trying to integrate django_filter within this view.
Error Message
TypeError at /collections/christmas/?category=mens,
get context data takes exactly 2 arguments (1 given)
Filter
class ProductFilter(django_filters.FilterSet):
class Meta:
model = Product
fields = ['categories']
Detail View
class collection_detail(DetailView):
model = Collection
def get_context_data(self, request, **kwargs):
context = super(collection_detail, self).get_context_data(**kwargs)
context['collection_list'] = ProductFilter(request.GET, queryset=Product.objects.filter(collection=self.object.id).filter(structure='parent'))
return context
How i intend it to work
The category filter is pre-defined in a list of links, so when the user clicks on a collection related to a specific category the url of the detail view would look like /collections/christmas/?category=mens .
What am I specifically doing wrong here? Is it possible to even do this?
You're missing *args in your overridden method.
class collection_detail(DetailView):
model = Collection
def get_context_data(self, *args, **kwargs):
context = super(collection_detail, self).get_context_data(*args, **kwargs)
context['collection_list'] = ProductFilter(self.request.GET, queryset=Product.objects.filter(collection=self.object.id).filter(structure='parent'))
return context

Django combine two fields data into a queryset

I have a model say Club where we have fields like:
manager = models.ForeignKey(Users, related_name="return_manager", on_delete=models.CASCADE)
members = models.ManyToManyField(Users, related_name="return_members", blank=True)
Now I want to create a drop down in a form where I can add both the manager and members to it. I tried making two requests for Club.objects.filter(pk=mypk).members.all() and Club.objects.filter(pk=mypk).manager. I tried chain function and using '| ' operator but none worked. I think the manager is a single User and not a queryset, that is what the main problem is. Any workarounds?
One possible way getting all of the information together involves modifying your form choices.
In your view you would need to pass the choices along as context to your form.
def my_view(request, club_pk):
context = {}
context.update({
"manager": Club.objects.get(pk=club_pk).manager,
"members": Club.objects.get(pk=club_pk).members.all()
}
form = MyForm(request.POST or None, request=request, context=context)
In your form, you would need to modify the __init__ method to update your choices like so:
class MyForm(forms.Form):
all_club_members = forms.ChoiceField('Manager + Members', required=True)
def __init__(self, *args, **kwargs):
self.context = kwargs.pop('context', None)
super(MyForm, self).__init__(*args, **kwargs)
manager_tuple = [(self.context['manager'].id, self.context['manager'].display_name)]
members_tuples = [(member.id, member.display_name) for member in self.context['members']
self.fields['all_club_members'].choices = manager_tuple + members_tuples
Try this:
manager = [Club.objects.filter(pk=mypk).manager]
members = Club.objects.filter(pk=mypk).members.all()
userlist = list(manager) + list(members)
return Users.objects.filter(pk__in=userlist)
Should create a queryset of all users

How do I get django url parameters from a view mixin?

Exactly what the title says. I have a mixin that needs to pull in the id of a model field in order to be useful. I assume the easy way to do that would be to pull it from the URL.
class StatsMixin(ContextMixin):
def get_stats_list(self, **kwargs):
# the ??? is the problem.
return Stats.objects.filter(id=???).select_related('url')
def get_context_data(self, **kwargs):
kwargs['stats'] = self.get_stats_list()[0]
print kwargs
return super(StatsMixin, self).get_context_data(**kwargs)
Here's the view implementation for reference.
class ResourceDetail(generic.DetailView, StatsMixin):
model = Submissions
template_name = 'url_list.html'
queryset = Rating.objects.all()
queryset = queryset.select_related('url')
You can access URL parameters in Django by using, self.args and self.kwargs.