Viewing subset of objects in Django, Views, URLs, Models - django

I know this is a very basic concept in Django, and I have tried the tutorial but it is not working. I am working on a comic book database with the models set like this (at least, a sample of two of the models):
Class Title(models.Model):
title = models.CharField(max_length=256)
vol = models.IntegerField("Vol.")
slug = models.SlugField(blank=True, null=True)
#desc = models.CharField(max_length=256)
class Meta:
ordering = ['title']
def get_absolute_url(self):
return "/comics2/title/%s" % self.slug
def __unicode__(self):
return self.title
class Issue(models.Model):
title = models.ForeignKey(Title)
number = models.IntegerField(help_text="Enter the number only. Do not include the hashtag.")
writer = models.ManyToManyField(Creator)
What I am trying to do is create a page that shows a list of all the issues within that Title.
But, I have it setup in the views like this:
class AstonishingXMenIssueListView(ListView):
context_object_name = "astonishing_list"
queryset = Issue.objects.filter(title__title="Astonishing X-Men").order_by("number")
template_name = "comics2/astonishing_list.html"
My urls.py look like this:
(r'^comics2/title/(?P<title_slug>[-\w]+)/$', AstonishingXMenIssueListView.as_view(
)),
Of course, going to /uncanny-xmen-v1/ shows the same thing as the Astonishing link above.
Obviously, this is not a practical way to list issues by title for future issues and titles, so I need it setup so that I don't have to individually do this. Now, I have tried following the Django generic views tutorial, but I got an index tuple error.
I've tried this, but it doesn't work. This is what gets me the index tuple error.
class IssuesByTitleView(ListView):
context_object_name = "issues_by_title_list"
template_name = "comics2/issues_by_title.html",
def get_queryset(self):
title = get_object_or_404(Title, title__iexact=self.args[0])
return Issue.objects.filter(title=title)
Any ideas? And can someone please reply in baby-language, as I am new to Django and Python, so simply telling me to look at the Tutorial again isn't going to help. So, maybe writing out the code would help! Thanks!

Generally, your IssueByTitleView is the right way to do it. But as you use named groups in your URL regex (the (?P<title_slug>[-\w]+) part of your URL), you have to access the URL parameters through self.kwargs instead of self.args. Also, you have to filter on the slug field, not the title field:
title = get_object_or_404(Title, slug=self.kwargs['title_slug'])

Related

Django. Rest framework. How to generate the same tags?

Digging out the features of Django Rest Framework, I constantly come across difficulties. Here it is now. I have photos, each photo has a separate field (photo_1, photo_2, photo_3, etc). These photos need to be uploaded to the same tags, like this:
<image>photo_1_url</image>
<image>photo_2_url</image>
<image>photo_3_url</image>
My models.py:
photo_1 = models.ImageField(upload_to=image, blank=True)
photo_2 = models.ImageField(upload_to=image, blank=True)
photo_3 = models.ImageField(upload_to=image, blank=True)
My views.py:
class SerializerImage(serializers.ModelSerializer):
class Meta:
model = kv
fields = ['photo_1', 'photo_2', 'photo_3']
In xml I get the following fields and this is wrong:
<photo_1></photo_1>
<photo_2></photo_2>
<photo_3></photo_3>
I need to place all the photos under the tag <image>.
Help advice! How to make all images under one tag. I tried through self.fields.update. Tag photo_1 changes to an image, but this can only be done once. Two tags with the same name are not displayed.
Thank!
UPDATE:
Supplement for Sreeram.
After your advice on the output, I get the following result:
<example_field>
<image>photo_1_url</image>
<image>photo_2_url</image>
<image>photo_3_url</image>
</example_field>
My expected result is independent <image> tags, without nesting. Like this:
<image>photo_1_url</image>
<image>photo_2_url</image>
<image>photo_3_url</image>
Use SerializerMethodField
from rest_framework import serializers
class SerializerImage(serializers.ModelSerializer):
example_field = serializers.SerializerMethodField()
class Meta:
model = kv
fields = ['example_field']
def get_example_field(self, obj):
#do your queries, edits here.
string = f'<image>{obj.photo_1},{obj.photo_2},{obj.photo_3}</image>'
return string

Django url patterns for two related models

I have two models (School and Student) with one to many relationship.
my models.py are set as follows:
class School(models.Model):
name = models.CharField(max_length=256)
principal = models.CharField(max_length=256)
location = models.CharField(max_length=256)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse("basic_app:school_detail",kwargs={'pk':self.pk})
class Student(models.Model):
name = models.CharField(max_length=256)
age = models.PositiveIntegerField()
school = models.ForeignKey(School,related_name='students',on_delete=models.CASCADE,default=None)
and the urls.py file will have the following:
urlpatterns = [
url(r'^$',views.SchoolListView.as_view(),name='school_list'),
url(r'^(?P<pk>\d+)/$',views.SchoolDetailView.as_view(),name='school_detail'),
url(r'^create/$',views.SchoolCreateView.as_view(),name='school_create'),
url(r'^update/(?P<pk>\d+)/$',views.SchoolUpdateView.as_view(),name='school_update'),
url(r'^delete/(?P<pk>\d+)/$',views.SchoolDeleteView.as_view(),name='school_delete'),
my question is I want to add to the urlpatterns list more urls for students:something like
#url(r'^$',views.StudentListView.as_view(),name='student_list'),
# url(r'^(?P<pk>\d+)/$',views.StudentDetailView.as_view(),name='student_detail'),
# url(r'^create/$',views.StudentCreateView.as_view(),name='student_create'),
# url(r'^update/(?P<pk>\d+)/$',views.StudentUpdateView.as_view(),name='student_update'),
# url(r'^delete/(?P<pk>\d+)/$',views.StudentDeleteView.as_view(),name='student_delete')
I know my addition is not correct because each group of students should be related to a specific school. I am confused how to use id/pk in the url because for example student_detail.html url should contain both school id and student id.
sorry if this looks naive question.. but I am still learning and any help will be highly appreciated..
thanks
You could add another argument school_pk to the URL pattern, for example:
url(r'^school/(?P<school_pk>\d+)/update/(?P<pk>\d+)/$',views.StudentUpdateView.as_view(),name='student_update'),
Then filter the queryset to only include students from that school.
class StudentUpdateView(UpdateView):
def get_queryset(self):
queryset = super(StudentUpdateView, self).get_queryset()
return queryset.filter(school=self.kwargs['school_pk'])
The UpdateView will take care of fetching the student, because you're still using pk for the student pk.
You need to add 'student(s)' to the urls to make them distinct. You may not need to add school_id to student urls as they are related by ForeignKey
url(r'^students$',views.StudentListView.as_view(),
name='student_list'),
url(r'^student/(?P<pk>\d+)/$',views.StudentDetailView.as_view(),
name='student_detail'),
url(r'^student/create/$',views.StudentCreateView.as_view(),
name='student_create'),
url(r'^student/update/(?P<pk>\d+)/$',views.StudentUpdateView.as_view(),
name='student_update'),
url(r'^student/delete/(?P<pk>\d+)/$',views.StudentDeleteView.as_view(),
name='student_delete')

How to reference pk in DetailView

Hi i'm sure this had a simple solution but i cant find it! It must be required ALL the time!
To learn django i am writing simple app for me to log my learning points. So i have two models:
class Topic(models.Model):
title = models.CharField(max_length=40)
def __unicode__(self):
return self.title
class Meta():
ordering = ['title']
class Fact(models.Model):
note = models.CharField(max_length=255)
topic = models.ForeignKey('Topic')
def __unicode__(self):
return self.note
class Meta():
ordering = ['note']
I have template and url that will list ALL the topics.
When i see that list i want to be able to click on it [which i can do] and have that topic and all the facts linked to it (thourgh the foreign key appear) [would that technicaly be described as filtered query set of child objects?] I am using detailview.
url
url(r'^(?P<pk>\d+)/$', TopicDetailView.as_view(), name='facts'),
Here is the code of the detail view. Know i knows it knows the pk as it shows the right page when i take out the extracontext filter (and just take .all()). But i cant ref it no matter how many ways i try. I'd like something like this...
class TopicDetailView(DetailView):
model = Topic
template_name = 'study/topic_facts.html'
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super(TopicDetailView, self).get_context_data(**kwargs)
# Add in a QuerySet of all the books
context['fact_list'] = Fact.objects.filter(topic='pk')
return context
I can do this if i put some logic and a filter in the template but that doesn't seem very proper to me and i feel i must be able to do this easily by adding the right extra context.
Help some poor newbie out! Many Thanks.
'pk' is just a string. You mean self.kwargs['pk'].
But actually you don't want to do this at all. The super class already adds the Topic object to the context: and you have a relationship between Topic and Fact. You can traverse this relationship in the template:
{% for fact in topic.fact_set.all %}
...
{% endfor %}
so you don't need to override get_context_data.

How can I write to the instance on the parent class from a subclass in Django models?

Following on from this question...
I have two primary models for my blog, Article and Link, and both are subclasses of Post. Simplifying a little, they look something like this:
class Post(models.Model):
title = models.CharField(max_length=100)
body = models.TextField()
post_date = models.DateField(db_index=True, auto_now_add=True)
class Article(Post):
feature_image = models.FileField(upload_to='feature_images')
class Link(Post):
link = models.URLField(verify_exists=True)
I want to collect over both Articles and Links, so in my view, I run Post.objects.order_by('post_date') and presto, I get the whole list--but only with the fields that are on Post. If I want to use the link in a Link instance, I can't.
I have the primary key, so I should be able to do something like Link.objects.get(pk=item.pk) and be set--but I'd have to know if this was a Link or an Article.
Can I create a post_type property on the parent model and write to it with the correct model name from the children?
I solved this in a totally different way in the end, by writing a custom manager for Post:
class PostManager(models.Manager):
def __get_final(self, pk):
for k in Post.__subclasses__():
if k.objects.filter(pk=pk).exists():
return k.objects.get(pk=pk)
return None
def __subclass_queryset(self, qs):
collection = []
for item in qs:
collection.append(self.__get_final(item.pk))
return collection
def all(self):
return self.__subclass_queryset(super(PostManager, self).all())
Now Post.objects.all() (or any other QuerySet operation I add to the manager, like order_by), and I'll get back a list of all of the objects, with their full set of specific fields. (I then reset the manager on the subclasses, so they're not saddled with these extra queries for routine operations.)

django views - accessing a m2m field in a generic view

I've stumbled upon this issue and my noob brain got fried trying to resolve it. I feel like there's some basic concepts here that I'm missing.
So I have this "Films" model with category choice field and a m2m relationship to a "Directors" model, and I'm trying to write 2 different views, one that returns a list of films filtered by category and one that returns a list of films filtered by director.
The first one is easy, but I just don't know how to get the director model's name field to create the second filter.
So I have this models (i've taken the irrelevant stuff out including the category thing i mentioned above)
class Director(models.Model):
name = models.CharField(max_length=50)
web = models.URLField(blank=True, help_text= "opcional")
class Film(models.Model):
name = models.CharField(max_length=50)
slug = models.SlugField(max_length= 15)
director = models.ManyToManyField(Director, blank=True, help_text= "opcional")
this url
(r'^peliculas/director/(?P<director>\w+)/$', 'filtered_by_director'),
and this view
def filtered_by_director(request,director):
return list_detail.object_list(
request,
queryset = Film.objects.filter(director.name=director),
template_name ='sections/film_list.html',
template_object_name = 'film',
paginate_by = 3
)
The same template is supposed to be used by both views to render the relevant list of objects
The view doesn't like the filter i'm using at the queryset for the m2m field, but I have no clue how to do it really, I've tried whatever I could think of and it gives me a "keyword can't be an expression" error
Any help to this lowly noob will be appreciated.
Line queryset = Film.objects.filter(director.name=director),
needs to read: queryset = Film.objects.filter(director__name=director),
Field lookups are done by __ double underscore syntax:
http://docs.djangoproject.com/en/dev/topics/db/queries/#field-lookups
In your filter, try specifying the director name like (documentation):
filter(director__name=director)