Click on row in django-tables2 to take me to another table? - django

I basically want to click on a row or linked element and take me to another filtered table.
For instance, let's say I have a table of genres:
Romance
Horror
Comedy
I click on Romance, and then I want a list of all the romance books. How might I do this with django-tables2?
How do I get what the user clicked on in my django table?
I tried to use
table.py
class GenreTable(tables.Table):
genre = tables.LinkColumn('books_genre_table')
class Meta: ...
This doesn't work because I can't pass the data and filter it to make a table in the next view/html 'books_genre_table.html'
EDIT: I already have a detail page for genres that is different than this page that I want to create. Furthermore, I want to filter the data in a new way that does not need to be saved as a detail page with a 'pk'. I just want to have all of these go to one url.

Lets say you have a genre URL like this:
path('some_path/<int:pk>/', genre_book_view, name='books_genre_table')
and have a view like this(here I will be using reverse relation to fetch books from genre):
def genre_book(request, pk):
# will be using genre here to fetch all the books
genre = Genre.objects.get(pk=pk)
context = {
'books': genre.book_set.all() # using reverse relation to get the books
}
return render(request, 'some_template.html', context)
Then you can link your view like this:
class GenreTable(tables.Table):
genre = tables.LinkColumn('books_genre_table', args=[A('pk')])
class Meta:
...

Related

Django: Create Choices For Filter Based on Distinct Model Values

Objective: I want to have a ModelChoiceFilter rendered on the page where the options/choices for the user to select are the distinct values of a field in the model.
The app allows users to track the cities that they have visited. I want users to be able to filter the model on country and for the filter options to only be countries that are in the model.
I am using django-filters and do successfully have a MultipleChoiceFilter working where the choices work when hard-coded (either in the models.py or in the FilterForm class:
class cityFilter(django_filters.FilterSet):
continent = MultipleChoiceFilter(
choices=cityModel.continent_choices,
widget=forms.CheckboxSelectMultiple,
label='Continent')
class Meta:
model = cityModel
fields = ['city', 'country', 'continent']
One can also set the choices directly in the FilterSet class like this:
country = MultipleChoiceFilter(
choices=(('GB','United Kingdom'),('FR','France')),
widget=forms.CheckboxSelectMultiple,
label='Country'
)
This works okay for continents but I want to allow a filter for countries. I only want to expose to the user the distinct set of countries in the model (as opposed to hard coding every country).
I could do something like this to get all the distinct countries in the model:
country_choices = cityModel.objects.values('country').distinct()
But I'm not sure where this should be placed in the app to get queried on the page load, and would then need to take each value in the queryset and iterate to turn it into a 'choice' tuple.
Is there a better pattern/approach?
If you want dynamic choices and the choices data from Model, you can try to use queryset in the ModelMultipleChoiceFilter like this:
continent = ModelMultipleChoiceFilter(
queryset=cityModel.objects.values('country').distinct(),
widget=forms.CheckboxSelectMultiple,
label='Continent')

How do I get the results of a multiple choice field from Django?

I set up a model multiple choice field, where a user can select multiple choices. I want to be able to get the choices that a user selected when filling out the form. What can I call to get the results that the user picked? Also, how would I iterate over those results (what does it return)?
Here's the field:
CHOICES = MyMultipleModelChoiceField(queryset=MODEL.objects.all(), widget=forms.CheckboxSelectMultiple, required=False)
Thanks!
Your post is incomplete there is too little informations you can to the following.
Use CreateView to create a new instance and then grab your data from your db, it will look like :
class CategoryCreate(generic.CreateView):
form_class = your_form_class
model = your_model
def get_success_url(self):
return reverse_lazy('your_view')
And in your next view you will be able to grab the data from your model.

how to get a value of a field in django

I'm currently working on a django app like IMDB.com that have a Media ( contains tvshows and movies ) model and an Episode model with a one-to-many relationship between them to display these episodes at the TvShow page.
I managed to be able to show the episodes of a tvshow inside the page with:
def tvshow(request, tvshow_title):
tvshow = get_object_or_404(Media, title=tvshow_title)
episodes = Episode.objects.all().filter(is_published=True, tvshow=tvshow)
context = {
'tvshow': tvshow,
'episodes': episodes
}
return render(request, 'media/tvshow.html', context)
and this worked perfectly fine but I also needed to display episodes based on season and this got me kinda confused how do I know how many seasons does a tv show have when there's no field for it in the Media model, but the Episode model had a season_number field, so I tried to get to query the last episode of a tv show based on the season_number:
latest_episode = Episode.objects.order_by('-season_number').filter(is_published=True, tvshow=tvshow)[:1]
and I managed to indeed get the episode but I don't know now how to get what is the number of the season in it.
I tried
seasons = latest_episode.season_number
and
seasons = latest_episode['season_number']
and neither of them worked. please tell me if there's a better way to do it and if this way is good let me know how to get the season_number. :)
Using [:1] returns a QuerySet, which is basically a list, and not a model instance (think of it as returning [EPISODE] instead of just EPISODE. This means that you dont have access to the episode's season_number attribute.
Try this:
latest_episode = Episode.objects.order_by('-season_number').filter(is_published=True, tvshow=tvshow).first()
and then you should be able to use latest_episode.season_number

Django views/filters

I have just completed the Django tutorials, and while excited about learning more, I am by no means proficient. I guess you could say that I don't know enough to be dangerous at this point.
Let's say that I have a database of music. I have an Artist model, an Album model, a Genre model, and a Song model. What I would like to be able to do is display albums (or even artists) based on given filters; so my front-end would display a list of albums and provide a means to filter the list. A "Jazz" link, for instance, would only display Jazz albums. Simple enough.
I can think of a couple ways to accomplish this, but I would like to start out on the right foot...to begin forming "best practice" Django methods. One way I can think of would be to write views...such that /albums/jazz would only display jazz. Another way would be to write model-level methods that filter the albums. Here I get a little fuzzy on how I would actually implement such a filter, however.
Will someone please give me broad overview of how this task is best accomplished?
Assuming you know how to structure an app within a project (i.e. what the tutorial teaches) you can work along this example with example models.py, urls.py and views.py for your sample app myapp.
Example models.py:
class Genre(models.Model):
name = models.CharField(unique=True) # set name to be unique
...
class Album(models.Model):
genre = models.ForeignKey(Genre)
...
Example urls.py:
urlpatterns = patterns('',
...
url(
r'^albums/(?P<genre>[-\w]+)/$',
ListAlbumsByGenreView.as_view(), name='list_albums_by_genre_view'
),
...
)
Note the genre parameter as the only argument in the URL pattern.
Example views.py using ListView:
from django.shortcuts import get_object_or_404
from django.views.generic.list import ListView
from myapp.models import Album, Genre
class ListAlbumsByGenreView(ListView):
model = Album
def get_context_data(self, **kwargs):
context = super(ListAlbumsByGenreView, self).get_context_data(**kwargs)
# fetch the genre; if genre not found, an HTTP 404 is returned
genre = get_object_or_404(Genre, name=kwargs['genre'])
# filter the albums by genre
context['albums'] = Album.objects.filter(genre=genre)
return context
The above ListView puts albums in your HTML template's context; this contains the list of albums filtered by genre.
The individually imported functions used above are all beautifully documented in the Django docs.

Beginner Django Forms Question: Adding an Item to a User's Categories

I have in my models Item with a many-to-many connection with Categories, and Categories have a Foreign Key to User.
What I'm hitting a road block figuring out is how to create a view with the intent to import an Item object to one or more of a User's Categories.
In it's most basic implementation I would like the view to display only the list of Categories that the User owns, and have the view process the form so that the Item is added to the appropriate Categories.
I've been struggling trying to figure out how to start this, including how to pass a User's categories to the form.
Thanks.
in the form class (ItemForm) do this
def __init__(self,user,*args,**kwargs):
super(ItemForm,self).__init__(*args,**kwargs)
self.fields['categories'] = forms.ModelMultipleChoiceField(
queryset=Categories.objects.filter(user=user))
then in your view call the form with :
form = ItemForm(request.user)
or
form = ItemForm(request.user, request.POST)
this should get you started. hopefully you can work out what you need to do from there. your question didn't leave much else to go by.